Coverage Report

Created: 2025-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tarantool/src/lib/bit/bit.h
Line
Count
Source
1
#ifndef TARANTOOL_LIB_BIT_BIT_H_INCLUDED
2
#define TARANTOOL_LIB_BIT_BIT_H_INCLUDED
3
/*
4
 * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file.
5
 *
6
 * Redistribution and use in source and binary forms, with or
7
 * without modification, are permitted provided that the following
8
 * conditions are met:
9
 *
10
 * 1. Redistributions of source code must retain the above
11
 *    copyright notice, this list of conditions and the
12
 *    following disclaimer.
13
 *
14
 * 2. Redistributions in binary form must reproduce the above
15
 *    copyright notice, this list of conditions and the following
16
 *    disclaimer in the documentation and/or other materials
17
 *    provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23
 * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
/**
35
 * @file
36
 * @brief Bit manipulation library
37
 */
38
#include "trivia/util.h"
39
40
#include <stddef.h>
41
#include <stdint.h>
42
#include <stdbool.h>
43
#include <string.h>
44
#if defined(HAVE_FFSL) || defined(HAVE_FFSLL)
45
#include <strings.h>
46
#endif /* defined(HAVE_FFSL) || defined(HAVE_FFSLL) */
47
#include <limits.h>
48
49
#if defined(__cplusplus)
50
extern "C" {
51
#endif /* defined(__cplusplus) */
52
53
/**
54
 * @brief Unaligned load from memory.
55
 * @param p pointer
56
 * @return number
57
 */
58
inline uint8_t
59
load_u8(const void *p)
60
0
{
61
0
  uint8_t res;
62
0
  memcpy(&res, p, sizeof(res));
63
0
  return res;
64
0
}
65
66
/** @copydoc load_u8 */
67
inline uint16_t
68
load_u16(const void *p)
69
0
{
70
0
  uint16_t res;
71
0
  memcpy(&res, p, sizeof(res));
72
0
  return res;
73
0
}
74
75
/** @copydoc load_u8 */
76
inline uint32_t
77
load_u32(const void *p)
78
0
{
79
0
  uint32_t res;
80
0
  memcpy(&res, p, sizeof(res));
81
0
  return res;
82
0
}
83
84
/** @copydoc load_u8 */
85
inline uint64_t
86
load_u64(const void *p)
87
247
{
88
247
  uint64_t res;
89
247
  memcpy(&res, p, sizeof(res));
90
247
  return res;
91
247
}
92
93
/** @copydoc load_u8 */
94
inline float
95
load_float(const void *p)
96
0
{
97
0
  float res;
98
0
  memcpy(&res, p, sizeof(res));
99
0
  return res;
100
0
}
101
102
/** @copydoc load_u8 */
103
inline double
104
load_double(const void *p)
105
0
{
106
0
  double res;
107
0
  memcpy(&res, p, sizeof(res));
108
0
  return res;
109
0
}
110
111
/** @copydoc load_u8 */
112
inline bool
113
load_bool(const void *p)
114
0
{
115
0
  bool res;
116
0
  memcpy(&res, p, sizeof(res));
117
0
  return res;
118
0
}
119
120
/**
121
 * @brief Unaligned store to memory.
122
 * @param p pointer
123
 * @param v number
124
 */
125
inline void
126
store_u8(void *p, uint8_t v)
127
0
{
128
0
  memcpy(p, &v, sizeof(v));
129
0
}
130
131
/** @copydoc store_u8 */
132
inline void
133
store_u16(void *p, uint16_t v)
134
0
{
135
0
  memcpy(p, &v, sizeof(v));
136
0
}
137
138
/** @copydoc store_u8 */
139
inline void
140
store_u32(void *p, uint32_t v)
141
0
{
142
0
  memcpy(p, &v, sizeof(v));
143
0
}
144
145
/** @copydoc store_u8 */
146
inline void
147
store_u64(void *p, uint64_t v)
148
0
{
149
0
  memcpy(p, &v, sizeof(v));
150
0
}
151
152
/** @copydoc store_u8 */
153
inline void
154
store_float(void *p, float v)
155
0
{
156
0
  memcpy(p, &v, sizeof(v));
157
0
}
158
159
/** @copydoc store_u8 */
160
inline void
161
store_double(void *p, double v)
162
0
{
163
0
  memcpy(p, &v, sizeof(v));
164
0
}
165
166
/** @copydoc store_bool */
167
inline void
168
store_bool(void *p, bool v)
169
0
{
170
0
  memcpy(p, &v, sizeof(v));
171
0
}
172
173
/**
174
 * @brief Returns the size of memory needed to store a bitmap
175
 * of \a bit_count bits.
176
 * The function rounds the size up to a multiple of the word
177
 * size, which is required by bit_set() and bit_clear().
178
 * @param bit_count number of bits in the bitmap
179
 * @retval bitmap size, in bytes
180
 */
181
#define BITMAP_SIZE(bit_count) \
182
0
  (DIV_ROUND_UP((bit_count), CHAR_BIT * sizeof(long)) * sizeof(long))
183
184
/**
185
 * @brief Test bit \a pos in memory chunk \a data
186
 * @param data memory chunk
187
 * @param pos bit number (zero-based)
188
 * @retval true bit \a pos is set in \a data
189
 * @retval false otherwise
190
 */
191
inline bool
192
bit_test(const void *data, size_t pos)
193
0
{
194
0
  size_t chunk = pos / CHAR_BIT;
195
0
  size_t offset = pos % CHAR_BIT;
196
197
0
  const uint8_t *ldata = (const uint8_t *)data;
198
0
  return (ldata[chunk] >> offset) & 0x1;
199
0
}
200
201
/**
202
 * @brief Set bit \a pos in a memory chunk \a data
203
 * @param data memory chunk
204
 * @param pos bit number (zero-based)
205
 * @return previous value
206
 * @see bit_test
207
 * @see bit_clear
208
 */
209
inline bool
210
bit_set(void *data, size_t pos)
211
1.55M
{
212
1.55M
  size_t chunk = pos / CHAR_BIT;
213
1.55M
  size_t offset = pos % CHAR_BIT;
214
215
1.55M
  uint8_t *ldata = (uint8_t *)data;
216
1.55M
  bool prev = (ldata[chunk] >> offset) & 0x1;
217
1.55M
  ldata[chunk] |= (1UL << offset);
218
1.55M
  return prev;
219
1.55M
}
220
221
/**
222
 * @brief Clear bit \a pos in memory chunk \a data
223
 * @param data memory chunk
224
 * @param pos bit number (zero-based)
225
 * @return previous value
226
 * @see bit_test
227
 * @see bit_set
228
 */
229
inline bool
230
bit_clear(void *data, size_t pos)
231
0
{
232
0
  size_t chunk = pos / CHAR_BIT;
233
0
  size_t offset = pos % CHAR_BIT;
234
235
0
  uint8_t *ldata = (uint8_t *)data;
236
0
  bool prev = (ldata[chunk] >> offset) & 0x1;
237
0
  ldata[chunk] &= ~(1UL << offset);
238
0
  return prev;
239
0
}
240
241
/**
242
 * @brief Set \a count bits in a memory chunk \a data starting from bit \a pos
243
 *  to the value \a val.
244
 * @param data - memory chunk
245
 * @param pos - the first bit number (zero-based)
246
 * @param count - the amount of bits to set
247
 * @param val - the new value of bits
248
 */
249
inline void
250
bit_set_range(void *data, size_t pos, size_t count, bool val)
251
0
{
252
0
  if (count == 0)
253
0
    return;
254
  /*
255
   * We can have:
256
   *  - a head of bits in the start;
257
   *  - a bunch of whole bytes in the middle;
258
   *  - a tail of bits in the end.
259
   */
260
0
  size_t pos_byte = pos / CHAR_BIT;
261
0
  size_t pos_bit = pos % CHAR_BIT;
262
  /*
263
   * The head may be the only byte to copy to.
264
   */
265
0
  size_t head_size = pos_bit + count < CHAR_BIT ?
266
0
         count : CHAR_BIT - pos_bit;
267
0
  size_t rest_size = count - head_size;    /* Can be 0. */
268
0
  size_t body_size = rest_size / CHAR_BIT; /* In bytes. */
269
0
  size_t tail_size = rest_size % CHAR_BIT; /* In bits. */
270
271
0
  size_t head_mask = ((1ULL << head_size) - 1) << pos_bit;
272
0
  size_t tail_mask = ((1ULL << tail_size) - 1);
273
274
0
  uint8_t value = val ? 0xFF : 0x00;
275
0
  uint8_t *head = (uint8_t *)data + pos_byte;
276
0
  uint8_t *body = head + 1;
277
0
  uint8_t *tail = body + body_size;
278
  /*
279
   * Set the head bits.
280
   */
281
0
  *head = (*head & ~head_mask) | (value & head_mask);
282
  /*
283
   * Set the body bytes.
284
   */
285
0
  memset(body, value, body_size);
286
  /*
287
   * Set the tail bits. The if-statement is required to avoid overwriting
288
   * a byte beyond the buffer even if `tail_mask' is empty.
289
   */
290
0
  if (tail_size > 0)
291
0
    *tail = (*tail & ~tail_mask) | (value & tail_mask);
292
  /*
293
   * Once you are done trying to "optimize" this routine, and have
294
   * realized what a terrible mistake that was, please increment
295
   * the following counter as a warning to the next guy:
296
   *
297
   * total_hours_wasted_here = 8
298
   */
299
0
}
300
301
/**
302
 * @brief Copy \a count bits from memory chunk \a src starting from bit \a src_i
303
 *  into \a dst starting from bit \a dst_i.
304
 * @param dst - the memory chunk to copy bits into.
305
 * @param dst_i - the position to copy bits into.
306
 * @param count - the amount of bits to copy.
307
 * @param src - the memory chunk to copy bits from.
308
 * @param src_i - the position to copy bits from.
309
 * @pre the bit buffers do not overlap.
310
 */
311
void
312
bit_copy_range(uint8_t *restrict dst, size_t dst_i, const uint8_t *restrict src,
313
         size_t src_i, size_t count);
314
315
/**
316
 * @brief Copy \a count bits from memory chunk \a src starting from bit \a src_i
317
 *  in backward order into \a dst starting from bit \a dst_i in forward order.
318
 * @param dst - the memory chunk to copy bits into.
319
 * @param dst_i - the position to copy bits into.
320
 * @param count - the amount of bits to copy.
321
 * @param src - the memory chunk to copy bits from.
322
 * @param src_i - the position to copy bits from.
323
 * @pre the bit buffers do not overlap.
324
 */
325
void
326
bit_copy_range_reverse(uint8_t *restrict dst, size_t dst_i,
327
           const uint8_t *restrict src, size_t src_i, size_t count);
328
329
/**
330
 * @cond false
331
 * @brief Naive implementation of ctz.
332
 */
333
#define CTZ_NAIVE(x, bitsize) {           \
334
  if (x == 0) {             \
335
    return (bitsize);         \
336
  }               \
337
                  \
338
  int r = 0;              \
339
  for (; (x & 1) == 0; r++) {         \
340
    x >>= 1;            \
341
  }               \
342
                  \
343
  return r;             \
344
}
345
/** @endcond */
346
347
/**
348
 * @brief Count Trailing Zeros.
349
 * Returns the number of trailing 0-bits in @a x, starting at the least
350
 * significant bit position. If @a x is 0, the result is undefined.
351
 * @param x integer
352
 * @see __builtin_ctz()
353
 * @return the number trailing 0-bits
354
 */
355
inline int
356
bit_ctz_u32(uint32_t x)
357
0
{
358
0
#if defined(HAVE_BUILTIN_CTZ)
359
0
  return __builtin_ctz(x);
360
#elif defined(HAVE_FFSL)
361
  return ffsl(x) - 1;
362
#else
363
  CTZ_NAIVE(x, sizeof(uint32_t) * CHAR_BIT);
364
#endif
365
0
}
366
367
/**
368
 * @copydoc bit_ctz_u32
369
 */
370
inline int
371
bit_ctz_u64(uint64_t x)
372
535
{
373
535
#if   defined(HAVE_BUILTIN_CTZLL)
374
535
  return __builtin_ctzll(x);
375
#elif defined(HAVE_FFSLL)
376
  return ffsll(x) - 1;
377
#else
378
  CTZ_NAIVE(x, sizeof(uint64_t) * CHAR_BIT);
379
#endif
380
535
}
381
382
#undef CTZ_NAIVE
383
384
/**
385
 * @cond false
386
 * @brief Naive implementation of clz.
387
 */
388
#define CLZ_NAIVE(x, bitsize) {           \
389
  if (x == 0) {             \
390
    return  (bitsize);          \
391
  }               \
392
                  \
393
  int r = (bitsize);            \
394
  for (; x; r--) {            \
395
    x >>= 1;            \
396
  }               \
397
                  \
398
  return r;             \
399
}
400
/** @endcond */
401
402
/**
403
 * @brief Count Leading Zeros.
404
 * Returns the number of leading 0-bits in @a x, starting at the most
405
 * significant bit position. If @a x is 0, the result is undefined.
406
 * @param x integer
407
 * @see __builtin_clz()
408
 * @return the number of leading 0-bits
409
 */
410
inline int
411
bit_clz_u32(uint32_t x)
412
0
{
413
0
#if   defined(HAVE_BUILTIN_CLZ)
414
0
  return __builtin_clz(x);
415
#else /* !defined(HAVE_BUILTIN_CLZ) */
416
  CLZ_NAIVE(x, sizeof(uint32_t) * CHAR_BIT);
417
#endif
418
0
}
419
420
/**
421
 * @copydoc bit_clz_u32
422
 */
423
inline int
424
bit_clz_u64(uint64_t x)
425
0
{
426
0
#if   defined(HAVE_BUILTIN_CLZLL)
427
0
  return __builtin_clzll(x);
428
#else /* !defined(HAVE_BUILTIN_CLZLL) */
429
  CLZ_NAIVE(x, sizeof(uint64_t) * CHAR_BIT);
430
#endif
431
0
}
432
433
#undef CLZ_NAIVE
434
435
/**
436
 * @cond false
437
 * @brief Naive implementation of popcount.
438
 */
439
#define POPCOUNT_NAIVE(x, bitsize)  {         \
440
  int r;                \
441
  for (r = 0; x; r++) {           \
442
    x &= (x-1);           \
443
  }               \
444
                  \
445
  return r;             \
446
}
447
/** @endcond */
448
449
/**
450
 * @brief Returns the number of 1-bits in @a x.
451
 * @param x integer
452
 * @see __builtin_popcount()
453
 * @return the number of 1-bits in @a x
454
 */
455
inline int
456
bit_count_u32(uint32_t x)
457
0
{
458
0
#if   defined(HAVE_BUILTIN_POPCOUNT)
459
0
  return __builtin_popcount(x);
460
#else /* !defined(HAVE_BUILTIN_POPCOUNT) */
461
  POPCOUNT_NAIVE(x, sizeof(uint32_t) * CHAR_BIT);
462
#endif
463
0
}
464
465
/**
466
 * @copydoc bit_count_u32
467
 */
468
inline int
469
bit_count_u64(uint64_t x)
470
0
{
471
0
#if   defined(HAVE_BUILTIN_POPCOUNTLL)
472
0
  return __builtin_popcountll(x);
473
#else /* !defined(HAVE_BUILTIN_POPCOUNTLL) */
474
  POPCOUNT_NAIVE(x, sizeof(uint64_t) * CHAR_BIT);
475
#endif
476
0
}
477
478
#undef POPCOUNT_NAIVE
479
480
/**
481
 * @brief Returns the number of 1-bits in @a data vector starting from
482
 *    @a bit_offset.
483
 * @param data byte vector of length @a length bits.
484
 * @param bit_offset offset within the byte vector from where to start
485
 *         counting 1-bits.
486
 * @param length length in bits of byte vector @a data.
487
 * @return the number of 1-bits in @a data.
488
 *
489
 * Implementation adopted from the internals of the Apache
490
 * Arrow C++ library.
491
 */
492
size_t
493
bit_count(const uint8_t *data, size_t bit_offset, size_t length);
494
495
/**
496
 * @brief Rotate @a x left by @a r bits
497
 * @param x integer
498
 * @param r number for bits to rotate
499
 * @return @a x rotated left by @a r bits
500
 */
501
inline uint32_t
502
bit_rotl_u32(uint32_t x, int r)
503
0
{
504
0
  assert(r > 0 && r < 32);
505
  /* gcc recognises this code and generates a rotate instruction */
506
0
  return ((x << r) | (x >> (32 - r)));
507
0
}
508
509
/**
510
 * @copydoc bit_rotl_u32
511
 */
512
inline uint64_t
513
bit_rotl_u64(uint64_t x, int r)
514
0
{
515
0
  assert(r > 0 && r < 64);
516
  /* gcc recognises this code and generates a rotate instruction */
517
0
  return ((x << r) | (x >> (64 - r)));
518
0
}
519
520
/**
521
 * @copydoc bit_rotl_u32
522
 */
523
__attribute__ ((const)) inline uintmax_t
524
bit_rotl_umax(uintmax_t x, int r)
525
0
{
526
0
  assert(r > 0 && r < (int)(sizeof(uintmax_t) * CHAR_BIT));
527
0
  /* gcc recognises this code and generates a rotate instruction */
528
0
  return ((x << r) | (x >> (sizeof(uintmax_t) * CHAR_BIT - r)));
529
0
}
530
/**
531
 * @brief Rotate @a x right by @a r bits
532
 * @param x integer
533
 * @param r number for bits to rotate
534
 * @return @a x rotated right by @a r bits
535
 * @todo Move this method to bit.h
536
 */
537
inline uint32_t
538
bit_rotr_u32(uint32_t x, int r)
539
0
{
540
0
  assert(r > 0 && r < 32);
541
  /* gcc recognises this code and generates a rotate instruction */
542
0
  return ((x >> r) | (x << (32 - r)));
543
0
}
544
545
/**
546
 * @copydoc bit_rotr_u32
547
 */
548
inline uint64_t
549
bit_rotr_u64(uint64_t x, int r)
550
0
{
551
0
  assert(r > 0 && r < 64);
552
  /* gcc recognises this code and generates a rotate instruction */
553
0
  return ((x >> r) | (x << (64 - r)));
554
0
}
555
556
/**
557
 * @copydoc bswap_u32
558
 */
559
inline uint16_t
560
bswap_u16(uint16_t x)
561
0
{
562
#if defined(HAVE_BUILTIN_BSWAP16)
563
  return __builtin_bswap16(x);
564
#else /* !defined(HAVE_BUILTIN_BSWAP16) */
565
0
  return  ((x << 8) & UINT16_C(0xff00)) |
566
0
    ((x >> 8) & UINT16_C(0x00ff));
567
0
#endif
568
0
}
569
570
/**
571
 * @brief Returns a byte order swapped integer @a x.
572
 * This function does not take into account host architecture
573
 * (as it done by htonl / ntohl functions) and always returns @a x
574
 * with byte order swapped (BE -> LE if @a x is in BE and vice versa).
575
 * @param x integer
576
 * @return @a x with swapped bytes
577
 */
578
inline uint32_t
579
bswap_u32(uint32_t x)
580
0
{
581
0
#if defined(HAVE_BUILTIN_BSWAP32)
582
0
  return __builtin_bswap32(x);
583
#else /* !defined(HAVE_BUILTIN_BSWAP32) */
584
  return  ((x << 24) & UINT32_C(0xff000000)) |
585
    ((x <<  8) & UINT32_C(0x00ff0000)) |
586
    ((x >>  8) & UINT32_C(0x0000ff00)) |
587
    ((x >> 24) & UINT32_C(0x000000ff));
588
#endif
589
0
}
590
591
/**
592
 * @copydoc bswap_u32
593
 */
594
inline uint64_t
595
bswap_u64(uint64_t x)
596
0
{
597
0
#if defined(HAVE_BUILTIN_BSWAP64)
598
0
  return __builtin_bswap64(x);
599
#else /* !defined(HAVE_BUILTIN_BSWAP64) */
600
  return  ( (x << 56) & UINT64_C(0xff00000000000000)) |
601
    ( (x << 40) & UINT64_C(0x00ff000000000000)) |
602
    ( (x << 24) & UINT64_C(0x0000ff0000000000)) |
603
    ( (x <<  8) & UINT64_C(0x000000ff00000000)) |
604
    ( (x >>  8) & UINT64_C(0x00000000ff000000)) |
605
    ( (x >> 24) & UINT64_C(0x0000000000ff0000)) |
606
    ( (x >> 40) & UINT64_C(0x000000000000ff00)) |
607
    ( (x >> 56) & UINT64_C(0x00000000000000ff));
608
#endif
609
0
}
610
611
/**
612
 * @brief Reverse bits in \a x.
613
 * @param x value
614
 * @return value with bits reversed
615
 */
616
static inline uint8_t
617
bit_reverse_u8(uint8_t x)
618
0
{
619
0
  x = ((x & 0x55) << 1) | ((x >> 1) & 0x55);
620
0
  x = ((x & 0x33) << 2) | ((x >> 2) & 0x33);
621
0
  x = (x << 4) | (x >> 4);
622
0
  return x;
623
0
}
Unexecuted instantiation: xrow_decode_error_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow.c:bit_reverse_u8
Unexecuted instantiation: iproto_features.c:bit_reverse_u8
Unexecuted instantiation: error.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: vclock.c:bit_reverse_u8
Unexecuted instantiation: mpstream.c:bit_reverse_u8
Unexecuted instantiation: error_payload.c:bit_reverse_u8
Unexecuted instantiation: tt_uuid.c:bit_reverse_u8
Unexecuted instantiation: mp_uuid.c:bit_reverse_u8
Unexecuted instantiation: mp_datetime.c:bit_reverse_u8
Unexecuted instantiation: random.c:bit_reverse_u8
Unexecuted instantiation: bit.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_auth_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_greeting_decode_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_id_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_raft_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_dml_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_sql_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: vclock_from_string_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_call_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_watch_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: swim_proto_member_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: swim_proto.c:bit_reverse_u8
Unexecuted instantiation: swim_proto_meta_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: xrow_header_decode_fuzzer.c:bit_reverse_u8
Unexecuted instantiation: box.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: gc.c:bit_reverse_u8
Unexecuted instantiation: user.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: authentication.c:bit_reverse_u8
Unexecuted instantiation: replication.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: recovery.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: applier.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: relay.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: journal.c:bit_reverse_u8
Unexecuted instantiation: sql.c:bit_reverse_u8
Unexecuted instantiation: wal.c:bit_reverse_u8
Unexecuted instantiation: call.c:bit_reverse_u8
Unexecuted instantiation: alter.c:bit_reverse_u8
Unexecuted instantiation: build.c:bit_reverse_u8
Unexecuted instantiation: expr.c:bit_reverse_u8
Unexecuted instantiation: func.c:bit_reverse_u8
Unexecuted instantiation: global.c:bit_reverse_u8
Unexecuted instantiation: main.c:bit_reverse_u8
Unexecuted instantiation: malloc.c:bit_reverse_u8
Unexecuted instantiation: mem.c:bit_reverse_u8
Unexecuted instantiation: os.c:bit_reverse_u8
Unexecuted instantiation: os_unix.c:bit_reverse_u8
Unexecuted instantiation: parse_def.c:bit_reverse_u8
Unexecuted instantiation: prepare.c:bit_reverse_u8
Unexecuted instantiation: printf.c:bit_reverse_u8
Unexecuted instantiation: resolve.c:bit_reverse_u8
Unexecuted instantiation: port.c:bit_reverse_u8
Unexecuted instantiation: select.c:bit_reverse_u8
Unexecuted instantiation: tokenize.c:bit_reverse_u8
Unexecuted instantiation: treeview.c:bit_reverse_u8
Unexecuted instantiation: trigger.c:bit_reverse_u8
Unexecuted instantiation: update.c:bit_reverse_u8
Unexecuted instantiation: util.c:bit_reverse_u8
Unexecuted instantiation: vdbe.c:bit_reverse_u8
Unexecuted instantiation: vdbeapi.c:bit_reverse_u8
Unexecuted instantiation: vdbeaux.c:bit_reverse_u8
Unexecuted instantiation: vdbesort.c:bit_reverse_u8
Unexecuted instantiation: walker.c:bit_reverse_u8
Unexecuted instantiation: where.c:bit_reverse_u8
Unexecuted instantiation: wherecode.c:bit_reverse_u8
Unexecuted instantiation: whereexpr.c:bit_reverse_u8
Unexecuted instantiation: console.c:bit_reverse_u8
Unexecuted instantiation: serialize_lua.c:bit_reverse_u8
Unexecuted instantiation: tuple.c:bit_reverse_u8
Unexecuted instantiation: misc.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: execute.c:bit_reverse_u8
Unexecuted instantiation: tuple_format.c:bit_reverse_u8
Unexecuted instantiation: msgpack.c:bit_reverse_u8
Unexecuted instantiation: iproto.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: xrow_io.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: tuple_convert.c:bit_reverse_u8
Unexecuted instantiation: index.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: index_def.c:bit_reverse_u8
Unexecuted instantiation: index_weak_ref.c:bit_reverse_u8
Unexecuted instantiation: memtx_bitset.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: memtx_tx.c:bit_reverse_u8
Unexecuted instantiation: memtx_engine.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: memtx_space.c:bit_reverse_u8
Unexecuted instantiation: memtx_sort_data.c:bit_reverse_u8
Unexecuted instantiation: sysview.c:bit_reverse_u8
Unexecuted instantiation: blackhole.c:bit_reverse_u8
Unexecuted instantiation: service_engine.c:bit_reverse_u8
Unexecuted instantiation: session_settings.c:bit_reverse_u8
Unexecuted instantiation: vinyl.c:bit_reverse_u8
Unexecuted instantiation: vy_stmt.c:bit_reverse_u8
Unexecuted instantiation: vy_mem.c:bit_reverse_u8
Unexecuted instantiation: vy_run.c:bit_reverse_u8
Unexecuted instantiation: vy_lsm.c:bit_reverse_u8
Unexecuted instantiation: vy_tx.c:bit_reverse_u8
Unexecuted instantiation: vy_read_iterator.c:bit_reverse_u8
Unexecuted instantiation: vy_point_lookup.c:bit_reverse_u8
Unexecuted instantiation: vy_cache.c:bit_reverse_u8
Unexecuted instantiation: vy_log.c:bit_reverse_u8
Unexecuted instantiation: vy_upsert.c:bit_reverse_u8
Unexecuted instantiation: vy_history.c:bit_reverse_u8
Unexecuted instantiation: vy_read_set.c:bit_reverse_u8
Unexecuted instantiation: vy_scheduler.c:bit_reverse_u8
Unexecuted instantiation: vy_regulator.c:bit_reverse_u8
Unexecuted instantiation: space.c:bit_reverse_u8
Unexecuted instantiation: space_cache.c:bit_reverse_u8
Unexecuted instantiation: space_def.c:bit_reverse_u8
Unexecuted instantiation: sequence.c:bit_reverse_u8
Unexecuted instantiation: field_default_func.c:bit_reverse_u8
Unexecuted instantiation: tuple_constraint_func.c:bit_reverse_u8
Unexecuted instantiation: tuple_constraint_fkey.c:bit_reverse_u8
Unexecuted instantiation: key_list.c:bit_reverse_u8
Unexecuted instantiation: alter.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: schema.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: session.c:bit_reverse_u8
Unexecuted instantiation: checkpoint.c:bit_reverse_u8
Unexecuted instantiation: txn.c:bit_reverse_u8
Unexecuted instantiation: txn_limbo.c:bit_reverse_u8
Unexecuted instantiation: txn_event_trigger.c:bit_reverse_u8
Unexecuted instantiation: raft.c:bit_reverse_u8
Unexecuted instantiation: bind.c:bit_reverse_u8
Unexecuted instantiation: read_view.c:bit_reverse_u8
Unexecuted instantiation: xlog_reader.c:bit_reverse_u8
Unexecuted instantiation: opcodes.c:bit_reverse_u8
Unexecuted instantiation: parse.c:bit_reverse_u8
Unexecuted instantiation: cursor.c:bit_reverse_u8
Unexecuted instantiation: delete.c:bit_reverse_u8
Unexecuted instantiation: hash.c:bit_reverse_u8
Unexecuted instantiation: insert.c:bit_reverse_u8
Unexecuted instantiation: pragma.c:bit_reverse_u8
Unexecuted instantiation: show.c:bit_reverse_u8
Unexecuted instantiation: iproto.c:bit_reverse_u8
Unexecuted instantiation: space_upgrade.c:bit_reverse_u8
Unexecuted instantiation: memtx_space_upgrade.c:bit_reverse_u8
Unexecuted instantiation: memtx_allocator.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: memtx_hash.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: memtx_tree.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: memtx_rtree.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: vy_range.c:bit_reverse_u8
Unexecuted instantiation: vy_write_iterator.c:bit_reverse_u8
Unexecuted instantiation: request.c:bit_reverse_u8
Unexecuted instantiation: func_adapter.c:bit_reverse_u8
Unexecuted instantiation: field_map.c:bit_reverse_u8
Unexecuted instantiation: tuple_format_map.c:bit_reverse_u8
Unexecuted instantiation: tuple_constraint.c:bit_reverse_u8
Unexecuted instantiation: tuple_builder.c:bit_reverse_u8
Unexecuted instantiation: xrow_update.c:bit_reverse_u8
Unexecuted instantiation: xrow_update_field.c:bit_reverse_u8
Unexecuted instantiation: xrow_update_array.c:bit_reverse_u8
Unexecuted instantiation: xrow_update_bar.c:bit_reverse_u8
Unexecuted instantiation: xrow_update_route.c:bit_reverse_u8
Unexecuted instantiation: xrow_update_map.c:bit_reverse_u8
Unexecuted instantiation: tuple_compare.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: tuple_extract_key.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: tuple_hash.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: tuple_bloom.c:bit_reverse_u8
Unexecuted instantiation: key_def.c:bit_reverse_u8
Unexecuted instantiation: field_def.c:bit_reverse_u8
Unexecuted instantiation: opt_def.c:bit_reverse_u8
Unexecuted instantiation: mp_tuple.c:bit_reverse_u8
Unexecuted instantiation: xlog.c:bit_reverse_u8
Unexecuted instantiation: utils.c:bit_reverse_u8
Unexecuted instantiation: pickle.c:bit_reverse_u8
Unexecuted instantiation: lyaml.cc:bit_reverse_u8(unsigned char)
Unexecuted instantiation: lua_cjson.c:bit_reverse_u8
Unexecuted instantiation: iterator.c:bit_reverse_u8
Unexecuted instantiation: index.c:bit_reverse_u8
Unexecuted instantiation: bitset.c:bit_reverse_u8
Unexecuted instantiation: page.c:bit_reverse_u8
Unexecuted instantiation: swim.c:bit_reverse_u8
Unexecuted instantiation: swim_io.c:bit_reverse_u8
Unexecuted instantiation: fio.c:bit_reverse_u8
Unexecuted instantiation: bloom.c:bit_reverse_u8
Unexecuted instantiation: xrow_decode_begin_fuzzer.c:bit_reverse_u8
624
625
/**
626
 * @brief Index bits in the @a x, i.e. find all positions where bits are set.
627
 * This method fills @a indexes array with found positions in increasing order.
628
 * @a offset is added to each index before putting it into @a indexes.
629
 * @param x integer
630
 * @param indexes memory array where found indexes are stored
631
 * @param offset a number added to each index
632
 * @return pointer to last+1 element in indexes array
633
 */
634
int *
635
bit_index_u32(uint32_t x, int *indexes, int offset);
636
637
/**
638
 * @copydoc bit_index_u32
639
 */
640
int *
641
bit_index_u64(uint64_t x, int *indexes, int offset);
642
643
/** @cond false **/
644
#if defined(__x86_64__)
645
/* Use bigger words on x86_64 */
646
#define ITER_UINT uint64_t
647
535
#define ITER_CTZ bit_ctz_u64
648
0
#define ITER_LOAD load_u64
649
#else
650
#define ITER_UINT uint32_t
651
#define ITER_CTZ bit_ctz_u32
652
#define ITER_LOAD load_u32
653
#endif
654
/** @endcond **/
655
656
/**
657
 * @brief The Bit Iterator
658
 */
659
struct bit_iterator {
660
  /** @cond false **/
661
  /** Current word to process using ctz **/
662
  ITER_UINT word;
663
  /** A bitmask that XORed with word (for set = false iteration) **/
664
  ITER_UINT word_xor;
665
  /** A base offset of the word in bits **/
666
  size_t word_base;
667
  /** A pointer to the start of a memory chunk **/
668
  const char *start;
669
  /** A pointer to the next part of a memory chunk */
670
  const char *next;
671
  /** A pointer to the end of a memory chunk */
672
  const char *end;
673
  /** @endcond **/
674
};
675
676
/**
677
 * @brief Initialize bit iterator \a it
678
 * @param it bit iterator
679
 * @param data memory chunk
680
 * @param size size of the memory chunk \a data
681
 * @param set true to iterate over set bits or false to iterate over clear bits
682
 */
683
inline void
684
bit_iterator_init(struct bit_iterator *it, const void *data, size_t size,
685
      bool set)
686
49
{
687
49
  it->start = (const char *) data;
688
49
  it->next = it->start;
689
49
  it->end = it->next + size;
690
49
  if (unlikely(size == 0)) {
691
0
    it->word = 0;
692
0
    return;
693
0
  }
694
695
49
  it->word_xor = set ? 0 : (ITER_UINT) -1;
696
49
  it->word_base = 0;
697
698
  /* Check if size is a multiple of sizeof(ITER_UINT) */
699
49
  if (likely(size % sizeof(ITER_UINT) == 0)) {
700
0
    it->word = ITER_LOAD(it->next);
701
0
    it->next += sizeof(ITER_UINT);
702
49
  } else {
703
49
    const char *e = it->next + size % sizeof(ITER_UINT);
704
49
    it->word = it->word_xor;
705
49
    char *w = (char *) &it->word;
706
245
    while (it->next < e)
707
196
      *w++ = *it->next++;
708
49
  }
709
49
  it->word ^= it->word_xor;
710
49
}
711
712
/**
713
 * @brief Return a number of a next set bit in \a it or \a SIZE_MAX
714
 * if no bits are remain in \a it
715
 * @param it bit iterator
716
 * @retval a zero-based number of a next set bit in iterator \a it
717
 * @retval SIZE_MAX if \a it does not have more set bits
718
 */
719
inline size_t
720
bit_iterator_next(struct bit_iterator *it)
721
584
{
722
584
  while (unlikely(it->word == 0)) {
723
49
    if (unlikely(it->next >= it->end))
724
49
      return SIZE_MAX;
725
726
    /* Extract the next word from memory */
727
0
    it->word = ITER_LOAD(it->next);
728
0
    it->word ^= it->word_xor;
729
0
    it->word_base = (it->next - it->start) * CHAR_BIT;
730
0
    it->next += sizeof(ITER_UINT);
731
0
  }
732
733
  /* Find the position of a first trailing bit in the current word */
734
535
  int bit = ITER_CTZ(it->word);
735
  /* Remove the first trailing bit from the current word */
736
535
  it->word &= it->word - 1;
737
  /* Add start position if the current word to the found bit */
738
535
  return it->word_base + bit;
739
584
}
740
741
#undef ITER_LOAD
742
#undef ITER_CTZ
743
#undef ITER_UINT
744
745
#if defined(__cplusplus)
746
} /* extern "C" */
747
#endif /* defined(__cplusplus) */
748
749
#endif /* TARANTOOL_LIB_BIT_BIT_H_INCLUDED */