Coverage Report

Created: 2026-03-16 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tbit.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/* Module Info: Operations on bit vectors.  A bit vector is an array of bytes
14
 *              with the least-significant bits in the first byte.  That is,
15
 *              the bytes are in little-endian order.
16
 */
17
18
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
19
20
#include "H5private.h"   /*generic functions        */
21
#include "H5Eprivate.h"  /*error handling       */
22
#include "H5Tpkg.h"      /*data-type functions        */
23
#include "H5WBprivate.h" /* Wrapped Buffers                      */
24
25
/*-------------------------------------------------------------------------
26
 * Function:    H5T__bit_copy
27
 *
28
 * Purpose:     Copies bits from one vector to another.
29
 *
30
 * Return:      void
31
 *
32
 *-------------------------------------------------------------------------
33
 */
34
void
35
H5T__bit_copy(uint8_t *dst, size_t dst_offset, const uint8_t *src, size_t src_offset, size_t size)
36
0
{
37
0
    size_t shift;
38
0
    size_t mask_lo, mask_hi;
39
0
    size_t s_idx, d_idx;
40
41
0
    FUNC_ENTER_PACKAGE_NOERR
42
43
    /* Normalize the offset to be a byte number and a bit offset within that
44
     * byte.
45
     */
46
0
    s_idx = src_offset / 8;
47
0
    d_idx = dst_offset / 8;
48
0
    src_offset %= 8;
49
0
    dst_offset %= 8;
50
51
    /* Get things rolling. This means copying bits until we're aligned on a
52
     * source byte.  This the following example, five bits are copied to the
53
     * destination.
54
     *
55
     *                      src[s_idx]
56
     *   +---------------+---------------+
57
     *   |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
58
     *   +---------------+---------------+
59
     *      ... : : : : : | | | | |
60
     *      ... v v v v v V V V V V
61
     *      ...+---------------+---------------+
62
     *      ...|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
63
     *      ...+---------------+---------------+
64
     *           dst[d_idx+1]      dst[d_idx]
65
     */
66
0
    while (src_offset && size > 0) {
67
0
        size_t nbits = MIN3(size, 8 - dst_offset, 8 - src_offset);
68
0
        size_t mask  = ((size_t)1 << nbits) - 1;
69
70
0
        dst[d_idx] &= (uint8_t) ~(mask << dst_offset);
71
0
        dst[d_idx] = (uint8_t)(dst[d_idx] | (((src[s_idx] >> src_offset) & (uint8_t)mask) << dst_offset));
72
73
0
        src_offset += nbits;
74
0
        if (src_offset >= 8) {
75
0
            s_idx++;
76
0
            src_offset %= 8;
77
0
        }
78
79
0
        dst_offset += nbits;
80
0
        if (dst_offset >= 8) {
81
0
            d_idx++;
82
0
            dst_offset %= 8;
83
0
        }
84
85
0
        size -= nbits;
86
0
    }
87
88
    /* The middle bits. We are aligned on a source byte which needs to be
89
     * copied to two (or one in the degenerate case) destination bytes.
90
     *
91
     *          src[s_idx]
92
     *       +---------------+
93
     *       |7 6 5 4 3 2 1 0|
94
     *       +---------------+
95
     *              | | | | | | | |
96
     *        V V V V V V V V
97
     *   +---------------+---------------+
98
     *   |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
99
     *   +---------------+---------------+
100
     *     dst[d_idx+1]      dst[d_idx]
101
     *
102
     *
103
     * Calculate shifts and masks.  See diagrams below.  MASK_LO in this
104
     * example is 0x1f (the low five bits) and MASK_HI is 0xe0 (the high three
105
     * bits). SHIFT is three since the source must be shifted right three bits
106
     * to line up with the destination.
107
     */
108
0
    shift   = dst_offset;
109
0
    mask_lo = ((size_t)1 << (8 - shift)) - 1;
110
0
    mask_hi = (~mask_lo) & 0xff;
111
112
0
    for (/*void*/; size > 8; size -= 8, d_idx++, s_idx++) {
113
0
        if (shift) {
114
0
            dst[d_idx + 0] &= (uint8_t)(~(mask_lo << shift));
115
0
            dst[d_idx + 0] |= (uint8_t)((src[s_idx] & mask_lo) << shift);
116
0
            dst[d_idx + 1] &= (uint8_t)(~(mask_hi >> (8 - shift)));
117
0
            dst[d_idx + 1] |= (uint8_t)((src[s_idx] & mask_hi) >> (8 - shift));
118
0
        }
119
0
        else
120
0
            dst[d_idx] = src[s_idx];
121
0
    }
122
123
    /* Finish up */
124
0
    while (size > 0) {
125
0
        size_t nbits = (size_t)MIN3(size, 8 - dst_offset, 8 - src_offset);
126
0
        size_t mask  = ((size_t)1 << nbits) - 1;
127
128
0
        dst[d_idx] &= (uint8_t)(~(mask << dst_offset));
129
0
        dst[d_idx] = (uint8_t)(dst[d_idx] | (((src[s_idx] >> src_offset) & (uint8_t)mask) << dst_offset));
130
131
0
        src_offset += nbits;
132
0
        if (src_offset >= 8) {
133
0
            s_idx++;
134
0
            src_offset %= 8;
135
0
        }
136
137
0
        dst_offset += nbits;
138
0
        if (dst_offset >= 8) {
139
0
            d_idx++;
140
0
            dst_offset %= 8;
141
0
        }
142
143
0
        size -= nbits;
144
0
    }
145
146
0
    FUNC_LEAVE_NOAPI_VOID
147
0
} /* end H5T__bit_copy() */
148
149
/*-------------------------------------------------------------------------
150
 * Function:    H5T__bit_shift
151
 *
152
 * Purpose:     Simulation of hardware shifting.  Shifts a bit vector
153
 *              in a way similar to shifting a variable value, like
154
 *              value <<= 3, or value >>= 16.  SHIFT_DIST is positive for
155
 *              left shift, negative for right shift.  The bit vector starts
156
 *              at OFFSET and is SIZE long.  The caller has to make sure
157
 *              SIZE+OFFSET doesn't exceed the size of BUF.
158
 *
159
 *              For example, if we have a bit sequence 00011100, offset=2,
160
 *              size=3, shift_dist=2, the result will be 00010000.
161
 *
162
 * Return:      void
163
 *
164
 *-------------------------------------------------------------------------
165
 */
166
herr_t
167
H5T__bit_shift(uint8_t *buf, ssize_t shift_dist, size_t offset, size_t size)
168
0
{
169
0
    uint8_t tmp_buf[512];        /* Temporary buffer */
170
0
    H5WB_t *wb        = NULL;    /* Wrapped buffer for temporary buffer */
171
0
    herr_t  ret_value = SUCCEED; /* Return value */
172
173
0
    FUNC_ENTER_PACKAGE
174
175
    /* Sanity check */
176
0
    assert(buf);
177
0
    assert(size);
178
179
0
    if (shift_dist) {
180
0
        size_t abs_shift_dist = (size_t)ABS(shift_dist);
181
182
0
        if (abs_shift_dist >= size)
183
0
            H5T__bit_set(buf, offset, size, 0);
184
0
        else {
185
0
            size_t   buf_size = (size / 8) + 1; /* Size of shift buffer needed */
186
0
            uint8_t *shift_buf;                 /* Pointer to shift buffer */
187
188
            /* Wrap the local buffer for serialized header info */
189
0
            if (NULL == (wb = H5WB_wrap(tmp_buf, sizeof(tmp_buf))))
190
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't wrap buffer");
191
192
            /* Get a pointer to a buffer that's large enough  */
193
0
            if (NULL == (shift_buf = (uint8_t *)H5WB_actual(wb, buf_size)))
194
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "can't get actual buffer");
195
196
            /* Shift vector by making copies */
197
0
            if (shift_dist > 0) { /* left shift */
198
                /* Copy part to be shifted to a temporary buffer */
199
0
                H5T__bit_copy(shift_buf, (size_t)0, buf, offset, size - abs_shift_dist);
200
201
                /* Copy it back to the original buffer */
202
0
                H5T__bit_copy(buf, offset + abs_shift_dist, shift_buf, (size_t)0, size - abs_shift_dist);
203
204
                /* Zero-set the left part*/
205
0
                H5T__bit_set(buf, offset, abs_shift_dist, 0);
206
0
            }
207
0
            else { /* right shift */
208
0
                H5T__bit_copy(shift_buf, (size_t)0, buf, offset + abs_shift_dist, size - abs_shift_dist);
209
0
                H5T__bit_copy(buf, offset, shift_buf, (size_t)0, size - abs_shift_dist);
210
0
                H5T__bit_set(buf, offset + size - abs_shift_dist, abs_shift_dist, 0);
211
0
            }
212
0
        } /* end else */
213
0
    }     /* end if */
214
215
0
done:
216
    /* Release resources */
217
0
    if (wb && H5WB_unwrap(wb) < 0)
218
0
        HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer");
219
220
0
    FUNC_LEAVE_NOAPI(ret_value)
221
0
} /* end H5T__bit_shift() */
222
223
/*-------------------------------------------------------------------------
224
 * Function:    H5T__bit_get_d
225
 *
226
 * Purpose:     Return a small bit sequence as a number.  Bit vector starts
227
 *              at OFFSET and is SIZE bits long.
228
 *
229
 * Return:      The bit sequence interpreted as an unsigned integer
230
 *
231
 *-------------------------------------------------------------------------
232
 */
233
uint64_t
234
H5T__bit_get_d(const uint8_t *buf, size_t offset, size_t size)
235
0
{
236
0
    uint64_t val = 0;
237
0
    size_t   i, hs;
238
0
    uint64_t ret_value = 0; /* Return value */
239
240
0
    FUNC_ENTER_PACKAGE_NOERR
241
242
0
    assert(8 * sizeof(val) >= size);
243
244
0
    H5T__bit_copy((uint8_t *)&val, (size_t)0, buf, offset, size);
245
0
    switch (H5T_native_order_g) {
246
0
        case H5T_ORDER_LE:
247
0
            break;
248
249
0
        case H5T_ORDER_BE:
250
0
            for (i = 0, hs = sizeof(val) / 2; i < hs; i++) {
251
0
                uint8_t tmp                              = ((uint8_t *)&val)[i];
252
0
                ((uint8_t *)&val)[i]                     = ((uint8_t *)&val)[sizeof(val) - (i + 1)];
253
0
                ((uint8_t *)&val)[sizeof(val) - (i + 1)] = tmp;
254
0
            }
255
0
            break;
256
257
0
        case H5T_ORDER_ERROR:
258
0
        case H5T_ORDER_VAX:
259
0
        case H5T_ORDER_NONE:
260
0
        case H5T_ORDER_MIXED:
261
0
        default:
262
            /* This function can't return errors */
263
0
            assert(0 && "unknown byte order");
264
0
    }
265
266
    /* Set return value */
267
0
    ret_value = val;
268
269
0
    FUNC_LEAVE_NOAPI(ret_value)
270
0
} /* end H5T__bit_get_d() */
271
272
/*-------------------------------------------------------------------------
273
 * Function:    H5T__bit_set_d
274
 *
275
 * Purpose:     Sets part of a bit vector to the specified unsigned value.
276
 *
277
 * Return:      void
278
 *
279
 *-------------------------------------------------------------------------
280
 */
281
void
282
H5T__bit_set_d(uint8_t *buf, size_t offset, size_t size, uint64_t val)
283
0
{
284
0
    size_t i, hs;
285
286
0
    FUNC_ENTER_PACKAGE_NOERR
287
288
0
    assert(8 * sizeof(val) >= size);
289
290
0
    switch (H5T_native_order_g) {
291
0
        case H5T_ORDER_LE:
292
0
            break;
293
294
0
        case H5T_ORDER_BE:
295
0
            for (i = 0, hs = sizeof(val) / 2; i < hs; i++) {
296
0
                uint8_t tmp                              = ((uint8_t *)&val)[i];
297
0
                ((uint8_t *)&val)[i]                     = ((uint8_t *)&val)[sizeof(val) - (i + 1)];
298
0
                ((uint8_t *)&val)[sizeof(val) - (i + 1)] = tmp;
299
0
            }
300
0
            break;
301
302
0
        case H5T_ORDER_ERROR:
303
0
        case H5T_ORDER_VAX:
304
0
        case H5T_ORDER_NONE:
305
0
        case H5T_ORDER_MIXED:
306
0
        default:
307
            /* This function can't return errors */
308
0
            assert(0 && "unknown byte order");
309
0
    }
310
311
0
    H5T__bit_copy(buf, offset, (uint8_t *)&val, (size_t)0, size);
312
313
0
    FUNC_LEAVE_NOAPI_VOID
314
0
} /* end H5T__bit_set_d() */
315
316
/*-------------------------------------------------------------------------
317
 * Function:    H5T__bit_set
318
 *
319
 * Purpose:     Sets or clears bits in a contiguous region of a vector
320
 *              beginning at bit OFFSET and continuing for SIZE bits.
321
 *
322
 * Return:      void
323
 *
324
 *-------------------------------------------------------------------------
325
 */
326
void
327
H5T__bit_set(uint8_t *buf, size_t offset, size_t size, bool value)
328
18
{
329
18
    int idx;
330
331
18
    FUNC_ENTER_PACKAGE_NOERR
332
333
    /* Normalize */
334
18
    idx = (int)offset / 8;
335
18
    offset %= 8;
336
337
    /* The first partial byte */
338
18
    if (size && offset % 8) {
339
10
        size_t   nbits = MIN(size, 8 - offset);
340
10
        unsigned mask  = ((unsigned)1 << nbits) - 1;
341
342
10
        if (value)
343
7
            buf[idx] = (uint8_t)(buf[idx] | (mask << offset));
344
3
        else
345
3
            buf[idx] &= (uint8_t)(~(mask << offset));
346
347
10
        idx++;
348
10
        size -= nbits;
349
10
    }
350
351
    /* The middle bytes */
352
52
    while (size >= 8) {
353
34
        buf[idx++] = (uint8_t)(value ? 0xff : 0x00);
354
34
        size -= 8;
355
34
    }
356
357
    /* The last partial byte */
358
18
    if (size) {
359
10
        if (value)
360
6
            buf[idx] |= (uint8_t)(((unsigned)1 << size) - 1);
361
4
        else
362
4
            buf[idx] &= (uint8_t)(~(((unsigned)1 << size) - 1));
363
10
    }
364
365
18
    FUNC_LEAVE_NOAPI_VOID
366
18
} /* end H5T__bit_set() */
367
368
/*-------------------------------------------------------------------------
369
 * Function:    H5T__bit_find
370
 *
371
 * Purpose:     Finds the first bit with the specified VALUE within a region
372
 *              of a bit vector.  The region begins at OFFSET and continues
373
 *              for SIZE bits, but the region can be searched from the least
374
 *              significant end toward the most significant end(H5T_BIT_LSB
375
 *              as DIRECTION), or from the most significant end to the least
376
 *              significant end(H5T_BIT_MSB as DIRECTION).
377
 *
378
 * Return:      Success:    The position of the bit found, relative to
379
 *                          the offset.
380
 *
381
 *              Failure:    -1
382
 *
383
 *-------------------------------------------------------------------------
384
 */
385
ssize_t
386
H5T__bit_find(const uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction, bool value)
387
0
{
388
0
    ssize_t base = (ssize_t)offset;
389
0
    ssize_t idx, i;
390
0
    size_t  iu;
391
0
    ssize_t ret_value = (-1); /* Return value */
392
393
    /* Use FUNC_ENTER_PACKAGE_NOERR here to avoid performance issues */
394
0
    FUNC_ENTER_PACKAGE_NOERR
395
396
    /* Some functions call this with value=true */
397
0
    assert(true == 1);
398
399
0
    switch (direction) {
400
0
        case H5T_BIT_LSB:
401
            /* Calculate index */
402
0
            idx = (ssize_t)(offset / 8);
403
0
            offset %= 8;
404
405
            /* Beginning */
406
0
            if (offset) {
407
0
                for (iu = offset; iu < 8 && size > 0; iu++, size--)
408
0
                    if (value == (bool)((buf[idx] >> iu) & 0x01))
409
0
                        HGOTO_DONE(8 * idx + (ssize_t)iu - base);
410
411
0
                offset = 0;
412
0
                idx++;
413
0
            } /* end if */
414
415
            /* Middle */
416
0
            while (size >= 8) {
417
0
                if ((value ? 0x00 : 0xff) != buf[idx])
418
0
                    for (i = 0; i < 8; i++)
419
0
                        if (value == (bool)((buf[idx] >> i) & 0x01))
420
0
                            HGOTO_DONE(8 * idx + i - base);
421
422
0
                size -= 8;
423
0
                idx++;
424
0
            } /* end while */
425
426
            /* End */
427
0
            for (i = 0; i < (ssize_t)size; i++)
428
0
                if (value == (bool)((buf[idx] >> i) & 0x01))
429
0
                    HGOTO_DONE(8 * idx + i - base);
430
0
            break;
431
432
0
        case H5T_BIT_MSB:
433
            /* Calculate index */
434
0
            idx = (ssize_t)((offset + size - 1) / 8);
435
0
            offset %= 8;
436
437
            /* Beginning */
438
0
            if (size > 8 - offset && (offset + size) % 8) {
439
0
                for (iu = (offset + size) % 8; iu > 0; --iu, --size)
440
0
                    if (value == (bool)((buf[idx] >> (iu - 1)) & 0x01))
441
0
                        HGOTO_DONE(8 * idx + (ssize_t)(iu - 1) - base);
442
443
0
                --idx;
444
0
            } /* end if */
445
446
            /* Middle */
447
0
            while (size >= 8) {
448
0
                if ((value ? 0x00 : 0xff) != buf[idx]) {
449
0
                    for (i = 7; i >= 0; --i)
450
0
                        if (value == (bool)((buf[idx] >> i) & 0x01))
451
0
                            HGOTO_DONE(8 * idx + i - base);
452
0
                } /* end if */
453
454
0
                size -= 8;
455
0
                --idx;
456
0
            } /* end while */
457
458
            /* End */
459
0
            if (size > 0) {
460
0
                for (iu = offset + size; iu > offset; --iu)
461
0
                    if (value == (bool)((buf[idx] >> (iu - 1)) & 0x01))
462
0
                        HGOTO_DONE(8 * idx + (ssize_t)(iu - 1) - base);
463
0
            }
464
0
            break;
465
466
0
        default:
467
0
            assert(0 && "Unknown bit search direction");
468
0
    } /* end switch */
469
470
0
done:
471
0
    FUNC_LEAVE_NOAPI(ret_value)
472
0
} /* end H5T__bit_find() */
473
474
/*-------------------------------------------------------------------------
475
 * Function:    H5T__bit_inc
476
 *
477
 * Purpose:     Increment part of a bit field by adding 1.  The bit field
478
 *              starts with bit position START and is SIZE bits long.
479
 *
480
 * Return:      The carry-out value.  true if overflows, false otherwise.
481
 *
482
 *-------------------------------------------------------------------------
483
 */
484
bool
485
H5T__bit_inc(uint8_t *buf, size_t start, size_t size)
486
0
{
487
0
    size_t   idx   = start / 8;
488
0
    unsigned carry = 1;
489
0
    unsigned acc, mask;
490
491
    /* Use FUNC_ENTER_PACKAGE_NOERR here to avoid performance issues */
492
0
    FUNC_ENTER_PACKAGE_NOERR
493
494
0
    assert(buf);
495
496
0
    start %= 8;
497
498
    /* The first partial byte */
499
0
    if (start) {
500
0
        if (size + start < 8)
501
0
            mask = ((unsigned)1 << size) - 1;
502
0
        else
503
0
            mask = ((unsigned)1 << (8 - start)) - 1;
504
0
        acc = ((unsigned)buf[idx] >> start) & mask;
505
0
        acc++;
506
0
        carry = acc & ((unsigned)1 << MIN(size, 8 - start));
507
0
        buf[idx] &= (uint8_t)(~(mask << start));
508
0
        buf[idx] = (uint8_t)(buf[idx] | ((acc & mask) << start));
509
0
        size -= MIN(size, 8 - start);
510
0
        start = 0;
511
0
        idx++;
512
0
    }
513
514
    /* The middle */
515
0
    while (carry && size >= 8) {
516
0
        acc = buf[idx];
517
0
        acc++;
518
0
        carry    = acc & 0x100;
519
0
        buf[idx] = (uint8_t)(acc & 0xff);
520
0
        idx++;
521
0
        size -= 8;
522
0
    }
523
524
    /* The last bits */
525
0
    if (carry && size > 0) {
526
0
        mask = ((unsigned)1 << size) - 1;
527
0
        acc  = buf[idx] & mask;
528
0
        acc++;
529
0
        carry = acc & ((unsigned)1 << size);
530
0
        buf[idx] &= (uint8_t)(~mask);
531
0
        buf[idx] |= (uint8_t)(acc & mask);
532
0
    }
533
534
0
    FUNC_LEAVE_NOAPI(carry ? true : false)
535
0
} /* end H5T__bit_inc() */
536
537
/*-------------------------------------------------------------------------
538
 * Function:    H5T__bit_dec
539
 *
540
 * Purpose:     Decrement part of a bit field by subtracting 1.  The bit
541
 *              field starts with bit position START and is SIZE bits long.
542
 *
543
 * Return:      The "borrow-in" value. It's true if underflows, false
544
 *              otherwise.
545
 *
546
 *-------------------------------------------------------------------------
547
 */
548
bool
549
H5T__bit_dec(uint8_t *buf, size_t start, size_t size)
550
0
{
551
0
    size_t   idx = start / 8;
552
0
    size_t   pos = start % 8;
553
0
    uint8_t  tmp;
554
0
    unsigned borrow = 0;
555
556
    /* Use FUNC_ENTER_PACKAGE_NOERR here to avoid performance issues */
557
0
    FUNC_ENTER_PACKAGE_NOERR
558
559
0
    assert(buf);
560
0
    assert(size);
561
562
    /* The first partial byte */
563
0
    if ((size + start - 1) / 8 > idx) {
564
        /* The bit sequence doesn't end in the same byte as starts */
565
566
        /* Example:  a sequence like 11000100 and start = 3.  We subtract 00001000 from
567
         * it and get 10111100.  If a sequence is 00000111, we do right shift for START
568
         * bits and get 00000000.  So we need to borrow from higher byte when we subtract
569
         * 00001000.
570
         */
571
0
        if (!(buf[idx] >> pos))
572
0
            borrow = 1;
573
0
        buf[idx] = (uint8_t)(buf[idx] - (1 << pos));
574
0
        idx++;
575
0
        size -= (8 - pos);
576
577
        /* The middle bytes */
578
0
        while (borrow && size >= 8) {
579
0
            if (buf[idx])
580
0
                borrow = 0;
581
0
            buf[idx]--;
582
583
0
            idx++;
584
0
            size -= 8;
585
0
        }
586
587
        /* The last partial byte */
588
0
        if (borrow && size > 0) {
589
            /* Similar to the first byte case, where sequence ends in the same byte as starts */
590
0
            tmp = buf[idx];
591
0
            buf[idx]--;
592
0
            if ((buf[idx] >> size) != tmp >> size)
593
0
                buf[idx] = (uint8_t)(buf[idx] + (1 << size));
594
0
        }
595
0
    }
596
0
    else {
597
        /* The bit sequence ends in the same byte as starts */
598
599
        /* Example: a sequence like 11000100 and pos=3, size=3.  We subtract 00001000
600
         * and get 10111100.  A bit is borrowed from 6th bit(buf[idx]>>6=00000010, tmp>>6=00000011,
601
         * not equal).  We need to put this bit back by increment 1000000.
602
         */
603
0
        tmp      = buf[idx];
604
0
        buf[idx] = (uint8_t)(buf[idx] - (1 << pos));
605
0
        if ((buf[idx] >> (pos + size)) != tmp >> (pos + size)) {
606
0
            buf[idx] = (uint8_t)(buf[idx] + (1 << (pos + size)));
607
0
            borrow   = 1;
608
0
        }
609
0
    }
610
611
0
    FUNC_LEAVE_NOAPI(borrow ? true : false)
612
0
} /* end H5T__bit_dec() */
613
614
/*-------------------------------------------------------------------------
615
 * Function:    H5T__bit_neg
616
 *
617
 * Purpose:     Negate part of a bit sequence.  The bit field starts with
618
 *              bit position START and is SIZE bits long.
619
 *
620
 * Return:      void
621
 *
622
 *-------------------------------------------------------------------------
623
 */
624
void
625
H5T__bit_neg(uint8_t *buf, size_t start, size_t size)
626
0
{
627
0
    size_t  idx = start / 8;
628
0
    size_t  pos = start % 8;
629
0
    uint8_t tmp[1];
630
631
    /* Use FUNC_ENTER_PACKAGE_NOERR here to avoid performance issues */
632
0
    FUNC_ENTER_PACKAGE_NOERR
633
634
0
    assert(buf);
635
0
    assert(size);
636
637
    /* The first partial byte */
638
0
    tmp[0] = (uint8_t)~buf[idx];
639
640
    /* Simply copy the negated bit field back to the original byte */
641
0
    if ((size + start - 1) / 8 > idx) { /*bit sequence doesn't end in the same byte as starts*/
642
0
        H5T__bit_copy(&(buf[idx]), pos, tmp, pos, (8 - pos));
643
0
        idx++;
644
0
        size -= (8 - pos);
645
646
        /* The middle bytes */
647
0
        while (size >= 8) {
648
0
            buf[idx] = (uint8_t) ~(buf[idx]);
649
0
            idx++;
650
0
            size -= 8;
651
0
        }
652
653
        /* The last partial byte */
654
0
        if (size > 0) {
655
            /* Similar to the first byte case, where sequence ends in the same byte as starts */
656
0
            tmp[0] = (uint8_t)~buf[idx];
657
0
            H5T__bit_copy(&(buf[idx]), (size_t)0, tmp, (size_t)0, size);
658
0
        }
659
0
    }
660
0
    else {
661
        /* bit sequence ends in the same byte as starts */
662
0
        H5T__bit_copy(&(buf[idx]), pos, tmp, pos, size);
663
0
    }
664
665
0
    FUNC_LEAVE_NOAPI_VOID
666
0
} /* end H5T__bit_neg() */