#pragma once #include // _BIDSCLASS _EXPCLASS #include #include #define PUT_8(x, buf, shift) WriteUnaligned((buf)++, (x) >> (shift)) #define GET_8_OR(x, buf, type, shift) (x) |= (type) * (buf)++ << (shift) #if defined(_big_endian_) #define LO_SHIFT 1 #define HI_SHIFT 0 #elif defined(_little_endian_) #define LO_SHIFT 0 #define HI_SHIFT 1 #endif #if !defined(_must_align2_) #define PUT_16(x, buf, shift) WriteUnaligned(buf, (x) >> (shift)), (buf) += 2 #define GET_16_OR(x, buf, type, shift) (x) |= (type)ReadUnaligned(buf) << (shift), (buf) += 2 #else #define PUT_16(x, buf, shift) PUT_8(x, buf, shift + 8 * LO_SHIFT), PUT_8(x, buf, shift + 8 * HI_SHIFT) #define GET_16_OR(x, buf, type, shift) GET_8_OR(x, buf, type, shift + 8 * LO_SHIFT), GET_8_OR(x, buf, type, shift + 8 * HI_SHIFT) #endif #if !defined(_must_align4_) #define PUT_32(x, buf, shift) WriteUnaligned(buf, (x) >> (shift)), (buf) += 4 #define GET_32_OR(x, buf, type, shift) (x) |= (type)ReadUnaligned(buf) << (shift), (buf) += 4 #else #define PUT_32(x, buf, shift) PUT_16(x, buf, shift + 16 * LO_SHIFT), PUT_16(x, buf, shift + 16 * HI_SHIFT) #define GET_32_OR(x, buf, type, shift) GET_16_OR(x, buf, type, shift + 16 * LO_SHIFT), GET_16_OR(x, buf, type, shift + 16 * HI_SHIFT) #endif #if !defined(_must_align8_) #define PUT_64(x, buf, shift) WriteUnaligned(buf, (x) >> (shift)), (buf) += 8 #define GET_64_OR(x, buf, type, shift) (x) |= (type)ReadUnaligned(buf) << (shift), (buf) += 8 #else #define PUT_64(x, buf, shift) PUT_32(x, buf, shift + 32 * LO_SHIFT), PUT_32(x, buf, shift + 32 * HI_SHIFT) #define GET_64_OR(x, buf, type, shift) GET_32_OR(x, buf, type, shift + 32 * LO_SHIFT), GET_32_OR(x, buf, type, shift + 32 * HI_SHIFT) #endif struct mem_traits { static ui8 get_8(const char*& mem) { ui8 x = 0; GET_8_OR(x, mem, ui8, 0); return x; } static ui16 get_16(const char*& mem) { ui16 x = 0; GET_16_OR(x, mem, ui16, 0); return x; } static ui32 get_32(const char*& mem) { ui32 x = 0; GET_32_OR(x, mem, ui32, 0); return x; } static void put_8(ui8 x, char*& mem) { PUT_8(x, mem, 0); } static void put_16(ui16 x, char*& mem) { PUT_16(x, mem, 0); } static void put_32(ui32 x, char*& mem) { PUT_32(x, mem, 0); } static int is_good(char*&) { return 1; } }; /* |____|____|____|____|____|____|____|____|____|____|____|____|____|____|8***|**** |____|____|____|____|____|____|____|____|____|____|____|____|i4**|****|****|**** |____|____|____|____|____|____|____|____|____|____|ii2*|****|****|****|****|**** |____|____|____|____|____|____|____|____|iii1|****|****|****|****|****|****|**** |____|____|____|____|____|____|iiii|8***|****|****|****|****|****|****|****|**** |____|____|____|____|iiii|i4**|****|****|****|****|****|****|****|****|****|**** |____|____|iiii|ii2*|****|****|****|****|****|****|****|****|****|****|****|**** |iiii|iii1|****|****|****|****|****|****|****|****|****|****|****|****|****|**** */ #define PACK1LIM 0x80u #define PACK2LIM 0x4000u #define PACK3LIM 0x200000u #define PACK4LIM 0x10000000u #define PACK5LIM 0x800000000ull #define PACK6LIM 0x40000000000ull #define PACK7LIM 0x2000000000000ull #define PACK8LIM 0x100000000000000ull #define MY_14(x) ((ui16)(x) < PACK1LIM ? 1 : 2) #define MY_28(x) ((ui32)(x) < PACK2LIM ? MY_14(x) : ((ui32)(x) < PACK3LIM ? 3 : 4)) #define MY_32(x) ((ui32)(x) < PACK4LIM ? MY_28(x) : 5) #define MY_64(x) ((ui64)(x) < PACK4LIM ? MY_28(x) : ((ui64)(x) < PACK6LIM ? ((ui64)(x) < PACK5LIM ? 5 : 6) : ((ui64)(x) < PACK7LIM ? 7 : ((ui64)(x) < PACK8LIM ? 8 : 9)))) #if !defined(MACRO_BEGIN) #define MACRO_BEGIN do { #define MACRO_END \ } \ while (0) #endif #define PACK_14(x, buf, how, ret) \ MACRO_BEGIN \ if ((ui16)(x) < PACK1LIM) { \ how::put_8((ui8)(x), (buf)); \ (ret) = 1; \ } else { \ how::put_8((ui8)(0x80 | (x) >> 8), (buf)); \ how::put_8((ui8)(x), (buf)); \ (ret) = 2; \ } \ MACRO_END #define PACK_28(x, buf, how, ret) \ MACRO_BEGIN \ if ((ui32)(x) < PACK2LIM) { \ PACK_14(x, buf, how, ret); \ } else { \ if ((ui32)(x) < PACK3LIM) { \ how::put_8((ui8)(0xC0 | (x) >> 16), buf); \ (ret) = 3; \ } else { \ how::put_8((ui8)(0xE0 | (x) >> 24), buf); \ how::put_8((ui8)((x) >> 16), buf); \ (ret) = 4; \ } \ how::put_16((ui16)(x), (buf)); \ } \ MACRO_END #define PACK_32(x, buf, how, ret) \ MACRO_BEGIN \ if ((ui32)(x) < PACK4LIM) { \ PACK_28(x, buf, how, ret); \ } else { \ how::put_8((ui8)(0xF0), buf); \ how::put_32((ui32)(x), buf); \ (ret) = 5; \ } \ MACRO_END #define PACK_64(x, buf, how, ret) \ MACRO_BEGIN \ if ((ui64)(x) < PACK4LIM) { \ PACK_28((ui32)(x), buf, how, ret); \ } else { \ if ((ui64)(x) < PACK6LIM) { \ if ((ui64)(x) < PACK5LIM) { \ how::put_8((ui8)(0xF0 | (x) >> 32), buf); \ (ret) = 5; \ } else { \ how::put_8((ui8)(0xF8 | (x) >> 40), buf); \ how::put_8((ui8)((x) >> 32), buf); \ (ret) = 6; \ } \ } else { \ if ((ui64)(x) < PACK7LIM) { \ how::put_8((ui8)(0xFC | (x) >> 48), buf); \ (ret) = 7; \ } else { \ if ((ui64)(x) < PACK8LIM) { \ how::put_8((ui8)(0xFE | (x) >> 56), buf); \ how::put_8((ui8)((x) >> 48), buf); \ (ret) = 8; \ } else { \ how::put_8((ui8)(0xFF), buf); \ how::put_16((ui16)((x) >> 48), buf); \ (ret) = 9; \ } \ } \ how::put_16((ui16)((x) >> 32), buf); \ } \ how::put_32((ui32)(x), buf); \ } \ MACRO_END #define DO_UNPACK_14(firstByte, x, buf, how, ret) \ MACRO_BEGIN \ if (firstByte < 0x80) { \ (x) = (firstByte); \ (ret) = 1; \ } else { \ (x) = (firstByte & 0x7F) << 8; \ (x) |= how::get_8(buf); \ (ret) = 2; \ } \ MACRO_END #define UNPACK_14(x, buf, how, ret) \ MACRO_BEGIN \ ui8 firstByte = how::get_8(buf); \ DO_UNPACK_14(firstByte, x, buf, how, ret); \ MACRO_END #define DO_UNPACK_28(firstByte, x, buf, how, ret) \ MACRO_BEGIN \ if (firstByte < 0xC0) { \ DO_UNPACK_14(firstByte, x, buf, how, ret); \ } else { \ if (firstByte < 0xE0) { \ (x) = (firstByte & 0x3F) << 16; \ (ret) = 3; \ } else { \ (x) = (firstByte & 0x1F) << 24; \ (x) |= how::get_8(buf) << 16; \ (ret) = 4; \ } \ (x) |= how::get_16(buf); \ } \ MACRO_END #define UNPACK_28(x, buf, how, ret) \ MACRO_BEGIN \ ui8 firstByte = how::get_8(buf); \ DO_UNPACK_28(firstByte, x, buf, how, ret); \ MACRO_END #define DO_UNPACK_32(firstByte, x, buf, how, ret) \ MACRO_BEGIN \ if (firstByte < 0xF0) { \ DO_UNPACK_28(firstByte, x, buf, how, ret); \ } else { \ (x) = how::get_32(buf); \ (ret) = 5; \ } \ MACRO_END #define UNPACK_32(x, buf, how, ret) \ MACRO_BEGIN \ ui8 firstByte = how::get_8(buf); \ DO_UNPACK_32(firstByte, x, buf, how, ret); \ MACRO_END #define DO_UNPACK_64(firstByte, x, buf, how, ret) \ MACRO_BEGIN \ if (firstByte < 0xF0) { \ DO_UNPACK_28(firstByte, x, buf, how, ret); \ } else { \ if (firstByte < 0xFC) { \ if (firstByte < 0xF8) { \ (x) = (ui64)(firstByte & 0x0F) << 32; \ (ret) = 5; \ } else { \ (x) = (ui64)(firstByte & 0x07) << 40; \ (x) |= (ui64)how::get_8(buf) << 32; \ (ret) = 6; \ } \ } else { \ if (firstByte < 0xFE) { \ (x) = (ui64)(firstByte & 0x03) << 48; \ (ret) = 7; \ } else { \ if (firstByte < 0xFF) { \ (x) = (ui64)(firstByte & 0x01) << 56; \ (x) |= (ui64)how::get_8(buf) << 48; \ (ret) = 8; \ } else { \ (x) = (ui64)how::get_16(buf) << 48; \ (ret) = 9; \ } \ } \ (x) |= (ui64)how::get_16(buf) << 32; \ } \ (x) |= how::get_32(buf); \ } \ MACRO_END #define UNPACK_64(x, buf, how, ret) \ MACRO_BEGIN \ ui8 firstByte = how::get_8(buf); \ DO_UNPACK_64(firstByte, x, buf, how, ret); \ MACRO_END inline int in_long(i64& longVal, const char* ptrBuf) { int ret = 0; UNPACK_64(longVal, ptrBuf, mem_traits, ret); return ret; } inline int out_long(const i64& longVal, char* ptrBuf) { int ret = 0; PACK_64(longVal, ptrBuf, mem_traits, ret); /*7*/ return ret; } inline int len_long(const i64& longVal) { return MY_64(longVal); } inline int in_long(i32& longVal, const char* ptrBuf) { int ret = 0; UNPACK_32(longVal, ptrBuf, mem_traits, ret); return ret; } inline int out_long(const i32& longVal, char* ptrBuf) { int ret = 0; PACK_32(longVal, ptrBuf, mem_traits, ret); return ret; } inline int len_long(const i32& longVal) { return MY_32(longVal); } template inline const C* Unpack32(T& x, const C* src) { int pkLen = 0; const char* c = reinterpret_cast(src); Y_UNUSED(pkLen); UNPACK_32(x, c, mem_traits, pkLen); Y_ASSERT(pkLen); return reinterpret_cast(c); } template inline const C* Unpack64(T& x, const C* src) { int pkLen = 0; const char* c = reinterpret_cast(src); Y_UNUSED(pkLen); UNPACK_64(x, c, mem_traits, pkLen); Y_ASSERT(pkLen); return reinterpret_cast(c); } template inline C* Pack32(const T& x, C* dest) { int pkLen = 0; Y_UNUSED(pkLen); char* c = reinterpret_cast(dest); PACK_32(x, c, mem_traits, pkLen); Y_ASSERT(pkLen); return reinterpret_cast(c); } template inline C* Pack64(const T& x, C* dest) { int pkLen = 0; Y_UNUSED(pkLen); char* c = reinterpret_cast(dest); PACK_64(x, c, mem_traits, pkLen); Y_ASSERT(pkLen); return reinterpret_cast(c); }