Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/enet/compress.c @ 8572

Last change on this file since 8572 was 7459, checked in by adrfried, 14 years ago

Merged ipv6 branch

Orxonox now includes a modified version of ENet 1.3.0

  • Property svn:eol-style set to native
File size: 20.8 KB
Line 
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
9typedef 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 */
25enum
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
42typedef 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
48void *
49enet_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
58void
59enet_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
90static enet_uint16
91enet_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
202static 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) \
235ENET_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
246size_t
247enet_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) \
416ENET_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) \
419ENET_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
441typedef 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
498size_t
499enet_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*/
637int
638enet_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     
Note: See TracBrowser for help on using the repository browser.