source: branches/profile/ARBDB/adcompr.cxx

Last change on this file was 11825, checked in by westram, 10 years ago
  • fix some format strings (detected by 32bit compile)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.4 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : adcompr.cxx                                       //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include <climits>
12
13#include <arbdbt.h>
14
15#include "gb_key.h"
16#include "gb_t_prot.h"
17#include "gb_compress.h"
18#include "gb_localdata.h"
19
20#if defined(DEBUG)
21// #define TEST_HUFFMAN_CODE
22#endif // DEBUG
23
24#define GBTUM_COMPRESS_TREE_SIZE 32
25
26
27#define GB_READ_BIT(p, c, bp, result)    if (!bp) { c = *(p++); bp = 8; }; result = (c>>7); result &= 1; c <<= 1; bp--
28
29#define GB_INIT_WRITE_BITS(p, bp) *p = 0; bp = 8
30
31#define GB_WRITE_BITS(p, bp, bitc, bits, i)     \
32    if (bp<=0) { bp += 8; p++;  *p = 0; }       \
33    if ((i=bp-bitc)<0) {                        \
34        *p |=  bits>>(-i);                      \
35        i += 8;                                 \
36        bp += 8; p++; *p = 0;                   \
37    }                                           \
38    *p |=  bits<<i;                             \
39    bp-=bitc;
40
41#define GB_READ_BITS(p, c, bp, bitc, bits) {    \
42        long _i;                                \
43        int _r;                                 \
44        bits = 0;                               \
45        for (_i=bitc-1; _i>=0; _i--) {          \
46            GB_READ_BIT(p, c, bp, _r);          \
47            bits = (bits<<1) + _r;              \
48        } }
49
50
51__ATTR__USERESULT static GB_ERROR gb_check_huffmann_tree(gb_compress_tree *t) {
52    if (t->leaf)
53        return 0;
54    if (!t->son[0])
55        return GB_export_error("Database entry corrupt (zero left son)");
56    if (!t->son[1])
57        return GB_export_error("Database entry corrupt (zero right son)");
58
59    {
60        GB_ERROR err = gb_check_huffmann_tree(t->son[0]);
61        if (err) return err;
62    }
63    return gb_check_huffmann_tree(t->son[1]);
64}
65
66#if defined(TEST_HUFFMAN_CODE)
67static void gb_dump_huffmann_tree(gb_compress_tree *t, const char *prefix) {
68    if (t->leaf) {
69        long command = (long)t->son[1];
70        printf("%s", prefix);
71
72        switch (command) {
73            case GB_CS_END: printf(" [GB_CS_END]\n"); break;
74            case GB_CS_ID: printf(" [GB_CS_ID]\n"); break;
75            case GB_CS_OK: {
76                long val = (long)t->son[0];
77                printf(": value=%li (='%c')\n", val, (char)val);
78                break;
79            }
80            default: {
81                long val = (long)t->son[0];
82                printf(" other command (%li) value=%li (='%c')\n", command, val, (char)val);
83                break;
84            }
85        }
86    }
87    else {
88        int   len        = strlen(prefix);
89        char *my_prefix  = malloc(len+2);
90        strcpy(my_prefix, prefix);
91        my_prefix[len+1] = 0;
92        my_prefix[len]   = '0';
93        gb_dump_huffmann_tree(t->son[0], my_prefix);
94        my_prefix[len]   = '1';
95        gb_dump_huffmann_tree(t->son[1], my_prefix);
96        free(my_prefix);
97    }
98}
99static void gb_dump_huffmann_list(gb_compress_list *bc, const char *prefix) {
100    if (bc->command == GB_CD_NODE) {
101        int   len        = strlen(prefix);
102        char *my_prefix  = malloc(len+2);
103        strcpy(my_prefix, prefix);
104        my_prefix[len+1] = 0;
105        my_prefix[len]   = '0';
106        gb_dump_huffmann_list(bc->son[0], my_prefix);
107        my_prefix[len]   = '1';
108        gb_dump_huffmann_list(bc->son[1], my_prefix);
109        free(my_prefix);
110    }
111    else {
112        printf("%s  value=%i (='%c') count=%li\n", prefix, bc->value, (char)bc->value, bc->count);
113    }
114}
115
116#endif // TEST_HUFFMAN_CODE
117
118gb_compress_tree *gb_build_uncompress_tree(const unsigned char *data, long short_flag, char **end) {
119    gb_compress_tree    *Main, *t;
120    long                 bits, mask, i;
121    const unsigned char *p;
122    GB_ERROR             error;
123
124    Main = (gb_compress_tree *)gbm_get_mem(sizeof(gb_compress_tree), GBM_CB_INDEX);
125    for (p=data; *p; p+=3+short_flag) {
126        bits = p[0];
127        mask = 0x80;
128        for (i=7; i; i--, mask=mask>>1) if (mask & bits) break; // find first bit
129        if (!i) {
130            GB_internal_error("Data corrupt");
131            return 0;
132        }
133        t = Main;
134        for (; i; i--) {
135            if (t->leaf) {
136                GB_export_error("Corrupt data !!!");
137                return 0;
138            }
139            mask = mask>>1;
140            if (mask & bits) {
141                if (!t->son[1]) {
142                    t->son[1] = (gb_compress_tree *)gbm_get_mem(sizeof(gb_compress_tree), GBM_CB_INDEX);
143                }
144                t=t->son[1];
145            }
146            else {
147                if (!t->son[0]) {
148                    t->son[0] = (gb_compress_tree *)gbm_get_mem(sizeof(gb_compress_tree), GBM_CB_INDEX);
149                }
150                t=t->son[0];
151            }
152        }
153        if (t->leaf) {
154            GB_export_error("Corrupt data !!!");
155            return 0;
156        }
157        t->leaf = 1;
158        if (short_flag) {
159            t->son[0] = (gb_compress_tree *)(long)((p[2]<<8)+p[3]);
160        }
161        else {
162            t->son[0] = (gb_compress_tree *)(long)(p[2]);
163        }
164        t->son[1] = (gb_compress_tree *)(long)p[1]; // command
165    }
166    if (end) *end = ((char *)p)+1;
167    if ((error = gb_check_huffmann_tree(Main))) {
168        GB_internal_errorf("%s", error);
169        gb_free_compress_tree(Main);
170        return 0;
171    }
172
173#if defined(TEST_HUFFMAN_CODE)
174    printf("Huffman tree:\n");
175    gb_dump_huffmann_tree(Main, "");
176#endif // TEST_HUFFMAN_CODE
177
178    return Main;
179}
180
181void gb_free_compress_tree(gb_compress_tree *tree) {
182    if (tree) {
183        if (!tree->leaf) {
184            if (tree->son[0]) gb_free_compress_tree(tree->son[0]);
185            if (tree->son[1])gb_free_compress_tree(tree->son[1]);
186        }
187    }
188    gbm_free_mem(tree, sizeof(gb_compress_tree), GBM_CB_INDEX);
189}
190
191gb_compress_list *gb_build_compress_list(const unsigned char *data, long short_flag, long *size) {
192    int                  i, maxi, bitc;
193    int                  val, bits, mask, value;
194    const unsigned char *p;
195
196    enum gb_compress_list_commands command = (enum gb_compress_list_commands)0;
197
198    maxi = 0;
199    val  = bits = mask = value = bitc = 0;
200    for (p=data; *p; p+=3+short_flag) {
201        i = (p[2]);
202        if (short_flag) {
203            i = (i<<8)+p[3];
204        }
205        if (i>maxi) maxi = i;
206    }
207    *size = maxi;
208
209    gb_compress_list *list = (gb_compress_list *)GB_calloc(sizeof(gb_compress_list), (size_t)maxi+1);
210
211    maxi = 0;
212    val = -1;
213
214    for (p=data; *p; p+=3+short_flag) {
215        val = (p[2]);
216        if (short_flag) val = (val<<8)+p[3];
217
218        for (i=maxi; i<val; i++) {
219            list[i].command = command;
220            list[i].mask    = mask;
221            list[i].bitcnt  = bitc;
222            list[i].bits    = bits;
223            list[i].value   = value;
224        }
225        maxi = val;
226
227        command = (enum gb_compress_list_commands)(p[1]);
228        bits = p[0];
229        mask = 0x80;
230        for (bitc=7; bitc; bitc--, mask=mask>>1) if (mask & bits) break; // find first bit
231        mask = 0xff>>(8-bitc);
232        bits = bits & mask;
233        value = val;
234    }
235    i = val;
236    list[i].command = command;
237    list[i].mask    = mask;
238    list[i].bitcnt  = bitc;
239    list[i].bits    = bits;
240    list[i].value   = value;
241    return list;
242}
243
244// ------------------------
245//      bit compression
246
247
248char *gb_compress_bits(const char *source, long size, const unsigned char *c_0, long *msize)
249{
250    const unsigned char *s      = (const unsigned char *)source;
251    char                *buffer = GB_give_other_buffer(source, size);
252    char                *dest   = buffer;
253
254    long  i, j;
255    int   bitptr, bits, bitc;
256    int   zo_flag = 0;
257    long  len;
258    int   h_i, command;
259    int   isNull[256];
260
261    for (i = 0; i<256; ++i) isNull[i] = 0;
262    for (i = 0; c_0[i]; ++i) isNull[c_0[i]] = 1;
263
264    GB_INIT_WRITE_BITS(dest, bitptr);
265    for (len = size, i = 0; len; len--) {
266        if (zo_flag == isNull[*(s++)]) {
267            zo_flag = 1 - zo_flag;
268            for (command = GB_CS_SUB; command != GB_CS_OK;) {
269                if (i>gb_local->bc_size) j = gb_local->bc_size; else j = i;
270                bits = gb_local->bitcompress[j].bits;
271                bitc = gb_local->bitcompress[j].bitcnt;
272                command = gb_local->bitcompress[j].command;
273                i -= gb_local->bitcompress[j].value;
274                GB_WRITE_BITS(dest, bitptr, bitc, bits, h_i);
275            }
276            i = 0;
277        }
278        i++;
279    }
280    for (command = GB_CS_SUB; command != GB_CS_OK;) {
281        if (i>gb_local->bc_size) j = gb_local->bc_size; else j = i;
282        bits = gb_local->bitcompress[j].bits;
283        bitc = gb_local->bitcompress[j].bitcnt;
284        command = gb_local->bitcompress[j].command;
285        i -= gb_local->bitcompress[j].value;
286        GB_WRITE_BITS(dest, bitptr, bitc, bits, h_i);
287    }
288    *msize = dest - buffer + 1;
289    return buffer;
290}
291
292
293GB_BUFFER gb_uncompress_bits(const char *source, long size, char c_0, char c_1) {
294    gb_compress_tree *Main = gb_local->bituncompress;
295
296    char ch   = 0;
297    long bitp = 0;
298    char outc = c_0;
299
300    const char *s      = source;
301    char       *p      = GB_give_other_buffer(source, size+1);
302    char       *buffer = p;
303
304    for (long pos = 0; pos<size;) {
305        long lastpos = pos;
306        for (long command = GB_CS_SUB; command != GB_CS_OK;) {
307            gb_compress_tree *t;
308            for (t = Main; !t->leaf;) {
309                int bit;
310                GB_READ_BIT(s, ch, bitp, bit);
311                t = t->son[bit];
312            }
313            command = (long) t->son[1];
314            pos += (long)t->son[0];
315        }
316        for (; lastpos<pos; lastpos++) *(p++) = outc;
317        if (outc==c_0) outc=c_1; else outc=c_0;
318    }
319    *p = 0;
320    return buffer;
321}
322
323
324
325/* Runlength encoding produces..
326 *
327 * from source: string
328 * dest:   [command]+
329 *
330 * command     data                     meaning
331 *
332 * -122        low high byte            'byte' was repeated 'low'+256*'high' times
333 * -119..-1    byte                     'byte' was repeated -'command' times
334 * 0           ---                      end
335 * 1..119      [byte]+                 'command' data bytes follow
336 */
337
338static char *g_b_write_run(char *dest, int scount, int lastbyte) {
339    while (scount> 0xffff) {
340        *(dest++) = 0x100-122;
341        *(dest++) = 0xff;
342        *(dest++) = 0xff;
343        *(dest++) = lastbyte;
344        scount -= 0xffff;
345    }
346    if (scount >250) {
347        *(dest++) = 0x100-122;
348        *(dest++) = scount & 0xff;
349        *(dest++) = (scount >> 8) & 0xff;
350        *(dest++) = lastbyte;
351        return dest;
352    }
353
354    while (scount>120) {                            // 120 blocks
355        *(dest++) = 0x100 - 120;
356        *(dest++) = lastbyte;
357        scount -= 120;
358    }
359
360    if (scount) {                       // and rest
361        *(dest++) = -scount;
362        *(dest++) = lastbyte;
363    }
364    return dest;
365}
366
367#define GB_COPY_NONRUN(dest, source, len)       \
368    while (len > 120) {                         \
369        int _i = 120;                           \
370        char *_p;                               \
371        len -= _i;                              \
372        *(dest++) = _i;                         \
373        _p = dest; dest+=_i;                    \
374        while (_i--) {                          \
375            *(_p++) = *(source++);              \
376        }                                       \
377    }                                           \
378    if  (len >0) {                              \
379        int _i = len;                           \
380        char *_p;                               \
381        len = 0;                                \
382        *(dest++) = _i;                         \
383        _p = dest; dest+=_i;                    \
384        while (_i--) {                          \
385            *(_p++) = *(source++);              \
386        }                                       \
387    }
388
389void gb_compress_equal_bytes_2(const char *source, size_t size, size_t *msize, char *dest) {
390    long        i;                                  // length counter
391    int         last, rbyte;                        // next and akt value
392    long        scount;                             // same count; count equal bytes
393    char       *buffer = dest;
394    const char *sourcenequal;                       // begin of non equal section
395    long        hi;                                 // to temporary store i
396    int         hsize;
397
398    sourcenequal = source;
399    rbyte = *(source ++);
400    last = -1;
401    for (i=size-1; i;) {
402        if (rbyte!=last) {                          // Search an equal pair
403            last = rbyte;
404            rbyte = *(source ++); i--;
405            continue;
406        }                                           // last rbyte *(source)
407        hi = i+1;
408        while (i) {                                 // get equal bytes
409            rbyte = *(source ++); i--;
410            if (rbyte!=last) break;
411        }
412        scount = hi-i;                              // number of equal bytes ; at end e.b.-1
413        if (scount <= GB_RUNLENGTH_SIZE) continue;  // less than 4-> no runlength compression
414
415        /* compression !!!
416         * 1. copy unequal bytes
417         * 2. fill rest
418         */
419
420        hsize   = source - sourcenequal - scount -1; // hsize of non equal bytes
421        source  = sourcenequal;
422        hi      = i;                                // i=unequal length
423        GB_COPY_NONRUN(dest, source, hsize);
424        dest    = g_b_write_run(dest, scount, last);
425        source += scount;                           // now equal bytes
426
427        sourcenequal = source++;                    // no rbyte written yet
428        last         = rbyte;
429        i            = hi;
430        if (i) {
431            rbyte = *(source++); i--;
432        }
433    }
434    // and now rest which is not compressed
435    hsize = source - sourcenequal;
436    source = sourcenequal;
437    GB_COPY_NONRUN(dest, source, hsize);
438
439    *(dest++) = 0;                  // end of data
440    *msize = dest-buffer;
441    if (*msize >size*9/8) printf("ssize %d, dsize %d\n", (int)size, (int)*msize);
442}
443
444static GB_BUFFER gb_compress_equal_bytes(const char *source, size_t size, size_t *msize, int last_flag) {
445    char *dest;
446    char *buffer;
447
448    dest  = buffer = GB_give_other_buffer(source, size*9/8);
449    *(dest++) = GB_COMPRESSION_RUNLENGTH | last_flag;
450    gb_compress_equal_bytes_2(source, size, msize, dest);
451    (*msize) ++;            // Tag byte
452    return buffer;
453}
454
455struct huffmann_list {
456    huffmann_list    *next;
457    long              val;
458    gb_compress_list *element;
459};
460
461static huffmann_list *huffmann_listhead = NULL;
462
463static void gb_compress_huffmann_add_to_list(long val, gb_compress_list *element) {
464    huffmann_list *dat, *search, *searchlast;
465
466    dat          = (huffmann_list *)gbm_get_mem(sizeof(huffmann_list), GBM_CB_INDEX);
467    dat->val     = val;
468    dat->element = element;
469
470    searchlast = 0;
471    for (search = huffmann_listhead; search; search = search->next) {
472        if (val<search->val) break;
473        searchlast = search;
474    }
475    if (huffmann_listhead) {
476        if (searchlast) {
477            dat->next = searchlast->next;
478            searchlast->next = dat;
479        }
480        else {
481            dat->next = huffmann_listhead;
482            huffmann_listhead = dat;
483        }
484    }
485    else {
486        huffmann_listhead = dat;
487    }
488}
489
490static long gb_compress_huffmann_pop(long *val, gb_compress_list **element) {
491    huffmann_list *dat;
492    if ((dat = huffmann_listhead)) {
493        huffmann_listhead = dat->next;
494        *val = dat->val;
495        *element = dat->element;
496        gbm_free_mem(dat, sizeof(huffmann_list), GBM_CB_INDEX);
497        return 1;
498    }
499    else {
500        GB_internal_error("huffman compression failed");
501        return 0;
502    }
503}
504
505static char *gb_compress_huffmann_rek(gb_compress_list *bc, int bits, int bitcnt, char *dest) {
506    if (bc->command == GB_CD_NODE) {
507        dest = gb_compress_huffmann_rek(bc->son[0], (bits<<1), bitcnt+1, dest);
508        dest = gb_compress_huffmann_rek(bc->son[1], (bits<<1)+1, bitcnt+1, dest);
509        gbm_free_mem(bc, sizeof(gb_compress_list), GBM_CB_INDEX);
510        return dest;
511    }
512    else {
513        *(dest++) = bits;
514        *(dest++) = bc->command;
515        *(dest++) = bc->value;
516        bc->bitcnt = bitcnt;
517        bc->mask = 0xff>>(8-bitcnt);
518        bc->bits = bits&bc->mask;
519        return dest;
520    }
521}
522
523static GB_BUFFER gb_compress_huffmann(GB_CBUFFER source, size_t size, size_t *msize, int last_flag) {
524    const int        COMPRESS_LIST_SIZE = 257;
525    gb_compress_list bitcompress[COMPRESS_LIST_SIZE];
526
527    memset((char *)(&bitcompress[0]), 0, sizeof(gb_compress_list)*COMPRESS_LIST_SIZE);
528
529    char *buffer = GB_give_other_buffer(source, size*2+3*GBTUM_COMPRESS_TREE_SIZE+1);
530    char *dest   = buffer;
531    *(dest++)    = GB_COMPRESSION_HUFFMANN | last_flag;
532
533    long id = 0;
534
535    {
536        long level;
537        long i;
538        long restcount;
539
540        long vali[2] = { 0, 0 };
541
542        gb_compress_list *element1 = 0;
543        gb_compress_list *element2 = 0;
544        gb_compress_list *bc       = 0;
545
546        unsigned char *s = (unsigned char *)source;
547        for (long len = size; len; len--) {
548            bitcompress[*(s++)].count++;
549        }
550        level = size/GBTUM_COMPRESS_TREE_SIZE;
551        restcount = 0;
552        for (i=0; i<256; i++) {
553            bitcompress[i].value = (int)i;
554            if (bitcompress[i].count>level) {
555                gb_compress_huffmann_add_to_list(bitcompress[i].count, &bitcompress[i]);
556                bitcompress[i].command = GB_CS_OK;
557            }
558            else {
559                restcount += bitcompress[i].count;
560                bitcompress[i].count = 0;
561                id = i;
562                bitcompress[i].command = GB_CS_ID;
563            }
564        }
565        bitcompress[COMPRESS_LIST_SIZE-1].command = GB_CS_END;
566
567        gb_compress_huffmann_add_to_list(restcount, &bitcompress[id]);
568        gb_compress_huffmann_add_to_list(1, &bitcompress[COMPRESS_LIST_SIZE-1]);
569        while (huffmann_listhead->next) {
570            gb_compress_huffmann_pop(&(vali[0]), &element1);
571            gb_compress_huffmann_pop(&(vali[1]), &element2);
572
573            bc          = (gb_compress_list *)gbm_get_mem(sizeof(gb_compress_list), GBM_CB_INDEX);
574            bc->command = GB_CD_NODE;
575            bc->son[0]  = element1;
576            bc->son[1]  = element2;
577
578            if (element1->command == GB_CD_NODE) {
579                bc->bits = element1->bits+1;
580                if (element2->command == GB_CD_NODE && element2->bits >= bc->bits) bc->bits = element2->bits+1;
581            }
582            else {
583                if (element2->command == GB_CD_NODE) {
584                    bc->bits = element2->bits+1;
585                }
586                else {
587                    bc->bits = 1;
588                }
589            }
590
591            gb_assert(bc->bits <= 7); // max. 7 bits allowed
592
593            // if already 6 bits used -> put to end of list; otherwise sort in
594            gb_compress_huffmann_add_to_list(bc->bits >= 6 ? LONG_MAX : vali[0]+vali[1], bc);
595        }
596        gb_compress_huffmann_pop(&(vali[0]), &element1);
597#if defined(TEST_HUFFMAN_CODE)
598        printf("huffman list:\n");
599        gb_dump_huffmann_list(bc, "");
600#endif // TEST_HUFFMAN_CODE
601        dest      = gb_compress_huffmann_rek(bc, 1, 0, dest);
602        *(dest++) = 0;
603    }
604
605    gb_compress_list *pbid = &bitcompress[id];
606    unsigned char    *s    = (unsigned char *)source;
607    {
608        int bitptr, bits, bitc;
609
610        GB_INIT_WRITE_BITS(dest, bitptr);
611        int h_i;
612        for (long len = size; len; len--) {
613            int val     = *(s++);
614            int command = bitcompress[val].command;
615            if (command == GB_CS_OK) {
616                gb_compress_list *pbc = &bitcompress[val];
617                bits = pbc->bits;
618                bitc = pbc->bitcnt;
619                GB_WRITE_BITS(dest, bitptr, bitc, bits, h_i);
620            }
621            else {
622                bits = pbid->bits;
623                bitc = pbid->bitcnt;
624                GB_WRITE_BITS(dest, bitptr, bitc, bits, h_i);
625
626                bits = val;
627                bitc = 8;
628                GB_WRITE_BITS(dest, bitptr, bitc, bits, h_i);
629            }
630        }
631        bits = bitcompress[COMPRESS_LIST_SIZE-1].bits;
632        bitc = bitcompress[COMPRESS_LIST_SIZE-1].bitcnt;
633        // cppcheck-suppress unreadVariable (bitptr is assigned but never used)
634        GB_WRITE_BITS(dest, bitptr, bitc, bits, h_i);
635    }
636    *msize = dest - buffer + 1;
637#if defined(TEST_HUFFMAN_CODE)
638    printf("huffman compression %zu -> %zu (%5.2f %%)\n", size, *msize, (double)((double)(*msize)/size*100));
639#endif // TEST_HUFFMAN_CODE
640    if (*msize >size*2) printf("ssize %d, size %d\n", (int)size, (int)*msize);
641    return buffer;
642}
643
644
645static GB_BUFFER gb_uncompress_equal_bytes(GB_CBUFFER s, size_t size, size_t *new_size) {
646    const signed char *source = (signed char*)s;
647    char              *dest;
648    unsigned int       c;
649    long               j;
650    long               i, k;
651    char              *buffer;
652
653    dest = buffer = GB_give_other_buffer((char *)source, size);
654
655#if defined(DEBUG) && 0
656    printf("gb_uncompress_equal_bytes(size=%li):\n", size);
657#endif // DEBUG
658
659    for (i=size; i;) {
660        j = *(source++);
661#if defined(DEBUG) && 0
662        printf("size=%li (code=%i)\n", i, (int)j);
663#endif // DEBUG
664        if (j>0) {                                  // uncompressed data block
665            if (j>i) j=i;
666            i -= j;
667            for (; j; j--) {
668                *(dest++) = (char)(*(source++));
669            }
670        }
671        else {                                      // equal bytes compressed
672            if (!j) break;                          // end symbol
673            if (j == -122) {
674                j = *(source++) & 0xff;
675                j |= ((*(source++)) << 8) &0xff00;
676                j = -j;
677            }
678            c = *(source++);
679            i += j;
680            if (i<0) {
681                j += -i;
682                i = 0;
683            }
684            if (j<-30) {                            // set multiple bytes
685                j = -j;
686                if (((long)dest) & 1) {
687                    *(dest++) = c;
688                    j--;
689                }
690                if (((long)dest) &2) {
691                    *(dest++) = c;
692                    *(dest++) = c;
693                    j-=2;
694                }
695                c &= 0xff;                          // copy c to upper bytes
696                c |= (c<<8);
697                c |= (c<<16);
698                k  = j&3;
699                j  = j>>2;
700                for (; j; j--) {
701                    *((GB_UINT4 *)dest) = c;
702                    dest += sizeof(GB_UINT4);
703                }
704                j = k;
705                for (; j; j--) *(dest++) = c;
706            }
707            else {
708                for (; j; j++) *(dest++) = c;
709            }
710        }
711    }
712
713    *new_size = dest-buffer;
714    gb_assert(size >= *new_size);                   // buffer overflow
715
716    return buffer;
717}
718
719static GB_BUFFER gb_uncompress_huffmann(GB_CBUFFER source, size_t maxsize, size_t *new_size) {
720    gb_compress_tree *un_tree, *t;
721
722    char *data[1];
723    char *p, *buffer;
724    long  bitp;
725    char  ch = 0, *s;
726    long  val, command;
727
728    un_tree = gb_build_uncompress_tree((unsigned char *)source, 0, data);
729    if (!un_tree) return 0;
730
731    bitp = 0;
732    buffer = p = GB_give_other_buffer(source, maxsize);
733    s = data[0];
734    while (1) {
735        for (t = un_tree; !t->leaf;) {
736            int bit;
737            GB_READ_BIT(s, ch, bitp, bit);
738            t = t->son[bit];
739        }
740        command = (long) t->son[1];
741        if (command == GB_CS_END) break;
742        if (command == GB_CS_ID) {
743            GB_READ_BITS(s, ch, bitp, 8, val);
744        }
745        else {
746            val = (long) t->son[0];
747        }
748        *(p++) = (int)val;
749    }
750    gb_free_compress_tree(un_tree);
751
752    *new_size = p-buffer;
753    gb_assert(maxsize >= *new_size);                // buffer overflow
754
755    return buffer;
756}
757
758GB_BUFFER gb_uncompress_bytes(GB_CBUFFER source, size_t size, size_t *new_size) {
759    char *data     = gb_uncompress_huffmann(source, size, new_size);
760    if (data) data = gb_uncompress_equal_bytes(data, size, new_size);
761    gb_assert(!data || size >= *new_size);          // buffer overflow
762    return data;
763}
764
765// -------------------------------------------------
766//      Compress long and floats (4 byte values)
767
768
769GB_BUFFER gb_uncompress_longs_old(GB_CBUFFER source, size_t size, size_t *new_size)
770{                               // size is byte value
771    char *res  = 0;
772    char *data = gb_uncompress_huffmann(source, (size*9)/8, new_size);
773    if (data) {
774        char *p, *s0, *s1, *s2, *s3;
775        GB_UINT4  mi, i;
776
777        data = gb_uncompress_equal_bytes(data, size, new_size);
778
779        gb_assert(*new_size == size);
780        res = p = GB_give_other_buffer(data, size);
781
782        STATIC_ASSERT(sizeof(GB_UINT4) == 4);
783
784        mi = (GB_UINT4)(size / 4);
785        s0 = data + 0 * mi;
786        s1 = data + 1 * mi;
787        s2 = data + 2 * mi;
788        s3 = data + 3 * mi;
789
790        for (i = 0; i < mi; i++) {
791            *(p++) = *(s0++);
792            *(p++) = *(s1++);
793            *(p++) = *(s2++);
794            *(p++) = *(s3++);
795        }
796
797        *new_size = mi*4;
798    }
799    return res;
800}
801
802
803static GB_BUFFER gb_uncompress_longs(GB_CBUFFER data, size_t size, size_t *new_size) {
804    const char *s0, *s1, *s2, *s3;
805    char       *p, *res;
806    long        mi, i;
807
808    res = p = GB_give_other_buffer(data, size);
809
810    STATIC_ASSERT(sizeof(GB_UINT4) == 4);
811
812    mi = size / 4;
813    s0 = data + 0 * mi;
814    s1 = data + 1 * mi;
815    s2 = data + 2 * mi;
816    s3 = data + 3 * mi;
817
818    for (i = 0; i < mi; i++) {
819        *(p++) = *(s0++);
820        *(p++) = *(s1++);
821        *(p++) = *(s2++);
822        *(p++) = *(s3++);
823    }
824
825    *new_size = mi*4;
826    return res;
827}
828
829static GB_BUFFER gb_compress_longs(GB_CBUFFER source, long size, int last_flag) {
830    long        mi, i;
831    const char *p;
832    char       *s0, *s1, *s2, *s3;
833    char       *dest = GB_give_other_buffer(source, size+1);
834
835    mi = size/4;
836    p = source;
837    *(dest) = GB_COMPRESSION_SORTBYTES | last_flag;
838    s0 = dest + 0*mi + 1;
839    s1 = dest + 1*mi + 1;
840    s2 = dest + 2*mi + 1;
841    s3 = dest + 3*mi + 1;
842    for (i=0; i<mi; i++) {
843        *(s0++) = *(p++);
844        *(s1++) = *(p++);
845        *(s2++) = *(p++);
846        *(s3++) = *(p++);
847    }
848    return dest;
849}
850
851// -----------------------------
852//      Dictionary Functions
853
854GB_DICTIONARY * gb_get_dictionary(GB_MAIN_TYPE *Main, GBQUARK key) {
855    gb_Key *ks = &Main->keys[key];
856    if (ks->gb_key_disabled) return 0;
857    if (!ks->gb_key) {
858        gb_load_single_key_data(Main->gb_main(), key);
859        if (Main->gb_key_data && !ks->gb_key) {
860            GB_internal_error("Couldn't load gb_key");
861        }
862    }
863    return Main->keys[key].dictionary;
864}
865
866bool GB_is_dictionary_compressed(GBDATA *gbd) {
867    if (gbd->is_entry()) {
868        GBENTRY    *gbe  = gbd->as_entry();
869        const char *data = gbe->data();
870
871        if (data) {
872            if (gbe->flags.compressed_data) {
873                size_t   size     = gbe->uncompressed_size();
874                int      last     = 0;
875                GB_ERROR error    = 0;
876                size_t   new_size = -1;
877
878                while (!last) {
879                    int c = *((unsigned char *)(data++));
880
881                    if (c & GB_COMPRESSION_LAST) {
882                        last = 1;
883                        c &= ~GB_COMPRESSION_LAST;
884                    }
885
886                    if (c == GB_COMPRESSION_DICTIONARY) {
887                        return true;
888                    }
889
890                    if (c == GB_COMPRESSION_HUFFMANN) {
891                        data = gb_uncompress_huffmann(data, size + GB_COMPRESSION_TAGS_SIZE_MAX, &new_size);
892                    }
893                    else if (c == GB_COMPRESSION_RUNLENGTH) {
894                        data = gb_uncompress_equal_bytes(data, size + GB_COMPRESSION_TAGS_SIZE_MAX, &new_size);
895                    }
896                    else if (c == GB_COMPRESSION_SEQUENCE) {
897                        data = gb_uncompress_by_sequence(gbe, data, size, &error, &new_size);
898                    }
899                    else if (c == GB_COMPRESSION_SORTBYTES) {
900                        data = gb_uncompress_longs(data, size, &new_size);
901                    }
902                    else {
903                        error = GB_export_errorf("Internal Error: Cannot uncompress data of field '%s'", GB_read_key_pntr(gbe));
904                    }
905
906                    if (error) {
907                        GB_internal_error(error);
908                        break;
909                    }
910                }
911            }
912        }
913    }
914    return false;
915}
916
917// -----------------------------------
918//      Top compression algorithms
919
920GB_BUFFER gb_compress_data(GBDATA *gbd, int key, GB_CBUFFER source, size_t size, size_t *msize, GB_COMPRESSION_MASK max_compr, bool pre_compressed) {
921    // Compress a data string.
922    //
923    // Returns:
924    // - NULL if no compression makes sense
925    // - otherwise returns compressed data and stores its size in 'msize'
926
927    char *data;
928    int   last_flag = GB_COMPRESSION_LAST;
929
930    if (pre_compressed) {
931        last_flag = 0;
932    }
933
934    gb_assert(1);
935
936    if (max_compr & GB_COMPRESSION_SORTBYTES) {
937        source = gb_compress_longs(source, size, last_flag);
938        last_flag = 0;
939        size++;                 // @@@ OLI
940    }
941    else if (max_compr & GB_COMPRESSION_DICTIONARY) {
942        GB_MAIN_TYPE *Main = GB_MAIN(gbd);
943        GB_DICTIONARY *dict;
944        if (!key) {
945            key = GB_KEY_QUARK(gbd);
946        }
947        dict = gb_get_dictionary(Main, key);
948        if (dict) {
949            size_t real_size = size-(gbd->type()==GB_STRING); // for strings w/o trailing zero; @@@ or use is_a_string()?
950
951            if (real_size) {
952                data = gb_compress_by_dictionary(dict, source, real_size, msize, last_flag, 9999, 3);
953
954                if ((*msize<=10 && size>10) || *msize < size*7/8) {  // successfull compression
955                    source = data;
956                    size = *msize;
957                    last_flag = 0;
958                }
959            }
960        }
961
962    }
963    if (max_compr & GB_COMPRESSION_RUNLENGTH && size > GB_RUNLENGTH_MIN_SIZE) {
964        data = gb_compress_equal_bytes(source, size, msize, last_flag);
965        if (*msize < size-10 && *msize < size*7/8) { // successfull compression
966            source = data;
967            size = *msize;
968            last_flag = 0;
969        }
970    }
971
972    if (max_compr & GB_COMPRESSION_HUFFMANN && size > GB_HUFFMAN_MIN_SIZE) {
973        data = gb_compress_huffmann(source, size, msize, last_flag);
974        if (*msize < size-10 && *msize < size*7/8) { // successfull compression
975            source = data;
976            size = *msize;
977            last_flag = 0;
978        }
979    }
980
981    *msize = size;
982
983    if (last_flag) return 0;                        // no compression
984    return (char *)source;
985}
986
987GB_CBUFFER gb_uncompress_data(GBDATA *gbd, GB_CBUFFER source, size_t size) {
988    int         last     = 0;
989    const char *data     = (char *)source;
990    size_t      new_size = -1;
991    GB_ERROR    error    = 0;
992
993    while (!last) {
994        int c = *((unsigned char *)(data++));
995        if (c & GB_COMPRESSION_LAST) {
996            last = 1;
997            c &= ~GB_COMPRESSION_LAST;
998        }
999        if (c == GB_COMPRESSION_HUFFMANN) {
1000            data = gb_uncompress_huffmann(data, size + GB_COMPRESSION_TAGS_SIZE_MAX, &new_size);
1001        }
1002        else if (c == GB_COMPRESSION_RUNLENGTH) {
1003            data = gb_uncompress_equal_bytes(data, size + GB_COMPRESSION_TAGS_SIZE_MAX, &new_size);
1004        }
1005        else if (c == GB_COMPRESSION_DICTIONARY) {
1006            data = gb_uncompress_by_dictionary(gbd, data, size + GB_COMPRESSION_TAGS_SIZE_MAX, &new_size);
1007        }
1008        else if (c == GB_COMPRESSION_SEQUENCE) {
1009            data = gb_uncompress_by_sequence(gbd, data, size, &error, &new_size);
1010        }
1011        else if (c == GB_COMPRESSION_SORTBYTES) {
1012            data = gb_uncompress_longs(data, size, &new_size);
1013        }
1014        else {
1015            error = GBS_global_string("Internal Error: Cannot uncompress data of field '%s'", GB_read_key_pntr(gbd));
1016        }
1017
1018        if (!data && !error) error = GB_await_error();
1019        if (error) last = 1;                        // sth went wrong, stop
1020    }
1021
1022    if (!error && new_size != size) {
1023        error = GBS_global_string("Wrong decompressed size (expected=%zi, got=%zi)", size, new_size);
1024    }
1025
1026    if (error) {
1027        GB_export_error(error);
1028        data = 0;
1029    }
1030
1031    return data;
1032}
1033
Note: See TracBrowser for help on using the repository browser.