renet 0.1.0

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