source: tags/arb_5.2/ARBDB/adcompr.c

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