source: osgVisual/src/cluster/enet/compress.c @ 68

Last change on this file since 68 was 68, checked in by Torben Dannhauer, 14 years ago

1st compiling version with clusterENet.

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