Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}