diff options
Diffstat (limited to 'src/H5encode.h')
-rw-r--r-- | src/H5encode.h | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/src/H5encode.h b/src/H5encode.h new file mode 100644 index 0000000..a9172ff --- /dev/null +++ b/src/H5encode.h @@ -0,0 +1,287 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * File-independent encode/decode routines + */ + +#ifndef H5encode_H +#define H5encode_H + +/**************************/ +/* Library Private Macros */ +/**************************/ + +/* + * Encode and decode macros for file meta-data. + * Currently, all file meta-data is little-endian. + */ + +#define INT16ENCODE(p, i) \ + do { \ + *(p) = (uint8_t)((unsigned)(i)&0xff); \ + (p)++; \ + *(p) = (uint8_t)(((unsigned)(i) >> 8) & 0xff); \ + (p)++; \ + } while (0) + +#define UINT16ENCODE(p, i) \ + do { \ + *(p) = (uint8_t)((unsigned)(i)&0xff); \ + (p)++; \ + *(p) = (uint8_t)(((unsigned)(i) >> 8) & 0xff); \ + (p)++; \ + } while (0) + +#define INT32ENCODE(p, i) \ + do { \ + *(p) = (uint8_t)((uint32_t)(i)&0xff); \ + (p)++; \ + *(p) = (uint8_t)(((uint32_t)(i) >> 8) & 0xff); \ + (p)++; \ + *(p) = (uint8_t)(((uint32_t)(i) >> 16) & 0xff); \ + (p)++; \ + *(p) = (uint8_t)(((uint32_t)(i) >> 24) & 0xff); \ + (p)++; \ + } while (0) + +#define UINT32ENCODE(p, i) \ + do { \ + *(p) = (uint8_t)((i)&0xff); \ + (p)++; \ + *(p) = (uint8_t)(((i) >> 8) & 0xff); \ + (p)++; \ + *(p) = (uint8_t)(((i) >> 16) & 0xff); \ + (p)++; \ + *(p) = (uint8_t)(((i) >> 24) & 0xff); \ + (p)++; \ + } while (0) + +/* Encode an unsigned integer into a variable-sized buffer */ +/* (Assumes that the high bits of the integer are zero) */ +#define ENCODE_VAR(p, typ, n, l) \ + do { \ + typ _n = (n); \ + size_t _i; \ + uint8_t *_p = (uint8_t *)(p); \ + \ + for (_i = 0; _i < l; _i++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + (p) = (uint8_t *)(p) + l; \ + } while (0) + +/* Encode a 32-bit unsigned integer into a variable-sized buffer */ +/* (Assumes that the high bits of the integer are zero) */ +#define UINT32ENCODE_VAR(p, n, l) ENCODE_VAR(p, uint32_t, n, l) + +#define INT64ENCODE(p, n) \ + do { \ + int64_t _n = (n); \ + size_t _i; \ + uint8_t *_p = (uint8_t *)(p); \ + \ + for (_i = 0; _i < sizeof(int64_t); _i++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + for (/*void*/; _i < 8; _i++) \ + *_p++ = (uint8_t)((n) < 0 ? 0xff : 0); \ + (p) = (uint8_t *)(p) + 8; \ + } while (0) + +#define UINT64ENCODE(p, n) \ + do { \ + uint64_t _n = (n); \ + size_t _i; \ + uint8_t *_p = (uint8_t *)(p); \ + \ + for (_i = 0; _i < sizeof(uint64_t); _i++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + for (/*void*/; _i < 8; _i++) \ + *_p++ = 0; \ + (p) = (uint8_t *)(p) + 8; \ + } while (0) + +/* Encode a 64-bit unsigned integer into a variable-sized buffer */ +/* (Assumes that the high bits of the integer are zero) */ +#define UINT64ENCODE_VAR(p, n, l) ENCODE_VAR(p, uint64_t, n, l) + +#define H5_ENCODE_UNSIGNED(p, n) \ + do { \ + HDcompile_assert(sizeof(unsigned) == sizeof(uint32_t)); \ + UINT32ENCODE(p, n); \ + } while (0) + +/* Assumes the endianness of uint64_t is the same as double */ +#define H5_ENCODE_DOUBLE(p, n) \ + do { \ + uint64_t _n; \ + size_t _u; \ + uint8_t *_p = (uint8_t *)(p); \ + \ + HDcompile_assert(sizeof(double) == 8); \ + HDcompile_assert(sizeof(double) == sizeof(uint64_t)); \ + memcpy(&_n, &n, sizeof(double)); \ + for (_u = 0; _u < sizeof(uint64_t); _u++, _n >>= 8) \ + *_p++ = (uint8_t)(_n & 0xff); \ + (p) = (uint8_t *)(p) + 8; \ + } while (0) + +/* DECODE converts little endian bytes pointed by p to integer values and store + * it in i. For signed values, need to do sign-extension when converting + * the last byte which carries the sign bit. + * The macros does not require i be of a certain byte sizes. It just requires + * i be big enough to hold the intended value range. E.g. INT16DECODE works + * correctly even if i is actually a 64bit int like in a Cray. + */ + +#define INT16DECODE(p, i) \ + do { \ + (i) = (int16_t)((*(p)&0xff)); \ + (p)++; \ + (i) |= (int16_t)(((*(p)&0xff) << 8) | ((*(p)&0x80) ? ~0xffff : 0x0)); \ + (p)++; \ + } while (0) + +#define UINT16DECODE(p, i) \ + do { \ + (i) = (uint16_t)(*(p)&0xff); \ + (p)++; \ + (i) |= (uint16_t)((*(p)&0xff) << 8); \ + (p)++; \ + } while (0) + +#define INT32DECODE(p, i) \ + do { \ + (i) = ((int32_t)(*(p)&0xff)); \ + (p)++; \ + (i) |= ((int32_t)(*(p)&0xff) << 8); \ + (p)++; \ + (i) |= ((int32_t)(*(p)&0xff) << 16); \ + (p)++; \ + (i) |= ((int32_t)(((*(p) & (unsigned)0xff) << 24) | ((*(p)&0x80) ? ~0xffffffffULL : 0x0ULL))); \ + (p)++; \ + } while (0) + +#define UINT32DECODE(p, i) \ + do { \ + (i) = (uint32_t)(*(p)&0xff); \ + (p)++; \ + (i) |= ((uint32_t)(*(p)&0xff) << 8); \ + (p)++; \ + (i) |= ((uint32_t)(*(p)&0xff) << 16); \ + (p)++; \ + (i) |= ((uint32_t)(*(p)&0xff) << 24); \ + (p)++; \ + } while (0) + +/* Decode a variable-sized buffer */ +/* (Assumes that the high bits of the integer will be zero) */ +#define DECODE_VAR(p, n, l) \ + do { \ + size_t _i; \ + \ + n = 0; \ + (p) += l; \ + for (_i = 0; _i < l; _i++) \ + n = (n << 8) | *(--p); \ + (p) += l; \ + } while (0) + +/* Decode a variable-sized buffer into a 32-bit unsigned integer */ +/* (Assumes that the high bits of the integer will be zero) */ +#define UINT32DECODE_VAR(p, n, l) DECODE_VAR(p, n, l) + +#define INT64DECODE(p, n) \ + do { \ + /* WE DON'T CHECK FOR OVERFLOW! */ \ + size_t _i; \ + \ + n = 0; \ + (p) += 8; \ + for (_i = 0; _i < sizeof(int64_t); _i++) \ + n = (n << 8) | *(--p); \ + (p) += 8; \ + } while (0) + +#define UINT64DECODE(p, n) \ + do { \ + /* WE DON'T CHECK FOR OVERFLOW! */ \ + size_t _i; \ + \ + n = 0; \ + (p) += 8; \ + for (_i = 0; _i < sizeof(uint64_t); _i++) \ + n = (n << 8) | *(--p); \ + (p) += 8; \ + } while (0) + +/* Decode a variable-sized buffer into a 64-bit unsigned integer */ +/* (Assumes that the high bits of the integer will be zero) */ +#define UINT64DECODE_VAR(p, n, l) DECODE_VAR(p, n, l) + +#define H5_DECODE_UNSIGNED(p, n) \ + do { \ + HDcompile_assert(sizeof(unsigned) == sizeof(uint32_t)); \ + UINT32DECODE(p, n); \ + } while (0) + +/* Assumes the endianness of uint64_t is the same as double */ +#define H5_DECODE_DOUBLE(p, n) \ + do { \ + uint64_t _n; \ + size_t _u; \ + \ + HDcompile_assert(sizeof(double) == 8); \ + HDcompile_assert(sizeof(double) == sizeof(uint64_t)); \ + _n = 0; \ + (p) += 8; \ + for (_u = 0; _u < sizeof(uint64_t); _u++) \ + _n = (_n << 8) | *(--p); \ + memcpy(&(n), &_n, sizeof(double)); \ + (p) += 8; \ + } while (0) + +/* Macros to encode/decode offset/length's for storing in the file */ +#define H5_ENCODE_LENGTH_LEN(p, l, s) \ + do { \ + switch (s) { \ + case 4: \ + UINT32ENCODE(p, l); \ + break; \ + case 8: \ + UINT64ENCODE(p, l); \ + break; \ + case 2: \ + UINT16ENCODE(p, l); \ + break; \ + default: \ + assert("bad sizeof size" && 0); \ + } \ + } while (0) + +#define H5_DECODE_LENGTH_LEN(p, l, s) \ + do { \ + switch (s) { \ + case 4: \ + UINT32DECODE(p, l); \ + break; \ + case 8: \ + UINT64DECODE(p, l); \ + break; \ + case 2: \ + UINT16DECODE(p, l); \ + break; \ + default: \ + assert("bad sizeof size" && 0); \ + } \ + } while (0) + +#endif /* H5encode_H */ |