pack.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #include "pack.h"
  2. ////////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Pack
  5. //
  6. int Pack(ui8* buf, ui32 value) {
  7. ui8* p = buf;
  8. for (;;) {
  9. ui8 v = (ui8)value & 0x7f;
  10. value >>= 7;
  11. if (!value) {
  12. *p++ = v;
  13. break;
  14. }
  15. *p++ = (v | 0x80);
  16. }
  17. return (int)(p - buf);
  18. }
  19. ui32 Unpack(const ui8*& data) {
  20. ui32 value = 0;
  21. const ui8* p = data;
  22. for (int off = 0;; ++p, off += 7) {
  23. value |= (*p & 0x7f) << off;
  24. if ((*p & 0x80) == 0) {
  25. ++p;
  26. break;
  27. }
  28. }
  29. data = p;
  30. return value;
  31. }
  32. ////////////////////////////////////////////////////////////////////////////////
  33. //
  34. // PackU32
  35. //
  36. int PackU32(ui32 value, void* buf) {
  37. ui8* p = (ui8*)buf; // 654 3210 <-- bit of 'value' (7 bits total)
  38. if (value < (1u << 7)) { // [0--- ----]
  39. p[0] = (ui8)value; // ^ ^
  40. return 1; // MSB LSB
  41. }
  42. value -= (1u << 7); // DC BA98 7654 3210 <-- bit of 'value' (14 == 0xD bits total)
  43. if (value < (1u << 14)) { // [10-- ----] [---- ----]
  44. p[1] = (ui8)value; value >>= 8;
  45. p[0] = 0x80 | (ui8)value;
  46. return 2;
  47. }
  48. value -= (1u << 14); // And so on...
  49. if (value < (1u << 21)) { // [110- ----] [---- ----] [---- ----]
  50. p[2] = (ui8)value; value >>= 8;
  51. p[1] = (ui8)value; value >>= 8;
  52. p[0] = 0xc0 | (ui8)value;
  53. return 3;
  54. }
  55. value -= (1u << 21);
  56. if (value < (1u << 28)) { // [1110 ----] [---- ----] [---- ----] [---- ----]
  57. p[3] = (ui8)value; value >>= 8;
  58. p[2] = (ui8)value; value >>= 8;
  59. p[1] = (ui8)value; value >>= 8;
  60. p[0] = 0xe0 | (ui8)value;
  61. return 4;
  62. } // ...but for largest numbers, whole first byte is reserved.
  63. value -= (1u << 28); // [1111 0000] [---- ----] [---- ----] [---- ----] [---- ----]
  64. p[4] = (ui8)value; value >>= 8;
  65. p[3] = (ui8)value; value >>= 8;
  66. p[2] = (ui8)value; value >>= 8;
  67. p[1] = (ui8)value;
  68. p[0] = 0xf0;
  69. return 5;
  70. }
  71. int UnpackU32(ui32* value, const void* buf) {
  72. const ui8* p = (const ui8*)buf;
  73. ui8 b = p[0];
  74. if (!(b & 0x80)) {
  75. *value = b;
  76. return 1;
  77. }
  78. if (!(b & 0x40)) {
  79. *value = 0x80 + (((b & 0x3f) << 8) | p[1]);
  80. return 2;
  81. }
  82. if (!(b & 0x20)) {
  83. *value = 0x4080 + (((b & 0x1f) << 16) | (p[1] << 8) | p[2]);
  84. return 3;
  85. }
  86. if (!(b & 0x10)) {
  87. *value = 0x204080 + (((b & 0x0f) << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
  88. return 4;
  89. }
  90. *value = 0x10204080 + ((p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]);
  91. return 5;
  92. }
  93. int SkipU32(const void* buf) {
  94. static const i8 skip[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5 };
  95. int i = ((const ui8*)buf)[0] >> 4;
  96. return skip[i];
  97. }
  98. ////////////////////////////////////////////////////////////////////////////////
  99. //
  100. // PackU64
  101. //
  102. int PackU64(ui64 value, void* buf) { // Packing scheme is analogous to PackU32()
  103. ui8* p = (ui8*)buf;
  104. if (value < (1u << 7)) {
  105. p[0] = (ui8)value;
  106. return 1;
  107. }
  108. value -= (1u << 7);
  109. if (value < (1u << 14)) {
  110. p[1] = (ui8)value; value >>= 8;
  111. p[0] = 0x80 | (ui8)value;
  112. return 2;
  113. }
  114. value -= (1u << 14);
  115. if (value < (1u << 21)) {
  116. p[2] = (ui8)value; value >>= 8;
  117. p[1] = (ui8)value; value >>= 8;
  118. p[0] = 0xc0 | (ui8)value;
  119. return 3;
  120. }
  121. value -= (1u << 21);
  122. if (value < (1u << 28)) {
  123. p[3] = (ui8)value; value >>= 8;
  124. p[2] = (ui8)value; value >>= 8;
  125. p[1] = (ui8)value; value >>= 8;
  126. p[0] = 0xe0 | (ui8)value;
  127. return 4;
  128. }
  129. value -= (1u << 28);
  130. if (value < (ui64(1) << 35)) {
  131. p[4] = (ui8)value; value >>= 8;
  132. p[3] = (ui8)value; value >>= 8;
  133. p[2] = (ui8)value; value >>= 8;
  134. p[1] = (ui8)value; value >>= 8;
  135. p[0] = 0xf0 | (ui8)value;
  136. return 5;
  137. }
  138. value -= ui64(1) << 35;
  139. if (value < (ui64(1) << 42)) {
  140. p[5] = (ui8)value; value >>= 8;
  141. p[4] = (ui8)value; value >>= 8;
  142. p[3] = (ui8)value; value >>= 8;
  143. p[2] = (ui8)value; value >>= 8;
  144. p[1] = (ui8)value; value >>= 8;
  145. p[0] = 0xf8 | (ui8)value;
  146. return 6;
  147. }
  148. value -= ui64(1) << 42;
  149. if (value < (ui64(1) << 49)) { // [1111 110-] [---- ----] ... (+ 5 bytes)
  150. p[6] = (ui8)value; value >>= 8;
  151. p[5] = (ui8)value; value >>= 8;
  152. p[4] = (ui8)value; value >>= 8;
  153. p[3] = (ui8)value; value >>= 8;
  154. p[2] = (ui8)value; value >>= 8;
  155. p[1] = (ui8)value; value >>= 8;
  156. p[0] = 0xfc | (ui8)value;
  157. return 7;
  158. }
  159. value -= ui64(1) << 49;
  160. if (value < (ui64(1) << 56)) { // [1111 1110] [---- ----] ... (+ 6 bytes)
  161. p[7] = (ui8)value; value >>= 8;
  162. p[6] = (ui8)value; value >>= 8;
  163. p[5] = (ui8)value; value >>= 8;
  164. p[4] = (ui8)value; value >>= 8;
  165. p[3] = (ui8)value; value >>= 8;
  166. p[2] = (ui8)value; value >>= 8;
  167. p[1] = (ui8)value; value >>= 8;
  168. p[0] = 0xfe | (ui8)value;
  169. return 8;
  170. }
  171. value -= ui64(1) << 56; // [1111 1111] [---- ----] ... (+ 7 bytes)
  172. p[8] = (ui8)value; value >>= 8; // ^
  173. p[7] = (ui8)value; value >>= 8; // not a zero; contains actual bit
  174. p[6] = (ui8)value; value >>= 8;
  175. p[5] = (ui8)value; value >>= 8;
  176. p[4] = (ui8)value; value >>= 8;
  177. p[3] = (ui8)value; value >>= 8;
  178. p[2] = (ui8)value; value >>= 8;
  179. p[1] = (ui8)value; value >>= 8;
  180. p[0] = 0xff;
  181. return 9;
  182. }
  183. int UnpackU64(ui64* value, const void* buf) {
  184. const ui8* p = (const ui8*)buf;
  185. ui8 b = p[0];
  186. if (!(b & 0x80)) {
  187. *value = b;
  188. return 1;
  189. }
  190. if (!(b & 0x40)) {
  191. *value = 0x80 + (((b & 0x3f) << 8) | p[1]);
  192. return 2;
  193. }
  194. if (!(b & 0x20)) {
  195. *value = 0x4080 + (((b & 0x1f) << 16) | (p[1] << 8) | p[2]);
  196. return 3;
  197. }
  198. if (!(b & 0x10)) {
  199. *value = 0x204080 + (((b & 0x0f) << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
  200. return 4;
  201. }
  202. if (!(b & 0x08)) {
  203. *value = 0x10204080 + (
  204. (ui64(b & 0x07) << 32) |
  205. (ui32(p[1]) << 24) |
  206. ( p[2] << 16) |
  207. ( p[3] << 8) |
  208. p[4]
  209. );
  210. return 5;
  211. }
  212. if (!(b & 0x04)) {
  213. *value = 0x0810204080ull + (
  214. (ui64(b & 0x03) << 40) |
  215. (ui64(p[1]) << 32) |
  216. (ui32(p[2]) << 24) |
  217. ( p[3] << 16) |
  218. ( p[4] << 8) |
  219. p[5]
  220. );
  221. return 6;
  222. }
  223. if (!(b & 0x02)) {
  224. *value = 0x040810204080ull + (
  225. (ui64(b & 0x01) << 48) |
  226. (ui64(p[1]) << 40) |
  227. (ui64(p[2]) << 32) |
  228. (ui32(p[3]) << 24) |
  229. ( p[4] << 16) |
  230. ( p[5] << 8) |
  231. p[6]
  232. );
  233. return 7;
  234. }
  235. if (!(b & 0x01)) {
  236. *value = 0x02040810204080ull + (
  237. (ui64(p[1]) << 48) |
  238. (ui64(p[2]) << 40) |
  239. (ui64(p[3]) << 32) |
  240. (ui32(p[4]) << 24) |
  241. ( p[5] << 16) |
  242. ( p[6] << 8) |
  243. p[7]
  244. );
  245. return 8;
  246. }
  247. *value = 0x0102040810204080ull + (
  248. (ui64(p[1]) << 56) |
  249. (ui64(p[2]) << 48) |
  250. (ui64(p[3]) << 40) |
  251. (ui64(p[4]) << 32) |
  252. (ui32(p[5]) << 24) |
  253. ( p[6] << 16) |
  254. ( p[7] << 8) |
  255. p[8]
  256. );
  257. return 9;
  258. }
  259. #define REPEAT_16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
  260. #define REPEAT_32(x) REPEAT_16(x), REPEAT_16(x)
  261. #define REPEAT_64(x) REPEAT_32(x), REPEAT_32(x)
  262. #define REPEAT_128(x) REPEAT_64(x), REPEAT_64(x)
  263. int SkipU64(const void* buf) {
  264. static const i8 skip[256] = {
  265. REPEAT_128(1), REPEAT_64(2), REPEAT_32(3), REPEAT_16(4),
  266. 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 8, 9
  267. };
  268. return skip[*(const ui8*)buf];
  269. }
  270. #undef REPEAT_16
  271. #undef REPEAT_32
  272. #undef REPEAT_64
  273. #undef REPEAT_128