compress.c 21 KB

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