Coverage Report

Created: 2025-08-28 06:25

/src/haproxy/include/haproxy/vecpair.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * include/haproxy/vecpair.h
3
 * Vector pair handling - functions definitions.
4
 *
5
 * Copyright (C) 2000-2024 Willy Tarreau - w@1wt.eu
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining
8
 * a copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be
16
 * included in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
 * OTHER DEALINGS IN THE SOFTWARE.
26
 */
27
28
#ifndef _HAPROXY_VECPAIR_H
29
#define _HAPROXY_VECPAIR_H
30
31
#include <sys/types.h>
32
#include <string.h>
33
#include <import/ist.h>
34
#include <haproxy/api.h>
35
36
37
/* Principles of operation
38
 * -----------------------
39
 * These functions take two vectors represented as ISTs, they're each the
40
 * pointer to and the length of a work area. Functions operate over these
41
 * two areas as if they were a contiguous area. It is up to the caller to
42
 * use them to designate free space or data depending on whether it wants
43
 * to write or read to the area. This allows to easily represent a wrapping
44
 * buffer, both for data and free space.
45
 *
46
 * In order to ease sequencing of operations, most of the functions below
47
 * will:
48
 *   - always consider v1 before v2
49
 *   - always ignore any vector whose length is zero (the pointer is ignored)
50
 *   - automatically switch from v1 to v2 upon updates, including if their
51
 *     size is zero
52
 *   - end after both v1 and v2 are depleted (len==0)
53
 *   - update the affected vectors after operation (pointer, length) so that
54
 *     they can easily be chained without adding new tests
55
 *   - return the number of bytes processed after operation.
56
 *
57
 * These functions do not need to know the allocated size nor any such thing,
58
 * it's the caller's job to know that and to build the relevant vector pair.
59
 * See the vp_{ring,data,room}_to_{ring,data,room}() functions at the end for
60
 * this.
61
 */
62
63
/* vp_isempty(): returns true if both areas are empty */
64
static inline int vp_isempty(const struct ist v1, const struct ist v2)
65
0
{
66
0
  return !v1.len && !v2.len;
67
0
}
Unexecuted instantiation: errors.c:vp_isempty
Unexecuted instantiation: log.c:vp_isempty
Unexecuted instantiation: mworker.c:vp_isempty
Unexecuted instantiation: ring.c:vp_isempty
Unexecuted instantiation: sink.c:vp_isempty
Unexecuted instantiation: applet.c:vp_isempty
68
69
/* vp_size(): returns the total size of the two vectors */
70
static inline size_t vp_size(const struct ist v1, const struct ist v2)
71
0
{
72
0
  return v1.len + v2.len;
73
0
}
Unexecuted instantiation: errors.c:vp_size
Unexecuted instantiation: log.c:vp_size
Unexecuted instantiation: mworker.c:vp_size
Unexecuted instantiation: ring.c:vp_size
Unexecuted instantiation: sink.c:vp_size
Unexecuted instantiation: applet.c:vp_size
74
75
/* _vp_head() : returns the pointer to the head (beginning) of the area, which is
76
 * the address of the first byte of the first non-empty area. It must not be
77
 * called with both areas empty.
78
 */
79
static inline char *_vp_head(const struct ist v1, const struct ist v2)
80
0
{
81
0
  return v1.len ? v1.ptr : v2.ptr;
82
0
}
Unexecuted instantiation: errors.c:_vp_head
Unexecuted instantiation: log.c:_vp_head
Unexecuted instantiation: mworker.c:_vp_head
Unexecuted instantiation: ring.c:_vp_head
Unexecuted instantiation: sink.c:_vp_head
Unexecuted instantiation: applet.c:_vp_head
83
84
/* vp_head() : returns the pointer to the head (beginning) of the area, which is
85
 * the address of the first byte of the first non-empty area. It may return
86
 * NULL if both areas are empty.
87
 */
88
static inline char *vp_head(const struct ist v1, const struct ist v2)
89
0
{
90
0
  return v1.len ? v1.ptr : v2.len ? v2.ptr : NULL;
91
0
}
Unexecuted instantiation: errors.c:vp_head
Unexecuted instantiation: log.c:vp_head
Unexecuted instantiation: mworker.c:vp_head
Unexecuted instantiation: ring.c:vp_head
Unexecuted instantiation: sink.c:vp_head
Unexecuted instantiation: applet.c:vp_head
92
93
/* _vp_addr() : return the address corresponding to applying an offset <ofs>
94
 * after the head. It must not be called with an offset larger than the total
95
 * area size.
96
 */
97
static inline char *_vp_addr(const struct ist v1, const struct ist v2, size_t ofs)
98
0
{
99
0
  if (ofs < v1.len)
100
0
    return v1.ptr + ofs;
101
0
  else {
102
0
    ofs -= v1.len;
103
0
    return v2.ptr + ofs;
104
0
  }
105
0
}
Unexecuted instantiation: errors.c:_vp_addr
Unexecuted instantiation: log.c:_vp_addr
Unexecuted instantiation: mworker.c:_vp_addr
Unexecuted instantiation: ring.c:_vp_addr
Unexecuted instantiation: sink.c:_vp_addr
Unexecuted instantiation: applet.c:_vp_addr
106
107
/* vp_addr() : return the address corresponding to applying an offset <ofs>
108
 * after the head. It may return NULL if the length is beyond the total area
109
 * size.
110
 */
111
static inline char *vp_addr(const struct ist v1, const struct ist v2, size_t ofs)
112
0
{
113
0
  if (ofs < v1.len)
114
0
    return v1.ptr + ofs;
115
0
  else {
116
0
    ofs -= v1.len;
117
0
    if (ofs >= v2.len)
118
0
      return NULL;
119
0
    return v2.ptr + ofs;
120
0
  }
121
0
}
Unexecuted instantiation: errors.c:vp_addr
Unexecuted instantiation: log.c:vp_addr
Unexecuted instantiation: mworker.c:vp_addr
Unexecuted instantiation: ring.c:vp_addr
Unexecuted instantiation: sink.c:vp_addr
Unexecuted instantiation: applet.c:vp_addr
122
123
/* vp_ofs() : return the offset corresponding to the pointer <p> within either
124
 * v1 or v2, or a size equal to the sum of both lengths if <p> is outside both
125
 * areas.
126
 */
127
static inline size_t vp_ofs(const struct ist v1, const struct ist v2, const char *p)
128
0
{
129
0
  if (p >= v1.ptr && p < v1.ptr + v1.len)
130
0
    return p - v1.ptr;
131
0
132
0
  if (p >= v2.ptr && p < v2.ptr + v2.len)
133
0
    return v1.len + (p - v2.ptr);
134
0
135
0
  return v1.len + v2.len;
136
0
}
Unexecuted instantiation: errors.c:vp_ofs
Unexecuted instantiation: log.c:vp_ofs
Unexecuted instantiation: mworker.c:vp_ofs
Unexecuted instantiation: ring.c:vp_ofs
Unexecuted instantiation: sink.c:vp_ofs
Unexecuted instantiation: applet.c:vp_ofs
137
138
/* vp_next() : return the address of the next character after <p> or NULL if it
139
 * runs out of both v1 and v2.
140
 */
141
static inline char *vp_next(const struct ist v1, const struct ist v2, const char *p)
142
0
{
143
0
  size_t ofs = vp_ofs(v1, v2, p);
144
0
145
0
  return vp_addr(v1, v2, ofs + 1);
146
0
}
Unexecuted instantiation: errors.c:vp_next
Unexecuted instantiation: log.c:vp_next
Unexecuted instantiation: mworker.c:vp_next
Unexecuted instantiation: ring.c:vp_next
Unexecuted instantiation: sink.c:vp_next
Unexecuted instantiation: applet.c:vp_next
147
148
/* vp_seek_addr() : return the pointer to the byte at relative offset <seek> in
149
 * the area(s). The caller must ensure that seek is strictly smaller than the
150
 * total amount of bytes in the vectors.
151
 */
152
static inline char *vp_seek_addr(struct ist v1, struct ist v2, size_t seek)
153
0
{
154
0
  if (seek < v1.len)
155
0
    return v1.ptr + seek;
156
0
  else
157
0
    return v2.ptr + seek - v1.len;
158
0
}
Unexecuted instantiation: errors.c:vp_seek_addr
Unexecuted instantiation: log.c:vp_seek_addr
Unexecuted instantiation: mworker.c:vp_seek_addr
Unexecuted instantiation: ring.c:vp_seek_addr
Unexecuted instantiation: sink.c:vp_seek_addr
Unexecuted instantiation: applet.c:vp_seek_addr
159
160
/*********************************************/
161
/* Functions used to modify the buffer state */
162
/*********************************************/
163
164
/* vp_skip() : skip the requested amount of bytes from the area(s) and update
165
 * them accordingly. If the amount to skip exceeds the total size of the two
166
 * areas, they're emptied and the total number of emptied bytes is returned.
167
 * It is unspecified what area pointers point to after their len is emptied.
168
 */
169
static inline size_t vp_skip(struct ist *v1, struct ist *v2, size_t skip)
170
0
{
171
0
  if (skip <= v1->len) {
172
0
    v1->ptr += skip;
173
0
    v1->len -= skip;
174
0
  }
175
0
  else {
176
0
    if (skip > v1->len + v2->len)
177
0
      skip = v1->len + v2->len;
178
179
0
    v2->ptr += skip - v1->len;
180
0
    v2->len -= skip - v1->len;
181
0
    v1->ptr += v1->len;
182
0
    v1->len  = 0;
183
0
  }
184
0
  return skip;
185
0
}
Unexecuted instantiation: errors.c:vp_skip
Unexecuted instantiation: log.c:vp_skip
Unexecuted instantiation: mworker.c:vp_skip
Unexecuted instantiation: ring.c:vp_skip
Unexecuted instantiation: sink.c:vp_skip
Unexecuted instantiation: applet.c:vp_skip
186
187
/* vp_getchr() : tries to retrieve the next from the beginning of the area, and
188
 * advance the beginning by one char on success. An int equal to the unsigned
189
 * char is returned on success, otherwise a negative value if there is nothing
190
 * left in the area.
191
 */
192
static inline int vp_getchr(struct ist *v1, struct ist *v2)
193
0
{
194
0
  int c = -1;
195
0
196
0
  if (v1->len) {
197
0
    v1->len--;
198
0
    c = (unsigned char)*(v1->ptr++);
199
0
  }
200
0
  else if (v2->len) {
201
0
    v2->len--;
202
0
    c = (unsigned char)*(v2->ptr++);
203
0
  }
204
0
205
0
  return c;
206
0
}
Unexecuted instantiation: errors.c:vp_getchr
Unexecuted instantiation: log.c:vp_getchr
Unexecuted instantiation: mworker.c:vp_getchr
Unexecuted instantiation: ring.c:vp_getchr
Unexecuted instantiation: sink.c:vp_getchr
Unexecuted instantiation: applet.c:vp_getchr
207
208
/* vp_getblk_ofs() : gets one full block of data at once from a pair of vectors,
209
 * starting from offset <ofs> after the head, and for up to <len> bytes. The
210
 * caller is responsible for ensuring that <ofs> does not exceed the total
211
 * number of bytes available in the areas. The areas will then be updated so
212
 * that the next head points to the first unread byte (i.e. skip <ofs> plus
213
 * the number of bytes returned). The number of bytes copied is returned. This
214
 * is meant to be used on concurrently accessed areas, so that a reader can
215
 * read a known area while it is been concurrently fed and/or trimmed. Usually
216
 * you'd prefer to use the more convenient vp_getblk() or vp_peek_ofs().
217
 */
218
static inline size_t vp_getblk_ofs(struct ist *v1, struct ist *v2, size_t ofs, char *blk, size_t len)
219
0
{
220
0
  size_t ret = 0;
221
0
  size_t block;
222
223
0
  BUG_ON_HOT(ofs >= v1->len + v2->len);
224
225
0
  vp_skip(v1, v2, ofs);
226
227
0
  block = v1->len;
228
0
  if (block > len)
229
0
    block = len;
230
231
0
  if (block) {
232
0
    memcpy(blk + ret, v1->ptr, block);
233
0
    v1->ptr += block;
234
0
    v1->len -= block;
235
0
    ret += block;
236
0
    len -= block;
237
0
  }
238
239
0
  block = v2->len;
240
0
  if (block > len)
241
0
    block = len;
242
243
0
  if (block) {
244
0
    memcpy(blk + ret, v2->ptr, block);
245
0
    v2->ptr += block;
246
0
    v2->len -= block;
247
0
    ret += block;
248
0
  }
249
250
0
  return ret;
251
0
}
Unexecuted instantiation: errors.c:vp_getblk_ofs
Unexecuted instantiation: log.c:vp_getblk_ofs
Unexecuted instantiation: mworker.c:vp_getblk_ofs
Unexecuted instantiation: ring.c:vp_getblk_ofs
Unexecuted instantiation: sink.c:vp_getblk_ofs
Unexecuted instantiation: applet.c:vp_getblk_ofs
252
253
/* vp_getblk() : gets one full block of data at once from a pair of vectors,
254
 * starting from their head, and for up to <len> bytes. The areas will be
255
 * updated so that the next head points to the first unread byte. The number
256
 * of bytes copied is returned.  This is meant to be used on concurrently
257
 * accessed areas, so that a reader can read a known area while it is been
258
 * concurrently fed and/or trimmed. See also vp_peek_ofs().
259
 */
260
static inline size_t vp_getblk(struct ist *v1, struct ist *v2, char *blk, size_t len)
261
0
{
262
0
  return vp_getblk_ofs(v1, v2, 0, blk, len);
263
0
}
Unexecuted instantiation: errors.c:vp_getblk
Unexecuted instantiation: log.c:vp_getblk
Unexecuted instantiation: mworker.c:vp_getblk
Unexecuted instantiation: ring.c:vp_getblk
Unexecuted instantiation: sink.c:vp_getblk
Unexecuted instantiation: applet.c:vp_getblk
264
265
/* vp_peek() : gets one full block of data at once from a pair of vectors,
266
 * starting from offset <ofs> after the head, and for up to <len> bytes.
267
 * The caller is responsible for ensuring that <ofs> does not exceed the
268
 * total number of bytes available in the areas. The areas are *not* updated.
269
 * The number of bytes copied is returned. This is meant to be used on
270
 * concurrently accessed areas, so that a reader can read a known area while
271
 * it is been concurrently fed and/or trimmed. See also vp_getblk().
272
 */
273
static inline size_t vp_peek_ofs(struct ist v1, struct ist v2, size_t ofs, char *blk, size_t len)
274
0
{
275
0
  return vp_getblk_ofs(&v1, &v2, ofs, blk, len);
276
0
}
Unexecuted instantiation: errors.c:vp_peek_ofs
Unexecuted instantiation: log.c:vp_peek_ofs
Unexecuted instantiation: mworker.c:vp_peek_ofs
Unexecuted instantiation: ring.c:vp_peek_ofs
Unexecuted instantiation: sink.c:vp_peek_ofs
Unexecuted instantiation: applet.c:vp_peek_ofs
277
278
/* vp_putchr() : tries to append char <c> at the beginning of the area, and
279
 * advance the beginning by one char. Data are truncated if there is no room
280
 * left.
281
 */
282
static inline void vp_putchr(struct ist *v1, struct ist *v2, char c)
283
0
{
284
0
  if (v1->len) {
285
0
    v1->len--;
286
0
    *(v1->ptr++) = c;
287
0
  }
288
0
  else if (v2->len) {
289
0
    v2->len--;
290
0
    *(v2->ptr++) = c;
291
0
  }
292
0
}
Unexecuted instantiation: errors.c:vp_putchr
Unexecuted instantiation: log.c:vp_putchr
Unexecuted instantiation: mworker.c:vp_putchr
Unexecuted instantiation: ring.c:vp_putchr
Unexecuted instantiation: sink.c:vp_putchr
Unexecuted instantiation: applet.c:vp_putchr
293
294
/* vp_putblk_ofs() : put one full block of data at once into a pair of vectors,
295
 * starting from offset <ofs> after the head, and for exactly <len> bytes.
296
 * The caller is responsible for ensuring that <ofs> does not exceed the total
297
 * number of bytes available in the areas. The function will check that it is
298
 * indeed possible to put <len> bytes after <ofs> before proceeding. If the
299
 * areas can accept such data, they will then be updated so that the next
300
 * head points to the first untouched byte (i.e. skip <ofs> plus the number
301
 * of bytes sent). The number of bytes copied is returned on success, or 0 is
302
 * returned if it cannot be copied, in which case the areas are left
303
 * untouched. This is meant to be used on concurrently accessed areas, so that
304
 * a reader can read a known area while it is been concurrently fed and/or
305
 * trimmed. Usually you'd prefer to use the more convenient vp_putblk() or
306
 * vp_poke_ofs().
307
 */
308
static inline size_t vp_putblk_ofs(struct ist *v1, struct ist *v2, size_t ofs, const char *blk, size_t len)
309
0
{
310
0
  size_t ret = 0;
311
0
  size_t block;
312
313
0
  BUG_ON_HOT(ofs >= v1->len + v2->len);
314
315
0
  if (len && ofs + len <= v1->len + v2->len) {
316
0
    vp_skip(v1, v2, ofs);
317
318
0
    block = v1->len;
319
0
    if (block > len)
320
0
      block = len;
321
322
0
    if (block) {
323
0
      memcpy(v1->ptr, blk + ret, block);
324
0
      v1->ptr += block;
325
0
      v1->len -= block;
326
0
      ret += block;
327
0
      len -= block;
328
0
    }
329
330
0
    block = v2->len;
331
0
    if (block > len)
332
0
      block = len;
333
334
0
    if (block) {
335
0
      memcpy(v2->ptr, blk + ret, block);
336
0
      v2->ptr += block;
337
0
      v2->len -= block;
338
0
      ret += block;
339
0
    }
340
0
  }
341
0
  return ret;
342
0
}
Unexecuted instantiation: errors.c:vp_putblk_ofs
Unexecuted instantiation: log.c:vp_putblk_ofs
Unexecuted instantiation: mworker.c:vp_putblk_ofs
Unexecuted instantiation: ring.c:vp_putblk_ofs
Unexecuted instantiation: sink.c:vp_putblk_ofs
Unexecuted instantiation: applet.c:vp_putblk_ofs
343
344
/* vp_pokeblk() : puts one full block of data at once into a pair of vectors,
345
 * starting from offset <ofs> after the head, and for exactly <len> bytes.
346
 * The caller is responsible for ensuring that neither <ofs> nor <ofs> + <len>
347
 * exceed the total number of bytes available in the areas. This is meant to
348
 * be used on concurrently accessed areas, so that a reader can read a known
349
 * area while* it is been concurrently fed and/or trimmed. The area pointers
350
 * are left unaffected. The number of bytes copied is returned.
351
 */
352
static inline size_t vp_poke_ofs(struct ist v1, struct ist v2, size_t ofs, const char *blk, size_t len)
353
0
{
354
0
  return vp_putblk_ofs(&v1, &v2, ofs, blk, len);
355
0
}
Unexecuted instantiation: errors.c:vp_poke_ofs
Unexecuted instantiation: log.c:vp_poke_ofs
Unexecuted instantiation: mworker.c:vp_poke_ofs
Unexecuted instantiation: ring.c:vp_poke_ofs
Unexecuted instantiation: sink.c:vp_poke_ofs
Unexecuted instantiation: applet.c:vp_poke_ofs
356
357
/* vp_putblk() : put one full block of data at once into a pair of vectors,
358
 * starting at the head, and for exactly <len> bytes. The caller is
359
 * responsible for ensuring that <len> does not exceed the total number of
360
 * bytes available in the areas. This is meant to be used on concurrently
361
 * accessed areas, so that a reader can read a known area while it is been
362
 * concurrently fed and/or trimmed. The area pointers are updated according to
363
 * the amount of bytes copied. The number of bytes copied is returned.
364
 */
365
static inline size_t vp_putblk(struct ist *v1, struct ist *v2, const char *blk, size_t len)
366
0
{
367
0
  vp_putblk_ofs(v1, v2, 0, blk, len);
368
0
  return len;
369
0
}
Unexecuted instantiation: errors.c:vp_putblk
Unexecuted instantiation: log.c:vp_putblk
Unexecuted instantiation: mworker.c:vp_putblk
Unexecuted instantiation: ring.c:vp_putblk
Unexecuted instantiation: sink.c:vp_putblk
Unexecuted instantiation: applet.c:vp_putblk
370
371
/* vp_put_varint_ofs(): encode 64-bit value <v> as a varint into a pair of
372
 * vectors, starting at an offset after the head. The code assumes that the
373
 * caller has checked that the encoded value fits in the areas so that there
374
 * are no length checks inside the loop. Vectors are updated and the number of
375
 * written bytes is returned (excluding the offset).
376
 */
377
static inline size_t vp_put_varint_ofs(struct ist *v1, struct ist *v2, size_t ofs, uint64_t v)
378
0
{
379
0
  size_t data = 0;
380
381
0
  BUG_ON_HOT(ofs >= v1->len + v2->len);
382
383
0
  vp_skip(v1, v2, ofs);
384
385
0
  if (v >= 0xF0) {
386
    /* more than one byte, first write the 4 least significant
387
     * bits, then follow with 7 bits per byte.
388
     */
389
0
    vp_putchr(v1, v2, v | 0xF0);
390
0
    v = (v - 0xF0) >> 4;
391
392
0
    while (1) {
393
0
      data++;
394
0
      if (v < 0x80)
395
0
        break;
396
0
      vp_putchr(v1, v2, v | 0x80);
397
0
      v = (v - 0x80) >> 7;
398
0
    }
399
0
  }
400
401
  /* last byte */
402
0
  vp_putchr(v1, v2, v);
403
0
  data++;
404
0
  return data;
405
0
}
Unexecuted instantiation: errors.c:vp_put_varint_ofs
Unexecuted instantiation: log.c:vp_put_varint_ofs
Unexecuted instantiation: mworker.c:vp_put_varint_ofs
Unexecuted instantiation: ring.c:vp_put_varint_ofs
Unexecuted instantiation: sink.c:vp_put_varint_ofs
Unexecuted instantiation: applet.c:vp_put_varint_ofs
406
407
/* vp_put_varint(): encode 64-bit value <v> as a varint into a pair of vectors,
408
 * starting at the head. The code assumes that the caller has checked that
409
 * the encoded value fits in the areas so that there are no length checks
410
 * inside the loop. Vectors are updated and the number of written bytes is
411
 * returned.
412
 */
413
static inline size_t vp_put_varint(struct ist *v1, struct ist *v2, uint64_t v)
414
0
{
415
0
  return vp_put_varint_ofs(v1, v2, 0, v);
416
0
}
Unexecuted instantiation: errors.c:vp_put_varint
Unexecuted instantiation: log.c:vp_put_varint
Unexecuted instantiation: mworker.c:vp_put_varint
Unexecuted instantiation: ring.c:vp_put_varint
Unexecuted instantiation: sink.c:vp_put_varint
Unexecuted instantiation: applet.c:vp_put_varint
417
418
/* vp_get_varint_ofs(): try to decode a varint from a pair of vectors, starting
419
 * at offset <ofs> after the head, into value <vptr>. Returns the number of
420
 * bytes parsed in case of success, or 0 if there were not enough bytes, in
421
 * which case the contents of <vptr> are not updated. Vectors are updated to
422
 * skip the offset and the number of bytes parsed if there are enough bytes,
423
 * otherwise the parsing area is left untouched. The code assumes the caller
424
 * has checked that the offset is smaller than or equal to the number of bytes
425
 * in the vectors.
426
 */
427
static inline size_t vp_get_varint_ofs(struct ist *v1, struct ist *v2, size_t ofs, uint64_t *vptr)
428
0
{
429
0
  size_t data = v1->len + v2->len;
430
0
  const char *head, *wrap;
431
0
  uint64_t v = 0;
432
0
  int bits = 0;
433
0
  size_t ret;
434
435
0
  BUG_ON_HOT(ofs > data);
436
437
0
  vp_skip(v1, v2, ofs);
438
439
  /* let's see where we start from. The wrapping area only concerns the
440
   * end of the first area, even if it's empty it does not overlap with
441
   * the second one so we don't care about v1 being set or not.
442
   */
443
0
  head = v1->len ? v1->ptr : v2->ptr;
444
0
  wrap = v1->ptr + v1->len;
445
0
  data -= ofs;
446
447
0
  if (data != 0 && ((uint8_t)*head >= 0xF0)) {
448
0
    v = (uint8_t)*head;
449
0
    bits += 4;
450
0
    while (1) {
451
0
      if (++head == wrap)
452
0
        head = v2->ptr;
453
0
      data--;
454
0
      if (!data || !(*head & 0x80))
455
0
        break;
456
0
      v += (uint64_t)(uint8_t)*head << bits;
457
0
      bits += 7;
458
0
    }
459
0
  }
460
461
  /* last byte */
462
0
  if (!data)
463
0
    return 0;
464
465
0
  v += (uint64_t)(uint8_t)*head << bits;
466
0
  *vptr = v;
467
0
  data--;
468
469
0
  ret = v1->len + v2->len - data;
470
0
  vp_skip(v1, v2, ret);
471
0
  return ret;
472
0
}
Unexecuted instantiation: errors.c:vp_get_varint_ofs
Unexecuted instantiation: log.c:vp_get_varint_ofs
Unexecuted instantiation: mworker.c:vp_get_varint_ofs
Unexecuted instantiation: ring.c:vp_get_varint_ofs
Unexecuted instantiation: sink.c:vp_get_varint_ofs
Unexecuted instantiation: applet.c:vp_get_varint_ofs
473
474
/* vp_get_varint(): try to decode a varint from a pair of vectors, starting at
475
 * the head, into value <vptr>. Returns the number of bytes parsed in case of
476
 * success, or 0 if there were not enough bytes, in which case the contents of
477
 * <vptr> are not updated. Vectors are updated to skip the bytes parsed if
478
 * there are enough bytes, otherwise they're left untouched.
479
 */
480
static inline size_t vp_get_varint(struct ist *v1, struct ist *v2, uint64_t *vptr)
481
0
{
482
0
  return vp_get_varint_ofs(v1, v2, 0, vptr);
483
0
}
Unexecuted instantiation: errors.c:vp_get_varint
Unexecuted instantiation: log.c:vp_get_varint
Unexecuted instantiation: mworker.c:vp_get_varint
Unexecuted instantiation: ring.c:vp_get_varint
Unexecuted instantiation: sink.c:vp_get_varint
Unexecuted instantiation: applet.c:vp_get_varint
484
485
/* vp_peek_varint_ofs(): try to decode a varint from a pair of vectors, starting at
486
 * the head, into value <vptr>. Returns the number of bytes parsed in case of
487
 * success, or 0 if there were not enough bytes, in which case the contents of
488
 * <vptr> are not updated.
489
 */
490
static inline size_t vp_peek_varint_ofs(struct ist v1, struct ist v2, size_t ofs, uint64_t *vptr)
491
0
{
492
0
  return vp_get_varint_ofs(&v1, &v2, ofs, vptr);
493
0
}
Unexecuted instantiation: errors.c:vp_peek_varint_ofs
Unexecuted instantiation: log.c:vp_peek_varint_ofs
Unexecuted instantiation: mworker.c:vp_peek_varint_ofs
Unexecuted instantiation: ring.c:vp_peek_varint_ofs
Unexecuted instantiation: sink.c:vp_peek_varint_ofs
Unexecuted instantiation: applet.c:vp_peek_varint_ofs
494
495
496
/************************************************************/
497
/* ring-buffer API                                          */
498
/* This is used to manipulate rings made of (head,tail)     */
499
/* It creates vectors for reading (data) and writing (room) */
500
/************************************************************/
501
502
/* build 2 vectors <v1> and <v2> corresponding to the available data in ring
503
 * buffer of size <size>, starting at address <area>, with a head <head> and
504
 * a tail <tail>. <v2> is non-empty only if the data wraps (i.e. tail<head).
505
 */
506
static inline void vp_ring_to_data(struct ist *v1, struct ist *v2, char *area, size_t size, size_t head, size_t tail)
507
0
{
508
0
  v1->ptr = area + head;
509
0
  v1->len = ((head <= tail) ? tail : size) - head;
510
0
  v2->ptr = area;
511
0
  v2->len = (tail < head) ? tail : 0;
512
0
}
Unexecuted instantiation: errors.c:vp_ring_to_data
Unexecuted instantiation: log.c:vp_ring_to_data
Unexecuted instantiation: mworker.c:vp_ring_to_data
Unexecuted instantiation: ring.c:vp_ring_to_data
Unexecuted instantiation: sink.c:vp_ring_to_data
Unexecuted instantiation: applet.c:vp_ring_to_data
513
514
/* build 2 vectors <v1> and <v2> corresponding to the available room in ring
515
 * buffer of size <size>, starting at address <area>, with a head <head> and
516
 * a tail <tail>. <v2> is non-empty only if the room wraps (i.e. head>tail).
517
 */
518
static inline void vp_ring_to_room(struct ist *v1, struct ist *v2, char *area, size_t size, size_t head, size_t tail)
519
0
{
520
0
  v1->ptr = area + tail;
521
0
  v1->len = ((tail <= head) ? head : size) - tail;
522
0
  v2->ptr = area;
523
0
  v2->len = (head < tail) ? head : 0;
524
0
}
Unexecuted instantiation: errors.c:vp_ring_to_room
Unexecuted instantiation: log.c:vp_ring_to_room
Unexecuted instantiation: mworker.c:vp_ring_to_room
Unexecuted instantiation: ring.c:vp_ring_to_room
Unexecuted instantiation: sink.c:vp_ring_to_room
Unexecuted instantiation: applet.c:vp_ring_to_room
525
526
/* Set a ring's <head> and <tail> according to the data area represented by the
527
 * concatenation of <v1> and <v2> which must point to two adjacent areas within
528
 * a ring buffer of <size> bytes starting at <area>. <v1>, if not empty, starts
529
 * at the head and <v2>, if not empty, ends at the tail. If both vectors are of
530
 * length zero, the ring is considered empty and both its head and tail will be
531
 * reset.
532
 */
533
static inline void vp_data_to_ring(const struct ist v1, const struct ist v2, char *area, size_t size, size_t *head, size_t *tail)
534
0
{
535
0
  size_t ofs;
536
537
0
  if (!v1.len && !v2.len) {
538
0
    *head = *tail = 0;
539
0
    return;
540
0
  }
541
542
0
  ofs = (v1.len ? v1.ptr : v2.ptr) - area;
543
0
  if (ofs >= size)
544
0
    ofs -= size;
545
0
  *head = ofs;
546
547
0
  ofs = (v2.len ? v2.ptr + v2.len : v1.ptr + v1.len) - area;
548
0
  if (ofs >= size)
549
0
    ofs -= size;
550
0
  *tail = ofs;
551
0
}
Unexecuted instantiation: errors.c:vp_data_to_ring
Unexecuted instantiation: log.c:vp_data_to_ring
Unexecuted instantiation: mworker.c:vp_data_to_ring
Unexecuted instantiation: ring.c:vp_data_to_ring
Unexecuted instantiation: sink.c:vp_data_to_ring
Unexecuted instantiation: applet.c:vp_data_to_ring
552
553
/* Set a ring's <head> and <tail> according to the room area represented by the
554
 * concatenation of <v1> and <v2> which must point to two adjacent areas within
555
 * a ring buffer of <size> bytes starting at <area>. <v1>, if not empty, starts
556
 * at the tail and <v2>, if not empty, ends at the head. If both vectors are of
557
 * length zero, the ring is considered full and both its head and tail will be
558
 * reset (which cannot be distinguished from empty). The caller must make sure
559
 * not to fill a ring with this API.
560
 */
561
static inline void vp_room_to_ring(const struct ist v1, const struct ist v2, char *area, size_t size, size_t *head, size_t *tail)
562
0
{
563
0
  size_t ofs;
564
0
565
0
  if (!v1.len && !v2.len) {
566
0
    *head = *tail = 0;
567
0
    return;
568
0
  }
569
0
570
0
  ofs = (v1.len ? v1.ptr : v2.ptr) - area;
571
0
  if (ofs >= size)
572
0
    ofs -= size;
573
0
  *tail = ofs;
574
0
575
0
  ofs = (v2.len ? v2.ptr + v2.len : v1.ptr + v1.len) - area;
576
0
  if (ofs >= size)
577
0
    ofs -= size;
578
0
  *head = ofs;
579
0
}
Unexecuted instantiation: errors.c:vp_room_to_ring
Unexecuted instantiation: log.c:vp_room_to_ring
Unexecuted instantiation: mworker.c:vp_room_to_ring
Unexecuted instantiation: ring.c:vp_room_to_ring
Unexecuted instantiation: sink.c:vp_room_to_ring
Unexecuted instantiation: applet.c:vp_room_to_ring
580
581
#endif /* _HAPROXY_VECPAIR_H */
582
583
/*
584
 * Local variables:
585
 *  c-indent-level: 8
586
 *  c-basic-offset: 8
587
 * End:
588
 */