/src/samba/third_party/ngtcp2/lib/ngtcp2_vec.c
Line | Count | Source |
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 | | |
32 | 0 | ngtcp2_vec *ngtcp2_vec_init(ngtcp2_vec *vec, const uint8_t *base, size_t len) { |
33 | 0 | *vec = (ngtcp2_vec){ |
34 | 0 | .base = (uint8_t *)base, |
35 | 0 | .len = len, |
36 | 0 | }; |
37 | |
|
38 | 0 | return vec; |
39 | 0 | } |
40 | | |
41 | 0 | uint64_t ngtcp2_vec_len(const ngtcp2_vec *vec, size_t n) { |
42 | 0 | size_t i; |
43 | 0 | size_t res = 0; |
44 | |
|
45 | 0 | for (i = 0; i < n; ++i) { |
46 | 0 | res += vec[i].len; |
47 | 0 | } |
48 | |
|
49 | 0 | return res; |
50 | 0 | } |
51 | | |
52 | 0 | int64_t ngtcp2_vec_len_varint(const ngtcp2_vec *vec, size_t n) { |
53 | 0 | uint64_t res = 0; |
54 | 0 | size_t len; |
55 | 0 | size_t i; |
56 | |
|
57 | 0 | for (i = 0; i < n; ++i) { |
58 | 0 | len = vec[i].len; |
59 | 0 | if (len > NGTCP2_MAX_VARINT - res) { |
60 | 0 | return -1; |
61 | 0 | } |
62 | | |
63 | 0 | res += len; |
64 | 0 | } |
65 | | |
66 | 0 | return (int64_t)res; |
67 | 0 | } |
68 | | |
69 | | ngtcp2_ssize ngtcp2_vec_split(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, |
70 | 0 | size_t *psrccnt, size_t left, size_t maxcnt) { |
71 | 0 | size_t i; |
72 | 0 | size_t srccnt = *psrccnt; |
73 | 0 | size_t nmove; |
74 | 0 | size_t extra = 0; |
75 | |
|
76 | 0 | for (i = 0; i < srccnt; ++i) { |
77 | 0 | if (left >= src[i].len) { |
78 | 0 | left -= src[i].len; |
79 | 0 | continue; |
80 | 0 | } |
81 | | |
82 | 0 | if (*pdstcnt && src[srccnt - 1].base + src[srccnt - 1].len == dst[0].base) { |
83 | 0 | if (*pdstcnt + srccnt - i - 1 > maxcnt) { |
84 | 0 | return -1; |
85 | 0 | } |
86 | | |
87 | 0 | dst[0].len += src[srccnt - 1].len; |
88 | 0 | dst[0].base = src[srccnt - 1].base; |
89 | 0 | extra = src[srccnt - 1].len; |
90 | 0 | --srccnt; |
91 | 0 | } else if (*pdstcnt + srccnt - i > maxcnt) { |
92 | 0 | return -1; |
93 | 0 | } |
94 | | |
95 | 0 | if (left == 0) { |
96 | 0 | *psrccnt = i; |
97 | 0 | } else { |
98 | 0 | *psrccnt = i + 1; |
99 | 0 | } |
100 | |
|
101 | 0 | nmove = srccnt - i; |
102 | 0 | if (nmove) { |
103 | 0 | memmove(dst + nmove, dst, sizeof(ngtcp2_vec) * (*pdstcnt)); |
104 | 0 | *pdstcnt += nmove; |
105 | 0 | memcpy(dst, src + i, sizeof(ngtcp2_vec) * nmove); |
106 | 0 | } |
107 | |
|
108 | 0 | ngtcp2_vec_drop(&dst[0], left); |
109 | 0 | src[i].len = left; |
110 | |
|
111 | 0 | if (nmove == 0) { |
112 | 0 | extra -= left; |
113 | 0 | } |
114 | |
|
115 | 0 | return (ngtcp2_ssize)(ngtcp2_vec_len(dst, nmove) + extra); |
116 | 0 | } |
117 | | |
118 | 0 | return 0; |
119 | 0 | } |
120 | | |
121 | | size_t ngtcp2_vec_merge(ngtcp2_vec *dst, size_t *pdstcnt, ngtcp2_vec *src, |
122 | 0 | size_t *psrccnt, size_t left, size_t maxcnt) { |
123 | 0 | size_t orig_left = left; |
124 | 0 | size_t i = 0; |
125 | 0 | ngtcp2_vec *a, *b; |
126 | |
|
127 | 0 | assert(maxcnt); |
128 | |
|
129 | 0 | if (*pdstcnt == 0) { |
130 | 0 | if (*psrccnt == 0) { |
131 | 0 | return 0; |
132 | 0 | } |
133 | | |
134 | 0 | a = &dst[0]; |
135 | 0 | b = &src[0]; |
136 | |
|
137 | 0 | if (left < b->len) { |
138 | 0 | a->len = left; |
139 | 0 | a->base = b->base; |
140 | |
|
141 | 0 | ngtcp2_vec_drop(b, left); |
142 | |
|
143 | 0 | return left; |
144 | 0 | } |
145 | | |
146 | 0 | *a = *b; |
147 | 0 | ++*pdstcnt; |
148 | 0 | left -= b->len; |
149 | 0 | i = 1; |
150 | 0 | } |
151 | | |
152 | 0 | for (; left && i < *psrccnt; ++i) { |
153 | 0 | a = &dst[*pdstcnt - 1]; |
154 | 0 | b = &src[i]; |
155 | |
|
156 | 0 | if (left < b->len) { |
157 | 0 | if (a->base + a->len == b->base) { |
158 | 0 | a->len += left; |
159 | 0 | } else if (*pdstcnt == maxcnt) { |
160 | 0 | break; |
161 | 0 | } else { |
162 | 0 | dst[*pdstcnt] = (ngtcp2_vec){ |
163 | 0 | .base = b->base, |
164 | 0 | .len = left, |
165 | 0 | }; |
166 | 0 | ++*pdstcnt; |
167 | 0 | } |
168 | | |
169 | 0 | ngtcp2_vec_drop(b, left); |
170 | 0 | left = 0; |
171 | |
|
172 | 0 | break; |
173 | 0 | } |
174 | | |
175 | 0 | if (a->base + a->len == b->base) { |
176 | 0 | a->len += b->len; |
177 | 0 | } else if (*pdstcnt == maxcnt) { |
178 | 0 | break; |
179 | 0 | } else { |
180 | 0 | dst[(*pdstcnt)++] = *b; |
181 | 0 | } |
182 | | |
183 | 0 | left -= b->len; |
184 | 0 | } |
185 | |
|
186 | 0 | memmove(src, src + i, sizeof(ngtcp2_vec) * (*psrccnt - i)); |
187 | 0 | *psrccnt -= i; |
188 | |
|
189 | 0 | return orig_left - left; |
190 | 0 | } |
191 | | |
192 | | size_t ngtcp2_vec_copy_at_most(ngtcp2_vec *dst, size_t dstcnt, |
193 | | const ngtcp2_vec *src, size_t srccnt, |
194 | 0 | size_t left) { |
195 | 0 | size_t i, j; |
196 | |
|
197 | 0 | for (i = 0, j = 0; left > 0 && i < srccnt && j < dstcnt;) { |
198 | 0 | if (src[i].len == 0) { |
199 | 0 | ++i; |
200 | 0 | continue; |
201 | 0 | } |
202 | | |
203 | 0 | if (src[i].len > left) { |
204 | 0 | dst[j] = (ngtcp2_vec){ |
205 | 0 | .base = src[i].base, |
206 | 0 | .len = left, |
207 | 0 | }; |
208 | |
|
209 | 0 | return j + 1; |
210 | 0 | } |
211 | | |
212 | 0 | dst[j] = src[i]; |
213 | 0 | left -= dst[j].len; |
214 | 0 | ++i; |
215 | 0 | ++j; |
216 | 0 | } |
217 | | |
218 | 0 | return j; |
219 | 0 | } |
220 | | |
221 | 0 | void ngtcp2_vec_copy(ngtcp2_vec *dst, const ngtcp2_vec *src, size_t cnt) { |
222 | 0 | memcpy(dst, src, sizeof(ngtcp2_vec) * cnt); |
223 | 0 | } |
224 | | |
225 | 0 | void ngtcp2_vec_split_at(ngtcp2_vec *dst, ngtcp2_vec *src, size_t offset) { |
226 | 0 | assert(offset < src->len); |
227 | |
|
228 | 0 | *dst = (ngtcp2_vec){ |
229 | 0 | .base = src->base + offset, |
230 | 0 | .len = src->len - offset, |
231 | 0 | }; |
232 | |
|
233 | 0 | src->len = offset; |
234 | 0 | } |