1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*
15  * Programmer: Robb Matzke
16  *             Friday, October 10, 1997
17  */
18 #ifndef H5VMprivate_H
19 #define H5VMprivate_H
20 
21 /* Private headers needed by this file */
22 #include "H5private.h"   /* Generic Functions            */
23 #include "H5Eprivate.h"  /* Error handling              */
24 #include "H5MMprivate.h" /* Memory management            */
25 
26 /* Vector-Vector sequence operation callback */
27 typedef herr_t (*H5VM_opvv_func_t)(hsize_t dst_off, hsize_t src_off, size_t len, void *udata);
28 
29 /* Vector comparison functions like Fortran66 comparison operators */
30 #define H5VM_vector_eq_s(N, V1, V2) (H5VM_vector_cmp_s(N, V1, V2) == 0)
31 #define H5VM_vector_lt_s(N, V1, V2) (H5VM_vector_cmp_s(N, V1, V2) < 0)
32 #define H5VM_vector_gt_s(N, V1, V2) (H5VM_vector_cmp_s(N, V1, V2) > 0)
33 #define H5VM_vector_le_s(N, V1, V2) (H5VM_vector_cmp_s(N, V1, V2) <= 0)
34 #define H5VM_vector_ge_s(N, V1, V2) (H5VM_vector_cmp_s(N, V1, V2) >= 0)
35 #define H5VM_vector_eq_u(N, V1, V2) (H5VM_vector_cmp_u(N, V1, V2) == 0)
36 #define H5VM_vector_lt_u(N, V1, V2) (H5VM_vector_cmp_u(N, V1, V2) < 0)
37 #define H5VM_vector_gt_u(N, V1, V2) (H5VM_vector_cmp_u(N, V1, V2) > 0)
38 #define H5VM_vector_le_u(N, V1, V2) (H5VM_vector_cmp_u(N, V1, V2) <= 0)
39 #define H5VM_vector_ge_u(N, V1, V2) (H5VM_vector_cmp_u(N, V1, V2) >= 0)
40 
41 /* Other functions */
42 #define H5VM_vector_cpy(N, DST, SRC)                                                                         \
43     {                                                                                                        \
44         HDassert(sizeof(*(DST)) == sizeof(*(SRC)));                                                          \
45         if (SRC)                                                                                             \
46             H5MM_memcpy(DST, SRC, (N) * sizeof(*(DST)));                                                     \
47         else                                                                                                 \
48             HDmemset(DST, 0, (N) * sizeof(*(DST)));                                                          \
49     }
50 
51 #define H5VM_vector_zero(N, DST) HDmemset(DST, 0, (N) * sizeof(*(DST)))
52 
53 /* Given a coordinate offset array (COORDS) of type TYPE, move the unlimited
54  * dimension (UNLIM_DIM) value to offset 0, sliding any intermediate values down
55  * one position. */
56 #define H5VM_swizzle_coords(TYPE, COORDS, UNLIM_DIM)                                                         \
57     {                                                                                                        \
58         /* COORDS must be an array of type TYPE */                                                           \
59         HDassert(sizeof(COORDS[0]) == sizeof(TYPE));                                                         \
60                                                                                                              \
61         /* Nothing to do when unlimited dimension is at position 0 */                                        \
62         if (0 != (UNLIM_DIM)) {                                                                              \
63             TYPE _tmp = (COORDS)[UNLIM_DIM];                                                                 \
64                                                                                                              \
65             HDmemmove(&(COORDS)[1], &(COORDS)[0], sizeof(TYPE) * (UNLIM_DIM));                               \
66             (COORDS)[0] = _tmp;                                                                              \
67         } /* end if */                                                                                       \
68     }
69 
70 /* Given a coordinate offset array (COORDS) of type TYPE, move the value at
71  * offset 0 to offset of the unlimied dimension (UNLIM_DIM), sliding any
72  * intermediate values up one position.  Undoes the "swizzle_coords" operation.
73  */
74 #define H5VM_unswizzle_coords(TYPE, COORDS, UNLIM_DIM)                                                       \
75     {                                                                                                        \
76         /* COORDS must be an array of type TYPE */                                                           \
77         HDassert(sizeof(COORDS[0]) == sizeof(TYPE));                                                         \
78                                                                                                              \
79         /* Nothing to do when unlimited dimension is at position 0 */                                        \
80         if (0 != (UNLIM_DIM)) {                                                                              \
81             TYPE _tmp = (COORDS)[0];                                                                         \
82                                                                                                              \
83             HDmemmove(&(COORDS)[0], &(COORDS)[1], sizeof(TYPE) * (UNLIM_DIM));                               \
84             (COORDS)[UNLIM_DIM] = _tmp;                                                                      \
85         } /* end if */                                                                                       \
86     }
87 
88 /* A null pointer is equivalent to a zero vector */
89 #define H5VM_ZERO NULL
90 
91 H5_DLL hsize_t H5VM_hyper_stride(unsigned n, const hsize_t *size, const hsize_t *total_size,
92                                  const hsize_t *offset, hsize_t *stride);
93 H5_DLL htri_t  H5VM_hyper_eq(unsigned n, const hsize_t *offset1, const hsize_t *size1, const hsize_t *offset2,
94                              const hsize_t *size2);
95 H5_DLL herr_t  H5VM_hyper_fill(unsigned n, const hsize_t *_size, const hsize_t *total_size,
96                                const hsize_t *offset, void *_dst, unsigned fill_value);
97 H5_DLL herr_t  H5VM_hyper_copy(unsigned n, const hsize_t *size, const hsize_t *dst_total_size,
98                                const hsize_t *dst_offset, void *_dst, const hsize_t *src_total_size,
99                                const hsize_t *src_offset, const void *_src);
100 H5_DLL herr_t  H5VM_stride_fill(unsigned n, hsize_t elmt_size, const hsize_t *size, const hsize_t *stride,
101                                 void *_dst, unsigned fill_value);
102 H5_DLL herr_t H5VM_stride_copy(unsigned n, hsize_t elmt_size, const hsize_t *_size, const hsize_t *dst_stride,
103                                void *_dst, const hsize_t *src_stride, const void *_src);
104 H5_DLL herr_t H5VM_stride_copy_s(unsigned n, hsize_t elmt_size, const hsize_t *_size,
105                                  const hssize_t *dst_stride, void *_dst, const hssize_t *src_stride,
106                                  const void *_src);
107 H5_DLL herr_t H5VM_array_fill(void *_dst, const void *src, size_t size, size_t count);
108 H5_DLL void   H5VM_array_down(unsigned n, const hsize_t *total_size, hsize_t *down);
109 H5_DLL hsize_t H5VM_array_offset_pre(unsigned n, const hsize_t *acc, const hsize_t *offset);
110 H5_DLL hsize_t H5VM_array_offset(unsigned n, const hsize_t *total_size, const hsize_t *offset);
111 H5_DLL herr_t  H5VM_array_calc_pre(hsize_t offset, unsigned n, const hsize_t *down, hsize_t *coords);
112 H5_DLL herr_t  H5VM_array_calc(hsize_t offset, unsigned n, const hsize_t *total_size, hsize_t *coords);
113 H5_DLL hsize_t H5VM_chunk_index(unsigned ndims, const hsize_t *coord, const uint32_t *chunk,
114                                 const hsize_t *down_nchunks);
115 H5_DLL void H5VM_chunk_scaled(unsigned ndims, const hsize_t *coord, const uint32_t *chunk, hsize_t *scaled);
116 H5_DLL hsize_t H5VM_chunk_index_scaled(unsigned ndims, const hsize_t *coord, const uint32_t *chunk,
117                                        const hsize_t *down_nchunks, hsize_t *scaled);
118 H5_DLL ssize_t H5VM_opvv(size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[],
119                          hsize_t dst_off_arr[], size_t src_max_nseq, size_t *src_curr_seq,
120                          size_t src_len_arr[], hsize_t src_off_arr[], H5VM_opvv_func_t op, void *op_data);
121 H5_DLL ssize_t H5VM_memcpyvv(void *_dst, size_t dst_max_nseq, size_t *dst_curr_seq, size_t dst_len_arr[],
122                              hsize_t dst_off_arr[], const void *_src, size_t src_max_nseq,
123                              size_t *src_curr_seq, size_t src_len_arr[], hsize_t src_off_arr[]);
124 
125 /*-------------------------------------------------------------------------
126  * Function:    H5VM_vector_reduce_product
127  *
128  * Purpose:     Product reduction of a vector.  Vector elements and return
129  *              value are size_t because we usually want the number of
130  *              elements in an array and array dimensions are always of type
131  *              size_t.
132  *
133  * Note:        Although this routine is 'static' in this file, that's intended
134  *              only as an optimization and the naming (with a single underscore)
135  *              reflects its inclusion in a "private" header file.
136  *
137  * Return:      Success:        Product of elements
138  *
139  *              Failure:        1 if N is zero
140  *
141  * Programmer:  Robb Matzke
142  *              Friday, October 10, 1997
143  *
144  *-------------------------------------------------------------------------
145  */
146 static inline hsize_t H5_ATTR_UNUSED
H5VM_vector_reduce_product(unsigned n,const hsize_t * v)147 H5VM_vector_reduce_product(unsigned n, const hsize_t *v)
148 {
149     hsize_t ret_value = 1;
150 
151     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
152     FUNC_ENTER_NOAPI_NOINIT_NOERR
153 
154     if (n && !v)
155         HGOTO_DONE(0)
156     while (n--)
157         ret_value *= *v++;
158 
159 done:
160     FUNC_LEAVE_NOAPI(ret_value)
161 }
162 
163 /*-------------------------------------------------------------------------
164  * Function:    H5VM_vector_zerop_u
165  *
166  * Purpose:     Determines if all elements of a vector are zero.
167  *
168  * Note:        Although this routine is 'static' in this file, that's intended
169  *              only as an optimization and the naming (with a single underscore)
170  *              reflects its inclusion in a "private" header file.
171  *
172  * Return:      Success:        TRUE if all elements are zero,
173  *                              FALSE otherwise
174  *
175  *              Failure:        TRUE if N is zero
176  *
177  * Programmer:  Robb Matzke
178  *              Friday, October 10, 1997
179  *
180  *-------------------------------------------------------------------------
181  */
182 static inline htri_t H5_ATTR_UNUSED
H5VM_vector_zerop_u(int n,const hsize_t * v)183 H5VM_vector_zerop_u(int n, const hsize_t *v)
184 {
185     htri_t ret_value = TRUE; /* Return value */
186 
187     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
188     FUNC_ENTER_NOAPI_NOINIT_NOERR
189 
190     if (!v)
191         HGOTO_DONE(TRUE)
192     while (n--)
193         if (*v++)
194             HGOTO_DONE(FALSE)
195 
196 done:
197     FUNC_LEAVE_NOAPI(ret_value)
198 }
199 
200 /*-------------------------------------------------------------------------
201  * Function:    H5VM_vector_zerop_s
202  *
203  * Purpose:     Determines if all elements of a vector are zero.
204  *
205  * Note:        Although this routine is 'static' in this file, that's intended
206  *              only as an optimization and the naming (with a single underscore)
207  *              reflects its inclusion in a "private" header file.
208  *
209  * Return:      Success:        TRUE if all elements are zero,
210  *                              FALSE otherwise
211  *
212  *              Failure:        TRUE if N is zero
213  *
214  * Programmer:  Robb Matzke
215  *              Friday, October 10, 1997
216  *
217  *-------------------------------------------------------------------------
218  */
219 static inline htri_t H5_ATTR_UNUSED
H5VM_vector_zerop_s(int n,const hssize_t * v)220 H5VM_vector_zerop_s(int n, const hssize_t *v)
221 {
222     htri_t ret_value = TRUE; /* Return value */
223 
224     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
225     FUNC_ENTER_NOAPI_NOINIT_NOERR
226 
227     if (!v)
228         HGOTO_DONE(TRUE)
229     while (n--)
230         if (*v++)
231             HGOTO_DONE(FALSE)
232 
233 done:
234     FUNC_LEAVE_NOAPI(ret_value)
235 }
236 
237 /*-------------------------------------------------------------------------
238  * Function:    H5VM_vector_cmp_u
239  *
240  * Purpose:     Compares two vectors of the same size and determines if V1 is
241  *              lexicographically less than, equal, or greater than V2.
242  *
243  * Note:        Although this routine is 'static' in this file, that's intended
244  *              only as an optimization and the naming (with a single underscore)
245  *              reflects its inclusion in a "private" header file.
246  *
247  * Return:      Success:        -1 if V1 is less than V2
248  *                              0 if they are equal
249  *                              1 if V1 is greater than V2
250  *
251  *              Failure:        0 if N is zero
252  *
253  * Programmer:  Robb Matzke
254  *              Friday, October 10, 1997
255  *
256  *-------------------------------------------------------------------------
257  */
258 static inline int H5_ATTR_UNUSED
H5VM_vector_cmp_u(unsigned n,const hsize_t * v1,const hsize_t * v2)259 H5VM_vector_cmp_u(unsigned n, const hsize_t *v1, const hsize_t *v2)
260 {
261     int ret_value = 0; /* Return value */
262 
263     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
264     FUNC_ENTER_NOAPI_NOINIT_NOERR
265 
266     if (v1 == v2)
267         HGOTO_DONE(0)
268     if (v1 == NULL)
269         HGOTO_DONE(-1)
270     if (v2 == NULL)
271         HGOTO_DONE(1)
272     while (n--) {
273         if (*v1 < *v2)
274             HGOTO_DONE(-1)
275         if (*v1 > *v2)
276             HGOTO_DONE(1)
277         v1++;
278         v2++;
279     }
280 
281 done:
282     FUNC_LEAVE_NOAPI(ret_value)
283 }
284 
285 /*-------------------------------------------------------------------------
286  * Function:    H5VM_vector_cmp_s
287  *
288  * Purpose:     Compares two vectors of the same size and determines if V1 is
289  *              lexicographically less than, equal, or greater than V2.
290  *
291  * Note:        Although this routine is 'static' in this file, that's intended
292  *              only as an optimization and the naming (with a single underscore)
293  *              reflects its inclusion in a "private" header file.
294  *
295  * Return:      Success:        -1 if V1 is less than V2
296  *                              0 if they are equal
297  *                              1 if V1 is greater than V2
298  *
299  *              Failure:        0 if N is zero
300  *
301  * Programmer:  Robb Matzke
302  *              Wednesday, April  8, 1998
303  *
304  *-------------------------------------------------------------------------
305  */
306 static inline int H5_ATTR_UNUSED
H5VM_vector_cmp_s(unsigned n,const hssize_t * v1,const hssize_t * v2)307 H5VM_vector_cmp_s(unsigned n, const hssize_t *v1, const hssize_t *v2)
308 {
309     int ret_value = 0; /* Return value */
310 
311     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
312     FUNC_ENTER_NOAPI_NOINIT_NOERR
313 
314     if (v1 == v2)
315         HGOTO_DONE(0)
316     if (v1 == NULL)
317         HGOTO_DONE(-1)
318     if (v2 == NULL)
319         HGOTO_DONE(1)
320     while (n--) {
321         if (*v1 < *v2)
322             HGOTO_DONE(-1)
323         if (*v1 > *v2)
324             HGOTO_DONE(1)
325         v1++;
326         v2++;
327     }
328 
329 done:
330     FUNC_LEAVE_NOAPI(ret_value)
331 }
332 
333 /*-------------------------------------------------------------------------
334  * Function:    H5VM_vector_inc
335  *
336  * Purpose:     Increments V1 by V2
337  *
338  * Note:        Although this routine is 'static' in this file, that's intended
339  *              only as an optimization and the naming (with a single underscore)
340  *              reflects its inclusion in a "private" header file.
341  *
342  * Return:      void
343  *
344  * Programmer:  Robb Matzke
345  *              Monday, October 13, 1997
346  *
347  *-------------------------------------------------------------------------
348  */
349 static inline void H5_ATTR_UNUSED
H5VM_vector_inc(int n,hsize_t * v1,const hsize_t * v2)350 H5VM_vector_inc(int n, hsize_t *v1, const hsize_t *v2)
351 {
352     while (n--)
353         *v1++ += *v2++;
354 }
355 
356 /* Lookup table for general log2(n) routine */
357 static const unsigned char LogTable256[] = {
358     /* clang-clang-format off */
359     0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
360     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
361     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
362     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7,
363     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
364     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
365     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
366     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
367     /* clang-clang-format on */
368 };
369 
370 /*-------------------------------------------------------------------------
371  * Function:    H5VM_log2_gen
372  *
373  * Purpose:     Determines the log base two of a number (i.e. log2(n)).
374  *              (i.e. the highest bit set in a number)
375  *
376  * Note:        This is from the "Bit Twiddling Hacks" at:
377  *                  http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
378  *
379  *              The version on the web-site is for 32-bit quantities and this
380  *              version has been extended for 64-bit quantities.
381  *
382  * Note:        Although this routine is 'static' in this file, that's intended
383  *              only as an optimization and the naming (with a single underscore)
384  *              reflects its inclusion in a "private" header file.
385  *
386  * Return:      log2(n) (always - no failure condition)
387  *
388  * Programmer:  Quincey Koziol
389  *              Monday, March  6, 2006
390  *
391  *-------------------------------------------------------------------------
392  */
393 static inline unsigned H5_ATTR_UNUSED
H5VM_log2_gen(uint64_t n)394 H5VM_log2_gen(uint64_t n)
395 {
396     unsigned              r;          /* r will be log2(n) */
397     register unsigned int t, tt, ttt; /* temporaries */
398 
399     if ((ttt = (unsigned)(n >> 32)))
400         if ((tt = (unsigned)(n >> 48)))
401             r = (t = (unsigned)(n >> 56)) ? 56 + (unsigned)LogTable256[t]
402                                           : 48 + (unsigned)LogTable256[tt & 0xFF];
403         else
404             r = (t = (unsigned)(n >> 40)) ? 40 + (unsigned)LogTable256[t]
405                                           : 32 + (unsigned)LogTable256[ttt & 0xFF];
406     else if ((tt = (unsigned)(n >> 16)))
407         r = (t = (unsigned)(n >> 24)) ? 24 + (unsigned)LogTable256[t] : 16 + (unsigned)LogTable256[tt & 0xFF];
408     else
409         /* Added 'uint8_t' cast to pacify PGCC compiler */
410         r = (t = (unsigned)(n >> 8)) ? 8 + (unsigned)LogTable256[t] : (unsigned)LogTable256[(uint8_t)n];
411 
412     return (r);
413 } /* H5VM_log2_gen() */
414 
415 /* Lookup table for specialized log2(n) of power of two routine */
416 static const unsigned MultiplyDeBruijnBitPosition[32] = {0,  1,  28, 2,  29, 14, 24, 3,  30, 22, 20,
417                                                          15, 25, 17, 4,  8,  31, 27, 13, 23, 21, 19,
418                                                          16, 7,  26, 12, 18, 6,  11, 5,  10, 9};
419 
420 /*-------------------------------------------------------------------------
421  * Function:    H5VM_log2_of2
422  *
423  * Purpose:     Determines the log base two of a number (i.e. log2(n)).
424  *              (i.e. the highest bit set in a number)
425  *
426  * Note:        **N must be a power of two** and is limited to 32-bit quantities.
427  *
428  *              This is from the "Bit Twiddling Hacks" at:
429  *                  http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
430  *
431  * Note:        Although this routine is 'static' in this file, that's intended
432  *              only as an optimization and the naming (with a single underscore)
433  *              reflects its inclusion in a "private" header file.
434  *
435  * Return:      log2(n) (always - no failure condition)
436  *
437  * Programmer:  Quincey Koziol
438  *              Monday, Febraury 27, 2006
439  *
440  *-------------------------------------------------------------------------
441  */
442 static inline H5_ATTR_PURE unsigned
H5VM_log2_of2(uint32_t n)443 H5VM_log2_of2(uint32_t n)
444 {
445 #ifndef NDEBUG
446     HDassert(POWER_OF_TWO(n));
447 #endif /* NDEBUG */
448     return (MultiplyDeBruijnBitPosition[(n * (uint32_t)0x077CB531UL) >> 27]);
449 } /* H5VM_log2_of2() */
450 
451 /*-------------------------------------------------------------------------
452  * Function:    H5VM_power2up
453  *
454  * Purpose:    Round up a number to the next power of 2
455  *
456  * Note:        Although this routine is 'static' in this file, that's intended
457  *              only as an optimization and the naming (with a single underscore)
458  *              reflects its inclusion in a "private" header file.
459  *
460  * Return:    Return the number which is a power of 2
461  *
462  * Programmer:    Vailin Choi; Nov 2014
463  *
464  *-------------------------------------------------------------------------
465  */
466 static inline H5_ATTR_CONST hsize_t
H5VM_power2up(hsize_t n)467 H5VM_power2up(hsize_t n)
468 {
469     hsize_t ret_value = 1; /* Return value */
470 
471     /* Returns 0 when n exceeds 2^63 */
472     if (n >= (hsize_t)1 << ((sizeof(hsize_t) * CHAR_BIT) - 1))
473         ret_value = 0;
474 
475     while (ret_value && ret_value < n)
476         ret_value <<= 1;
477 
478     return (ret_value);
479 } /* H5VM_power2up */
480 
481 /*-------------------------------------------------------------------------
482  * Function:    H5VM_limit_enc_size
483  *
484  * Purpose:     Determine the # of bytes needed to encode values within a
485  *              range from 0 to a given limit
486  *
487  * Note:        Although this routine is 'static' in this file, that's intended
488  *              only as an optimization and the naming (with a single underscore)
489  *              reflects its inclusion in a "private" header file.
490  *
491  * Return:      Number of bytes needed
492  *
493  * Programmer:  Quincey Koziol
494  *              Thursday, March 13, 2008
495  *
496  *-------------------------------------------------------------------------
497  */
498 static inline unsigned H5_ATTR_UNUSED
H5VM_limit_enc_size(uint64_t limit)499 H5VM_limit_enc_size(uint64_t limit)
500 {
501     return (H5VM_log2_gen(limit) / 8) + 1;
502 } /* end H5VM_limit_enc_size() */
503 
504 static const unsigned char H5VM_bit_set_g[8]   = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
505 static const unsigned char H5VM_bit_clear_g[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
506 
507 /*-------------------------------------------------------------------------
508  * Function:    H5VM_bit_get
509  *
510  * Purpose:     Determine the value of the n'th bit in a buffer.
511  *
512  * Note:        No range checking on <offset> is performed!
513  *
514  * Note #2:     Bits are sequentially stored in the buffer, starting with bit
515  *              offset 0 in the first byte's high-bit position, proceeding down
516  *              to bit offset 7 in the first byte's low-bit position, then to
517  *              bit offset 8 in the second byte's high-bit position, etc.
518  *
519  * Note:        Although this routine is 'static' in this file, that's intended
520  *              only as an optimization and the naming (with a single underscore)
521  *              reflects its inclusion in a "private" header file.
522  *
523  * Return:      TRUE/FALSE
524  *
525  * Programmer:  Quincey Koziol
526  *              Tuesday, November 25, 2008
527  *
528  *-------------------------------------------------------------------------
529  */
530 static inline hbool_t H5_ATTR_UNUSED
H5VM_bit_get(const unsigned char * buf,size_t offset)531 H5VM_bit_get(const unsigned char *buf, size_t offset)
532 {
533     /* Test the appropriate bit in the buffer */
534     return (hbool_t)((buf[offset / 8] & (H5VM_bit_set_g[offset % 8])) ? TRUE : FALSE);
535 } /* end H5VM_bit_get() */
536 
537 /*-------------------------------------------------------------------------
538  * Function:    H5VM_bit_set
539  *
540  * Purpose:     Set/reset the n'th bit in a buffer.
541  *
542  * Note:        No range checking on <offset> is performed!
543  *
544  * Note #2:     Bits are sequentially stored in the buffer, starting with bit
545  *              offset 0 in the first byte's high-bit position, proceeding down
546  *              to bit offset 7 in the first byte's low-bit position, then to
547  *              bit offset 8 in the second byte's high-bit position, etc.
548  *
549  * Note:        Although this routine is 'static' in this file, that's intended
550  *              only as an optimization and the naming (with a single underscore)
551  *              reflects its inclusion in a "private" header file.
552  *
553  * Return:      None
554  *
555  * Programmer:  Quincey Koziol
556  *              Tuesday, November 25, 2008
557  *
558  *-------------------------------------------------------------------------
559  */
560 static inline void H5_ATTR_UNUSED
H5VM_bit_set(unsigned char * buf,size_t offset,hbool_t val)561 H5VM_bit_set(unsigned char *buf, size_t offset, hbool_t val)
562 {
563     /* Set/reset the appropriate bit in the buffer */
564     if (val)
565         buf[offset / 8] |= H5VM_bit_set_g[offset % 8];
566     else
567         buf[offset / 8] &= H5VM_bit_clear_g[offset % 8];
568 } /* end H5VM_bit_set() */
569 
570 #endif /* H5VMprivate_H */
571