compress.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. /**
  2. @file compress.c
  3. @brief An adaptive order-2 PPM range coder
  4. */
  5. #define ENET_BUILDING_LIB 1
  6. #include <string.h>
  7. #include "enet/enet.h"
  8. typedef struct _ENetSymbol
  9. {
  10. /* binary indexed tree of symbols */
  11. enet_uint8 value;
  12. enet_uint8 count;
  13. enet_uint16 under;
  14. enet_uint16 left, right;
  15. /* context defined by this symbol */
  16. enet_uint16 symbols;
  17. enet_uint16 escapes;
  18. enet_uint16 total;
  19. enet_uint16 parent;
  20. } ENetSymbol;
  21. /* adaptation constants tuned aggressively for small packet sizes rather than large file compression */
  22. enum
  23. {
  24. ENET_RANGE_CODER_TOP = 1 << 24, ENET_RANGE_CODER_BOTTOM = 1 << 16,
  25. ENET_CONTEXT_SYMBOL_DELTA = 3, ENET_CONTEXT_SYMBOL_MINIMUM = 1, ENET_CONTEXT_ESCAPE_MINIMUM = 1,
  26. ENET_SUBCONTEXT_ORDER = 2, ENET_SUBCONTEXT_SYMBOL_DELTA = 2, ENET_SUBCONTEXT_ESCAPE_DELTA = 5
  27. };
  28. /* context exclusion roughly halves compression speed, so disable for now */
  29. #undef ENET_CONTEXT_EXCLUSION
  30. typedef struct _ENetRangeCoder
  31. {
  32. /* only allocate enough symbols for reasonable MTUs, would need to be larger for large file compression */
  33. ENetSymbol symbols[4096];
  34. } ENetRangeCoder;
  35. void *enet_range_coder_create(void)
  36. {
  37. ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc(sizeof(ENetRangeCoder));
  38. if (rangeCoder == NULL)
  39. return NULL;
  40. return rangeCoder;
  41. }
  42. void enet_range_coder_destroy(void * context)
  43. {
  44. ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
  45. if (rangeCoder == NULL)
  46. return;
  47. enet_free(rangeCoder);
  48. }
  49. #define ENET_SYMBOL_CREATE(symbol, value_, count_) \
  50. { \
  51. symbol = & rangeCoder -> symbols [nextSymbol ++]; \
  52. symbol -> value = value_; \
  53. symbol -> count = count_; \
  54. symbol -> under = count_; \
  55. symbol -> left = 0; \
  56. symbol -> right = 0; \
  57. symbol -> symbols = 0; \
  58. symbol -> escapes = 0; \
  59. symbol -> total = 0; \
  60. symbol -> parent = 0; \
  61. }
  62. #define ENET_CONTEXT_CREATE(context, escapes_, minimum) \
  63. { \
  64. ENET_SYMBOL_CREATE (context, 0, 0); \
  65. (context) -> escapes = escapes_; \
  66. (context) -> total = escapes_ + 256*minimum; \
  67. (context) -> symbols = 0; \
  68. }
  69. static enet_uint16 enet_symbol_rescale(ENetSymbol * symbol)
  70. {
  71. enet_uint16 total = 0;
  72. for (;;)
  73. {
  74. symbol->count -= symbol->count >> 1;
  75. symbol->under = symbol->count;
  76. if (symbol->left)
  77. symbol->under += enet_symbol_rescale(symbol + symbol->left);
  78. total += symbol->under;
  79. if (!symbol->right)
  80. break;
  81. symbol += symbol->right;
  82. }
  83. return total;
  84. }
  85. #define ENET_CONTEXT_RESCALE(context, minimum) \
  86. { \
  87. (context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \
  88. (context) -> escapes -= (context) -> escapes >> 1; \
  89. (context) -> total += (context) -> escapes + 256*minimum; \
  90. }
  91. #define ENET_RANGE_CODER_OUTPUT(value) \
  92. { \
  93. if (outData >= outEnd) \
  94. return 0; \
  95. * outData ++ = value; \
  96. }
  97. #define ENET_RANGE_CODER_ENCODE(under, count, total) \
  98. { \
  99. encodeRange /= (total); \
  100. encodeLow += (under) * encodeRange; \
  101. encodeRange *= (count); \
  102. for (;;) \
  103. { \
  104. if((encodeLow ^ (encodeLow + encodeRange)) >= ENET_RANGE_CODER_TOP) \
  105. { \
  106. if(encodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
  107. encodeRange = -encodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
  108. } \
  109. ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
  110. encodeRange <<= 8; \
  111. encodeLow <<= 8; \
  112. } \
  113. }
  114. #define ENET_RANGE_CODER_FLUSH \
  115. { \
  116. while (encodeLow) \
  117. { \
  118. ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
  119. encodeLow <<= 8; \
  120. } \
  121. }
  122. #define ENET_RANGE_CODER_FREE_SYMBOLS \
  123. { \
  124. if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER ) \
  125. { \
  126. nextSymbol = 0; \
  127. ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \
  128. predicted = 0; \
  129. order = 0; \
  130. } \
  131. }
  132. #define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update, minimum) \
  133. { \
  134. under_ = value*minimum; \
  135. count_ = minimum; \
  136. if (! (context) -> symbols) \
  137. { \
  138. ENET_SYMBOL_CREATE (symbol_, value_, update); \
  139. (context) -> symbols = symbol_ - (context); \
  140. } \
  141. else \
  142. { \
  143. ENetSymbol * node = (context) + (context) -> symbols; \
  144. for (;;) \
  145. { \
  146. if (value_ < node -> value) \
  147. { \
  148. node -> under += update; \
  149. if (node -> left) { node += node -> left; continue; } \
  150. ENET_SYMBOL_CREATE (symbol_, value_, update); \
  151. node -> left = symbol_ - node; \
  152. } \
  153. else \
  154. if (value_ > node -> value) \
  155. { \
  156. under_ += node -> under; \
  157. if (node -> right) { node += node -> right; continue; } \
  158. ENET_SYMBOL_CREATE (symbol_, value_, update); \
  159. node -> right = symbol_ - node; \
  160. } \
  161. else \
  162. { \
  163. count_ += node -> count; \
  164. under_ += node -> under - node -> count; \
  165. node -> under += update; \
  166. node -> count += update; \
  167. symbol_ = node; \
  168. } \
  169. break; \
  170. } \
  171. } \
  172. }
  173. #ifdef ENET_CONTEXT_EXCLUSION
  174. static const ENetSymbol emptyContext =
  175. { 0, 0, 0, 0, 0, 0, 0, 0, 0};
  176. #define ENET_CONTEXT_WALK(context, body) \
  177. { \
  178. const ENetSymbol * node = (context) + (context) -> symbols; \
  179. const ENetSymbol * stack [256]; \
  180. size_t stackSize = 0; \
  181. while (node -> left) \
  182. { \
  183. stack [stackSize ++] = node; \
  184. node += node -> left; \
  185. } \
  186. for (;;) \
  187. { \
  188. body; \
  189. if (node -> right) \
  190. { \
  191. node += node -> right; \
  192. while (node -> left) \
  193. { \
  194. stack [stackSize ++] = node; \
  195. node += node -> left; \
  196. } \
  197. } \
  198. else \
  199. if (stackSize <= 0) \
  200. break; \
  201. else \
  202. node = stack [-- stackSize]; \
  203. } \
  204. }
  205. #define ENET_CONTEXT_ENCODE_EXCLUDE(context, value_, under, total, minimum) \
  206. ENET_CONTEXT_WALK(context, { \
  207. if (node -> value != value_) \
  208. { \
  209. enet_uint16 parentCount = rangeCoder -> symbols [node -> parent].count + minimum; \
  210. if (node -> value < value_) \
  211. under -= parentCount; \
  212. total -= parentCount; \
  213. } \
  214. })
  215. #endif
  216. size_t enet_range_coder_compress(void * context, const ENetBuffer * inBuffers, size_t inBufferCount,
  217. size_t inLimit, enet_uint8 * outData, size_t outLimit)
  218. {
  219. ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
  220. enet_uint8 * outStart = outData, *outEnd = &outData[outLimit];
  221. const enet_uint8 * inData, *inEnd;
  222. enet_uint32 encodeLow = 0, encodeRange = ~0;
  223. ENetSymbol * root;
  224. enet_uint16 predicted = 0;
  225. size_t order = 0, nextSymbol = 0;
  226. if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0)
  227. return 0;
  228. inData = (const enet_uint8 *) inBuffers->data;
  229. inEnd = &inData[inBuffers->dataLength];
  230. inBuffers++;
  231. inBufferCount--;
  232. ENET_CONTEXT_CREATE(root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
  233. for (;;)
  234. {
  235. ENetSymbol * subcontext, *symbol;
  236. #ifdef ENET_CONTEXT_EXCLUSION
  237. const ENetSymbol * childContext = & emptyContext;
  238. #endif
  239. enet_uint8 value;
  240. enet_uint16 count, under, *parent = &predicted, total;
  241. if (inData >= inEnd)
  242. {
  243. if (inBufferCount <= 0)
  244. break;
  245. inData = (const enet_uint8 *) inBuffers->data;
  246. inEnd = &inData[inBuffers->dataLength];
  247. inBuffers++;
  248. inBufferCount--;
  249. }
  250. value = *inData++;
  251. for (subcontext = &rangeCoder->symbols[predicted]; subcontext != root;
  252. #ifdef ENET_CONTEXT_EXCLUSION
  253. childContext = subcontext,
  254. #endif
  255. subcontext = &rangeCoder->symbols[subcontext->parent])
  256. {
  257. ENET_CONTEXT_ENCODE(subcontext, symbol, value, under, count,
  258. ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
  259. *parent = symbol - rangeCoder->symbols;
  260. parent = &symbol->parent;
  261. total = subcontext->total;
  262. #ifdef ENET_CONTEXT_EXCLUSION
  263. if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
  264. ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, 0);
  265. #endif
  266. if (count > 0)
  267. {
  268. ENET_RANGE_CODER_ENCODE(subcontext -> escapes + under, count, total);
  269. }
  270. else
  271. {
  272. if (subcontext->escapes > 0 && subcontext->escapes < total)
  273. ENET_RANGE_CODER_ENCODE(0, subcontext -> escapes, total);
  274. subcontext->escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
  275. subcontext->total += ENET_SUBCONTEXT_ESCAPE_DELTA;
  276. }
  277. subcontext->total += ENET_SUBCONTEXT_SYMBOL_DELTA;
  278. if (count > 0xFF - 2 * ENET_SUBCONTEXT_SYMBOL_DELTA
  279. || subcontext->total > ENET_RANGE_CODER_BOTTOM - 0x100)
  280. ENET_CONTEXT_RESCALE(subcontext, 0);
  281. if (count > 0)
  282. goto nextInput;
  283. }
  284. ENET_CONTEXT_ENCODE(root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA,
  285. ENET_CONTEXT_SYMBOL_MINIMUM);
  286. *parent = symbol - rangeCoder->symbols;
  287. parent = &symbol->parent;
  288. total = root->total;
  289. #ifdef ENET_CONTEXT_EXCLUSION
  290. if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
  291. ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, ENET_CONTEXT_SYMBOL_MINIMUM);
  292. #endif
  293. ENET_RANGE_CODER_ENCODE(root -> escapes + under, count, total);
  294. root->total += ENET_CONTEXT_SYMBOL_DELTA;
  295. if (count > 0xFF - 2 * ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM
  296. || root->total > ENET_RANGE_CODER_BOTTOM - 0x100)
  297. ENET_CONTEXT_RESCALE(root, ENET_CONTEXT_SYMBOL_MINIMUM);
  298. nextInput: if (order >= ENET_SUBCONTEXT_ORDER)
  299. predicted = rangeCoder->symbols[predicted].parent;
  300. else
  301. order++;
  302. ENET_RANGE_CODER_FREE_SYMBOLS;
  303. }
  304. ENET_RANGE_CODER_FLUSH;
  305. return (size_t)(outData - outStart);
  306. }
  307. #define ENET_RANGE_CODER_SEED \
  308. { \
  309. if (inData < inEnd) decodeCode |= * inData ++ << 24; \
  310. if (inData < inEnd) decodeCode |= * inData ++ << 16; \
  311. if (inData < inEnd) decodeCode |= * inData ++ << 8; \
  312. if (inData < inEnd) decodeCode |= * inData ++; \
  313. }
  314. #define ENET_RANGE_CODER_READ(total) ((decodeCode - decodeLow) / (decodeRange /= (total)))
  315. #define ENET_RANGE_CODER_DECODE(under, count, total) \
  316. { \
  317. decodeLow += (under) * decodeRange; \
  318. decodeRange *= (count); \
  319. for (;;) \
  320. { \
  321. if((decodeLow ^ (decodeLow + decodeRange)) >= ENET_RANGE_CODER_TOP) \
  322. { \
  323. if(decodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
  324. decodeRange = -decodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
  325. } \
  326. decodeCode <<= 8; \
  327. if (inData < inEnd) \
  328. decodeCode |= * inData ++; \
  329. decodeRange <<= 8; \
  330. decodeLow <<= 8; \
  331. } \
  332. }
  333. #define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, createRoot, visitNode, createRight, createLeft) \
  334. { \
  335. under_ = 0; \
  336. count_ = minimum; \
  337. if (! (context) -> symbols) \
  338. { \
  339. createRoot; \
  340. } \
  341. else \
  342. { \
  343. ENetSymbol * node = (context) + (context) -> symbols; \
  344. for (;;) \
  345. { \
  346. enet_uint16 after = under_ + node -> under + (node -> value + 1)*minimum, before = node -> count + minimum; \
  347. visitNode; \
  348. if (code >= after) \
  349. { \
  350. under_ += node -> under; \
  351. if (node -> right) { node += node -> right; continue; } \
  352. createRight; \
  353. } \
  354. else \
  355. if (code < after - before) \
  356. { \
  357. node -> under += update; \
  358. if (node -> left) { node += node -> left; continue; } \
  359. createLeft; \
  360. } \
  361. else \
  362. { \
  363. value_ = node -> value; \
  364. count_ += node -> count; \
  365. under_ = after - before; \
  366. node -> under += update; \
  367. node -> count += update; \
  368. symbol_ = node; \
  369. } \
  370. break; \
  371. } \
  372. } \
  373. }
  374. #define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
  375. ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, return 0, exclude (node -> value, after, before), return 0, return 0)
  376. #define ENET_CONTEXT_ROOT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
  377. ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, \
  378. { \
  379. value_ = code / minimum; \
  380. under_ = code - code%minimum; \
  381. ENET_SYMBOL_CREATE (symbol_, value_, update); \
  382. (context) -> symbols = symbol_ - (context); \
  383. }, \
  384. exclude (node -> value, after, before), \
  385. { \
  386. value_ = node->value + 1 + (code - after)/minimum; \
  387. under_ = code - (code - after)%minimum; \
  388. ENET_SYMBOL_CREATE (symbol_, value_, update); \
  389. node -> right = symbol_ - node; \
  390. }, \
  391. { \
  392. value_ = node->value - 1 - (after - before - code - 1)/minimum; \
  393. under_ = code - (after - before - code - 1)%minimum; \
  394. ENET_SYMBOL_CREATE (symbol_, value_, update); \
  395. node -> left = symbol_ - node; \
  396. }) \
  397. #ifdef ENET_CONTEXT_EXCLUSION
  398. typedef struct _ENetExclude
  399. {
  400. enet_uint8 value;
  401. enet_uint16 under;
  402. }ENetExclude;
  403. #define ENET_CONTEXT_DECODE_EXCLUDE(context, total, minimum) \
  404. { \
  405. enet_uint16 under = 0; \
  406. nextExclude = excludes; \
  407. ENET_CONTEXT_WALK (context, { \
  408. under += rangeCoder -> symbols [node -> parent].count + minimum; \
  409. nextExclude -> value = node -> value; \
  410. nextExclude -> under = under; \
  411. nextExclude ++; \
  412. }); \
  413. total -= under; \
  414. }
  415. #define ENET_CONTEXT_EXCLUDED(value_, after, before) \
  416. { \
  417. size_t low = 0, high = nextExclude - excludes; \
  418. for(;;) \
  419. { \
  420. size_t mid = (low + high) >> 1; \
  421. const ENetExclude * exclude = & excludes [mid]; \
  422. if (value_ < exclude -> value) \
  423. { \
  424. if (low + 1 < high) \
  425. { \
  426. high = mid; \
  427. continue; \
  428. } \
  429. if (exclude > excludes) \
  430. after -= exclude [-1].under; \
  431. } \
  432. else \
  433. { \
  434. if (value_ > exclude -> value) \
  435. { \
  436. if (low + 1 < high) \
  437. { \
  438. low = mid; \
  439. continue; \
  440. } \
  441. } \
  442. else \
  443. before = 0; \
  444. after -= exclude -> under; \
  445. } \
  446. break; \
  447. } \
  448. }
  449. #endif
  450. #define ENET_CONTEXT_NOT_EXCLUDED(value_, after, before)
  451. size_t enet_range_coder_decompress(void * context, const enet_uint8 * inData, size_t inLimit,
  452. enet_uint8 * outData, size_t outLimit)
  453. {
  454. ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
  455. enet_uint8 * outStart = outData, *outEnd = &outData[outLimit];
  456. const enet_uint8 * inEnd = &inData[inLimit];
  457. enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0;
  458. ENetSymbol * root;
  459. enet_uint16 predicted = 0;
  460. size_t order = 0, nextSymbol = 0;
  461. #ifdef ENET_CONTEXT_EXCLUSION
  462. ENetExclude excludes [256];
  463. ENetExclude * nextExclude = excludes;
  464. #endif
  465. if (rangeCoder == NULL || inLimit <= 0)
  466. return 0;
  467. ENET_CONTEXT_CREATE(root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
  468. ENET_RANGE_CODER_SEED;
  469. for (;;)
  470. {
  471. ENetSymbol * subcontext, *symbol, *patch;
  472. #ifdef ENET_CONTEXT_EXCLUSION
  473. const ENetSymbol * childContext = & emptyContext;
  474. #endif
  475. enet_uint8 value = 0;
  476. enet_uint16 code, under, count, bottom, *parent = &predicted, total;
  477. for (subcontext = &rangeCoder->symbols[predicted]; subcontext != root;
  478. #ifdef ENET_CONTEXT_EXCLUSION
  479. childContext = subcontext,
  480. #endif
  481. subcontext = &rangeCoder->symbols[subcontext->parent])
  482. {
  483. if (subcontext->escapes <= 0)
  484. continue;
  485. total = subcontext->total;
  486. #ifdef ENET_CONTEXT_EXCLUSION
  487. if (childContext -> total > 0)
  488. ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, 0);
  489. #endif
  490. if (subcontext->escapes >= total)
  491. continue;
  492. code = ENET_RANGE_CODER_READ (total);
  493. if (code < subcontext->escapes)
  494. {
  495. ENET_RANGE_CODER_DECODE(0, subcontext -> escapes, total);
  496. continue;
  497. }
  498. code -= subcontext->escapes;
  499. #ifdef ENET_CONTEXT_EXCLUSION
  500. if (childContext -> total > 0)
  501. {
  502. ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_EXCLUDED);
  503. }
  504. else
  505. #endif
  506. {
  507. ENET_CONTEXT_TRY_DECODE(subcontext, symbol, code, value, under, count,
  508. ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_NOT_EXCLUDED);
  509. }
  510. bottom = symbol - rangeCoder->symbols;
  511. ENET_RANGE_CODER_DECODE(subcontext -> escapes + under, count, total);
  512. subcontext->total += ENET_SUBCONTEXT_SYMBOL_DELTA;
  513. if (count > 0xFF - 2 * ENET_SUBCONTEXT_SYMBOL_DELTA
  514. || subcontext->total > ENET_RANGE_CODER_BOTTOM - 0x100)
  515. ENET_CONTEXT_RESCALE(subcontext, 0);
  516. goto patchContexts;
  517. }
  518. total = root->total;
  519. #ifdef ENET_CONTEXT_EXCLUSION
  520. if (childContext -> total > 0)
  521. ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, ENET_CONTEXT_SYMBOL_MINIMUM);
  522. #endif
  523. code = ENET_RANGE_CODER_READ (total);
  524. if (code < root->escapes)
  525. {
  526. ENET_RANGE_CODER_DECODE(0, root -> escapes, total);
  527. break;
  528. }
  529. code -= root->escapes;
  530. #ifdef ENET_CONTEXT_EXCLUSION
  531. if (childContext -> total > 0)
  532. {
  533. ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_EXCLUDED);
  534. }
  535. else
  536. #endif
  537. {
  538. ENET_CONTEXT_ROOT_DECODE(root, symbol, code, value, under, count,
  539. ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM,
  540. ENET_CONTEXT_NOT_EXCLUDED);
  541. }
  542. bottom = symbol - rangeCoder->symbols;
  543. ENET_RANGE_CODER_DECODE(root -> escapes + under, count, total);
  544. root->total += ENET_CONTEXT_SYMBOL_DELTA;
  545. if (count > 0xFF - 2 * ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM
  546. || root->total > ENET_RANGE_CODER_BOTTOM - 0x100)
  547. ENET_CONTEXT_RESCALE(root, ENET_CONTEXT_SYMBOL_MINIMUM);
  548. patchContexts: for (patch = &rangeCoder->symbols[predicted]; patch != subcontext; patch =
  549. &rangeCoder->symbols[patch->parent])
  550. {
  551. ENET_CONTEXT_ENCODE(patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA,
  552. 0);
  553. *parent = symbol - rangeCoder->symbols;
  554. parent = &symbol->parent;
  555. if (count <= 0)
  556. {
  557. patch->escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
  558. patch->total += ENET_SUBCONTEXT_ESCAPE_DELTA;
  559. }
  560. patch->total += ENET_SUBCONTEXT_SYMBOL_DELTA;
  561. if (count > 0xFF - 2 * ENET_SUBCONTEXT_SYMBOL_DELTA
  562. || patch->total > ENET_RANGE_CODER_BOTTOM - 0x100)
  563. ENET_CONTEXT_RESCALE(patch, 0);
  564. }
  565. *parent = bottom;
  566. ENET_RANGE_CODER_OUTPUT(value);
  567. if (order >= ENET_SUBCONTEXT_ORDER)
  568. predicted = rangeCoder->symbols[predicted].parent;
  569. else
  570. order++;
  571. ENET_RANGE_CODER_FREE_SYMBOLS;
  572. }
  573. return (size_t)(outData - outStart);
  574. }
  575. /** @defgroup host ENet host functions
  576. @{
  577. */
  578. /** Sets the packet compressor the host should use to the default range coder.
  579. @param host host to enable the range coder for
  580. @returns 0 on success, < 0 on failure
  581. */
  582. int enet_host_compress_with_range_coder(ENetHost * host)
  583. {
  584. ENetCompressor compressor;
  585. memset(&compressor, 0, sizeof(compressor));
  586. compressor.context = enet_range_coder_create();
  587. if (compressor.context == NULL)
  588. return -1;
  589. compressor.compress = enet_range_coder_compress;
  590. compressor.decompress = enet_range_coder_decompress;
  591. compressor.destroy = enet_range_coder_destroy;
  592. enet_host_compress(host, &compressor);
  593. return 0;
  594. }
  595. /** @} */