1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2018 ngtcp2 contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "ngtcp2_vec.h"
26
27 #include <string.h>
28 #include <assert.h>
29
30 #include "ngtcp2_str.h"
31
ngtcp2_vec_init(ngtcp2_vec * vec,const uint8_t * base,size_t len)32 ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) {
33 vec->base = (uint8_t *)base;
34 vec->len = len;
35 return vec;
36 }
37
ngtcp2_vec_new(ngtcp2_vec ** pvec,const uint8_t * data,size_t datalen,const ngtcp2_mem * mem)38 int ngtcp2_vec_new(ngtcp2_vec **pvec, const uint8_t *data, size_t datalen,
39 const ngtcp2_mem *mem) {
40 size_t len;
41 uint8_t *p;
42
43 len = sizeof(ngtcp2_vec) + datalen;
44
45 *pvec = ngtcp2_mem_malloc(mem, len);
46 if (*pvec == NULL) {
47 return NGTCP2_ERR_NOMEM;
48 }
49
50 p = (uint8_t *)(*pvec) + sizeof(ngtcp2_vec);
51 (*pvec)->base = p;
52 (*pvec)->len = datalen;
53 if (datalen) {
54 /* p = */ ngtcp2_cpymem(p, data, datalen);
55 }
56
57 return 0;
58 }
59
ngtcp2_vec_del(ngtcp2_vec * vec,const ngtcp2_mem * mem)60 void ngtcp2_vec_del(ngtcp2_vec *vec, const ngtcp2_mem *mem) {
61 ngtcp2_mem_free(mem, vec);
62 }
63
ngtcp2_vec_len(const ngtcp2_vec * vec,size_t n)64 uint64_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n) {
65 size_t i;
66 size_t res = 0;
67
68 for (i = 0; i < n; ++i) {
69 res += vec[i].len;
70 }
71
72 return res;
73 }
74
ngtcp2_vec_len_varint(const ngtcp2_vec * vec,size_t n)75 int64_t ngtcp2_vec_len_varint(const ngtcp2_vec *vec, size_t n) {
76 uint64_t res = 0;
77 size_t len;
78 size_t i;
79
80 for (i = 0; i < n; ++i) {
81 len = vec[i].len;
82 if (len > NGTCP2_MAX_VARINT - res) {
83 return -1;
84 }
85
86 res += len;
87 }
88
89 return (int64_t)res;
90 }
91
ngtcp2_vec_split(ngtcp2_vec * src,size_t * psrccnt,ngtcp2_vec * dst,size_t * pdstcnt,size_t left,size_t maxcnt)92 ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *src, size_t *psrccnt, ngtcp2_vec *dst,
93 size_t *pdstcnt, size_t left, size_t maxcnt) {
94 size_t i;
95 size_t srccnt = *psrccnt;
96 size_t nmove;
97 size_t extra = 0;
98
99 for (i = 0; i < srccnt; ++i) {
100 if (left >= src[i].len) {
101 left -= src[i].len;
102 continue;
103 }
104
105 if (*pdstcnt && src[srccnt - 1].base + src[srccnt - 1].len == dst[0].base) {
106 if (*pdstcnt + srccnt - i - 1 > maxcnt) {
107 return -1;
108 }
109
110 dst[0].len += src[srccnt - 1].len;
111 dst[0].base = src[srccnt - 1].base;
112 extra = src[srccnt - 1].len;
113 --srccnt;
114 } else if (*pdstcnt + srccnt - i > maxcnt) {
115 return -1;
116 }
117
118 if (left == 0) {
119 *psrccnt = i;
120 } else {
121 *psrccnt = i + 1;
122 }
123
124 nmove = srccnt - i;
125 if (nmove) {
126 memmove(dst + nmove, dst, sizeof(ngtcp2_vec) * (*pdstcnt));
127 *pdstcnt += nmove;
128 memcpy(dst, src + i, sizeof(ngtcp2_vec) * nmove);
129 }
130
131 dst[0].len -= left;
132 dst[0].base += left;
133 src[i].len = left;
134
135 if (nmove == 0) {
136 extra -= left;
137 }
138
139 return (ngtcp2_ssize)(ngtcp2_vec_len(dst, nmove) + extra);
140 }
141
142 return 0;
143 }
144
ngtcp2_vec_merge(ngtcp2_vec * dst,size_t * pdstcnt,ngtcp2_vec * src,size_t * psrccnt,size_t left,size_t maxcnt)145 size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src,
146 size_t *psrccnt, size_t left, size_t maxcnt) {
147 size_t orig_left = left;
148 size_t i;
149 ngtcp2_vec *a, *b;
150
151 assert(maxcnt);
152
153 if (*pdstcnt == 0) {
154 if (*psrccnt == 0) {
155 return 0;
156 }
157
158 a = &dst[0];
159 b = &src[0];
160
161 if (left >= b->len) {
162 *a = *b;
163 ++*pdstcnt;
164 left -= b->len;
165 i = 1;
166 } else {
167 a->len = left;
168 a->base = b->base;
169
170 b->len -= left;
171 b->base += left;
172
173 return left;
174 }
175 } else {
176 i = 0;
177 }
178
179 for (; left && i < *psrccnt; ++i) {
180 a = &dst[*pdstcnt - 1];
181 b = &src[i];
182
183 if (left >= b->len) {
184 if (a->base + a->len == b->base) {
185 a->len += b->len;
186 } else if (*pdstcnt == maxcnt) {
187 break;
188 } else {
189 dst[(*pdstcnt)++] = *b;
190 }
191 left -= b->len;
192 continue;
193 }
194
195 if (a->base + a->len == b->base) {
196 a->len += left;
197 } else if (*pdstcnt == maxcnt) {
198 break;
199 } else {
200 dst[*pdstcnt].len = left;
201 dst[*pdstcnt].base = b->base;
202 ++*pdstcnt;
203 }
204
205 b->len -= left;
206 b->base += left;
207 left = 0;
208
209 break;
210 }
211
212 memmove(src, src + i, sizeof(ngtcp2_vec) * (*psrccnt - i));
213 *psrccnt -= i;
214
215 return orig_left - left;
216 }
217
ngtcp2_vec_copy_at_most(ngtcp2_vec * dst,size_t dstcnt,const ngtcp2_vec * src,size_t srccnt,size_t left)218 size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt,
219 const ngtcp2_vec *src, size_t srccnt,
220 size_t left) {
221 size_t i, j;
222
223 for (i = 0, j = 0; left > 0 && i < srccnt && j < dstcnt;) {
224 if (src[i].len == 0) {
225 ++i;
226 continue;
227 }
228 dst[j] = src[i];
229 if (dst[j].len > left) {
230 dst[j].len = left;
231 return j + 1;
232 }
233 left -= dst[j].len;
234 ++i;
235 ++j;
236 }
237
238 return j;
239 }
240
ngtcp2_vec_copy(ngtcp2_vec * dst,const ngtcp2_vec * src,size_t cnt)241 void ngtcp2_vec_copy(ngtcp2_vec *dst, const ngtcp2_vec *src, size_t cnt) {
242 memcpy(dst, src, sizeof(ngtcp2_vec) * cnt);
243 }
244