longs.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #pragma once
  2. #include <util/system/defaults.h> // _BIDSCLASS _EXPCLASS
  3. #include <util/system/yassert.h>
  4. #include <util/system/unaligned_mem.h>
  5. #define PUT_8(x, buf, shift) WriteUnaligned<ui8>((buf)++, (x) >> (shift))
  6. #define GET_8_OR(x, buf, type, shift) (x) |= (type) * (buf)++ << (shift)
  7. #if defined(_big_endian_)
  8. #define LO_SHIFT 1
  9. #define HI_SHIFT 0
  10. #elif defined(_little_endian_)
  11. #define LO_SHIFT 0
  12. #define HI_SHIFT 1
  13. #endif
  14. #if !defined(_must_align2_)
  15. #define PUT_16(x, buf, shift) WriteUnaligned<ui16>(buf, (x) >> (shift)), (buf) += 2
  16. #define GET_16_OR(x, buf, type, shift) (x) |= (type)ReadUnaligned<ui16>(buf) << (shift), (buf) += 2
  17. #else
  18. #define PUT_16(x, buf, shift) PUT_8(x, buf, shift + 8 * LO_SHIFT), PUT_8(x, buf, shift + 8 * HI_SHIFT)
  19. #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)
  20. #endif
  21. #if !defined(_must_align4_)
  22. #define PUT_32(x, buf, shift) WriteUnaligned<ui32>(buf, (x) >> (shift)), (buf) += 4
  23. #define GET_32_OR(x, buf, type, shift) (x) |= (type)ReadUnaligned<ui32>(buf) << (shift), (buf) += 4
  24. #else
  25. #define PUT_32(x, buf, shift) PUT_16(x, buf, shift + 16 * LO_SHIFT), PUT_16(x, buf, shift + 16 * HI_SHIFT)
  26. #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)
  27. #endif
  28. #if !defined(_must_align8_)
  29. #define PUT_64(x, buf, shift) WriteUnaligned<ui64>(buf, (x) >> (shift)), (buf) += 8
  30. #define GET_64_OR(x, buf, type, shift) (x) |= (type)ReadUnaligned<ui64>(buf) << (shift), (buf) += 8
  31. #else
  32. #define PUT_64(x, buf, shift) PUT_32(x, buf, shift + 32 * LO_SHIFT), PUT_32(x, buf, shift + 32 * HI_SHIFT)
  33. #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)
  34. #endif
  35. struct mem_traits {
  36. static ui8 get_8(const char*& mem) {
  37. ui8 x = 0;
  38. GET_8_OR(x, mem, ui8, 0);
  39. return x;
  40. }
  41. static ui16 get_16(const char*& mem) {
  42. ui16 x = 0;
  43. GET_16_OR(x, mem, ui16, 0);
  44. return x;
  45. }
  46. static ui32 get_32(const char*& mem) {
  47. ui32 x = 0;
  48. GET_32_OR(x, mem, ui32, 0);
  49. return x;
  50. }
  51. static void put_8(ui8 x, char*& mem) {
  52. PUT_8(x, mem, 0);
  53. }
  54. static void put_16(ui16 x, char*& mem) {
  55. PUT_16(x, mem, 0);
  56. }
  57. static void put_32(ui32 x, char*& mem) {
  58. PUT_32(x, mem, 0);
  59. }
  60. static int is_good(char*&) {
  61. return 1;
  62. }
  63. };
  64. /*
  65. |____|____|____|____|____|____|____|____|____|____|____|____|____|____|8***|****
  66. |____|____|____|____|____|____|____|____|____|____|____|____|i4**|****|****|****
  67. |____|____|____|____|____|____|____|____|____|____|ii2*|****|****|****|****|****
  68. |____|____|____|____|____|____|____|____|iii1|****|****|****|****|****|****|****
  69. |____|____|____|____|____|____|iiii|8***|****|****|****|****|****|****|****|****
  70. |____|____|____|____|iiii|i4**|****|****|****|****|****|****|****|****|****|****
  71. |____|____|iiii|ii2*|****|****|****|****|****|****|****|****|****|****|****|****
  72. |iiii|iii1|****|****|****|****|****|****|****|****|****|****|****|****|****|****
  73. */
  74. #define PACK1LIM 0x80u
  75. #define PACK2LIM 0x4000u
  76. #define PACK3LIM 0x200000u
  77. #define PACK4LIM 0x10000000u
  78. #define PACK5LIM 0x800000000ull
  79. #define PACK6LIM 0x40000000000ull
  80. #define PACK7LIM 0x2000000000000ull
  81. #define PACK8LIM 0x100000000000000ull
  82. #define MY_14(x) ((ui16)(x) < PACK1LIM ? 1 : 2)
  83. #define MY_28(x) ((ui32)(x) < PACK2LIM ? MY_14(x) : ((ui32)(x) < PACK3LIM ? 3 : 4))
  84. #define MY_32(x) ((ui32)(x) < PACK4LIM ? MY_28(x) : 5)
  85. #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))))
  86. #if !defined(MACRO_BEGIN)
  87. #define MACRO_BEGIN do {
  88. #define MACRO_END \
  89. } \
  90. while (0)
  91. #endif
  92. #define PACK_14(x, buf, how, ret) \
  93. MACRO_BEGIN \
  94. if ((ui16)(x) < PACK1LIM) { \
  95. how::put_8((ui8)(x), (buf)); \
  96. (ret) = 1; \
  97. } else { \
  98. how::put_8((ui8)(0x80 | (x) >> 8), (buf)); \
  99. how::put_8((ui8)(x), (buf)); \
  100. (ret) = 2; \
  101. } \
  102. MACRO_END
  103. #define PACK_28(x, buf, how, ret) \
  104. MACRO_BEGIN \
  105. if ((ui32)(x) < PACK2LIM) { \
  106. PACK_14(x, buf, how, ret); \
  107. } else { \
  108. if ((ui32)(x) < PACK3LIM) { \
  109. how::put_8((ui8)(0xC0 | (x) >> 16), buf); \
  110. (ret) = 3; \
  111. } else { \
  112. how::put_8((ui8)(0xE0 | (x) >> 24), buf); \
  113. how::put_8((ui8)((x) >> 16), buf); \
  114. (ret) = 4; \
  115. } \
  116. how::put_16((ui16)(x), (buf)); \
  117. } \
  118. MACRO_END
  119. #define PACK_32(x, buf, how, ret) \
  120. MACRO_BEGIN \
  121. if ((ui32)(x) < PACK4LIM) { \
  122. PACK_28(x, buf, how, ret); \
  123. } else { \
  124. how::put_8((ui8)(0xF0), buf); \
  125. how::put_32((ui32)(x), buf); \
  126. (ret) = 5; \
  127. } \
  128. MACRO_END
  129. #define PACK_64(x, buf, how, ret) \
  130. MACRO_BEGIN \
  131. if ((ui64)(x) < PACK4LIM) { \
  132. PACK_28((ui32)(x), buf, how, ret); \
  133. } else { \
  134. if ((ui64)(x) < PACK6LIM) { \
  135. if ((ui64)(x) < PACK5LIM) { \
  136. how::put_8((ui8)(0xF0 | (x) >> 32), buf); \
  137. (ret) = 5; \
  138. } else { \
  139. how::put_8((ui8)(0xF8 | (x) >> 40), buf); \
  140. how::put_8((ui8)((x) >> 32), buf); \
  141. (ret) = 6; \
  142. } \
  143. } else { \
  144. if ((ui64)(x) < PACK7LIM) { \
  145. how::put_8((ui8)(0xFC | (x) >> 48), buf); \
  146. (ret) = 7; \
  147. } else { \
  148. if ((ui64)(x) < PACK8LIM) { \
  149. how::put_8((ui8)(0xFE | (x) >> 56), buf); \
  150. how::put_8((ui8)((x) >> 48), buf); \
  151. (ret) = 8; \
  152. } else { \
  153. how::put_8((ui8)(0xFF), buf); \
  154. how::put_16((ui16)((x) >> 48), buf); \
  155. (ret) = 9; \
  156. } \
  157. } \
  158. how::put_16((ui16)((x) >> 32), buf); \
  159. } \
  160. how::put_32((ui32)(x), buf); \
  161. } \
  162. MACRO_END
  163. #define DO_UNPACK_14(firstByte, x, buf, how, ret) \
  164. MACRO_BEGIN \
  165. if (firstByte < 0x80) { \
  166. (x) = (firstByte); \
  167. (ret) = 1; \
  168. } else { \
  169. (x) = (firstByte & 0x7F) << 8; \
  170. (x) |= how::get_8(buf); \
  171. (ret) = 2; \
  172. } \
  173. MACRO_END
  174. #define UNPACK_14(x, buf, how, ret) \
  175. MACRO_BEGIN \
  176. ui8 firstByte = how::get_8(buf); \
  177. DO_UNPACK_14(firstByte, x, buf, how, ret); \
  178. MACRO_END
  179. #define DO_UNPACK_28(firstByte, x, buf, how, ret) \
  180. MACRO_BEGIN \
  181. if (firstByte < 0xC0) { \
  182. DO_UNPACK_14(firstByte, x, buf, how, ret); \
  183. } else { \
  184. if (firstByte < 0xE0) { \
  185. (x) = (firstByte & 0x3F) << 16; \
  186. (ret) = 3; \
  187. } else { \
  188. (x) = (firstByte & 0x1F) << 24; \
  189. (x) |= how::get_8(buf) << 16; \
  190. (ret) = 4; \
  191. } \
  192. (x) |= how::get_16(buf); \
  193. } \
  194. MACRO_END
  195. #define UNPACK_28(x, buf, how, ret) \
  196. MACRO_BEGIN \
  197. ui8 firstByte = how::get_8(buf); \
  198. DO_UNPACK_28(firstByte, x, buf, how, ret); \
  199. MACRO_END
  200. #define DO_UNPACK_32(firstByte, x, buf, how, ret) \
  201. MACRO_BEGIN \
  202. if (firstByte < 0xF0) { \
  203. DO_UNPACK_28(firstByte, x, buf, how, ret); \
  204. } else { \
  205. (x) = how::get_32(buf); \
  206. (ret) = 5; \
  207. } \
  208. MACRO_END
  209. #define UNPACK_32(x, buf, how, ret) \
  210. MACRO_BEGIN \
  211. ui8 firstByte = how::get_8(buf); \
  212. DO_UNPACK_32(firstByte, x, buf, how, ret); \
  213. MACRO_END
  214. #define DO_UNPACK_64(firstByte, x, buf, how, ret) \
  215. MACRO_BEGIN \
  216. if (firstByte < 0xF0) { \
  217. DO_UNPACK_28(firstByte, x, buf, how, ret); \
  218. } else { \
  219. if (firstByte < 0xFC) { \
  220. if (firstByte < 0xF8) { \
  221. (x) = (ui64)(firstByte & 0x0F) << 32; \
  222. (ret) = 5; \
  223. } else { \
  224. (x) = (ui64)(firstByte & 0x07) << 40; \
  225. (x) |= (ui64)how::get_8(buf) << 32; \
  226. (ret) = 6; \
  227. } \
  228. } else { \
  229. if (firstByte < 0xFE) { \
  230. (x) = (ui64)(firstByte & 0x03) << 48; \
  231. (ret) = 7; \
  232. } else { \
  233. if (firstByte < 0xFF) { \
  234. (x) = (ui64)(firstByte & 0x01) << 56; \
  235. (x) |= (ui64)how::get_8(buf) << 48; \
  236. (ret) = 8; \
  237. } else { \
  238. (x) = (ui64)how::get_16(buf) << 48; \
  239. (ret) = 9; \
  240. } \
  241. } \
  242. (x) |= (ui64)how::get_16(buf) << 32; \
  243. } \
  244. (x) |= how::get_32(buf); \
  245. } \
  246. MACRO_END
  247. #define UNPACK_64(x, buf, how, ret) \
  248. MACRO_BEGIN \
  249. ui8 firstByte = how::get_8(buf); \
  250. DO_UNPACK_64(firstByte, x, buf, how, ret); \
  251. MACRO_END
  252. inline int in_long(i64& longVal, const char* ptrBuf) {
  253. int ret = 0;
  254. UNPACK_64(longVal, ptrBuf, mem_traits, ret);
  255. return ret;
  256. }
  257. inline int out_long(const i64& longVal, char* ptrBuf) {
  258. int ret = 0;
  259. PACK_64(longVal, ptrBuf, mem_traits, ret); /*7*/
  260. return ret;
  261. }
  262. inline int len_long(const i64& longVal) {
  263. return MY_64(longVal);
  264. }
  265. inline int in_long(i32& longVal, const char* ptrBuf) {
  266. int ret = 0;
  267. UNPACK_32(longVal, ptrBuf, mem_traits, ret);
  268. return ret;
  269. }
  270. inline int out_long(const i32& longVal, char* ptrBuf) {
  271. int ret = 0;
  272. PACK_32(longVal, ptrBuf, mem_traits, ret);
  273. return ret;
  274. }
  275. inline int len_long(const i32& longVal) {
  276. return MY_32(longVal);
  277. }
  278. template <typename T, typename C>
  279. inline const C* Unpack32(T& x, const C* src) {
  280. int pkLen = 0;
  281. const char* c = reinterpret_cast<const char*>(src);
  282. Y_UNUSED(pkLen);
  283. UNPACK_32(x, c, mem_traits, pkLen);
  284. Y_ASSERT(pkLen);
  285. return reinterpret_cast<const C*>(c);
  286. }
  287. template <typename T, typename C>
  288. inline const C* Unpack64(T& x, const C* src) {
  289. int pkLen = 0;
  290. const char* c = reinterpret_cast<const char*>(src);
  291. Y_UNUSED(pkLen);
  292. UNPACK_64(x, c, mem_traits, pkLen);
  293. Y_ASSERT(pkLen);
  294. return reinterpret_cast<const C*>(c);
  295. }
  296. template <typename T, typename C>
  297. inline C* Pack32(const T& x, C* dest) {
  298. int pkLen = 0;
  299. Y_UNUSED(pkLen);
  300. char* c = reinterpret_cast<char*>(dest);
  301. PACK_32(x, c, mem_traits, pkLen);
  302. Y_ASSERT(pkLen);
  303. return reinterpret_cast<C*>(c);
  304. }
  305. template <typename T, typename C>
  306. inline C* Pack64(const T& x, C* dest) {
  307. int pkLen = 0;
  308. Y_UNUSED(pkLen);
  309. char* c = reinterpret_cast<char*>(dest);
  310. PACK_64(x, c, mem_traits, pkLen);
  311. Y_ASSERT(pkLen);
  312. return reinterpret_cast<C*>(c);
  313. }