• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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