FireBirdLib - Topfield TMS PVR TAP Programming Library
lh5.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <string.h>
3#include "libFireBird.h"
4
5#define PERCOLATE
6/*
7NOTE :
8 LHArc uses a "percolating" update of its Lempel-Ziv structures.
9 If you use the percolating method, the compressor will run slightly faster,
10 using a little more memory, and will be slightly less efficient than the
11 standard method.
12 You can choose either method, and note that the decompressor is not
13 affected by this choice and is able To decompress data created by each one
14 of the compressors.
15*/
16
17typedef short *ARPWord;
18typedef byte *ARPByte;
19
20/*
21NOTE :
22 The following constants are set to the values used by LHArc.
23 You can change three of them as follows :
24
25 DICBIT : Lempel-Ziv dictionnary size.
26 Lowering this constant can lower the compression efficiency a lot !
27 But increasing it (on a 32 bit platform only, i.e. Delphi 2) will not yield
28 noticeably better results.
29 If you set DICBIT to 15 or more, set PBIT To 5; and if you set DICBIT to 19
30 or more, set NPT to NP, too.
31
32 WINBIT : Sliding window size.
33 The compression ratio depends a lot of this value.
34 You can increase it to 15 to get better results on large files.
35 I recommend doing this if you have enough memory, except if you want that
36 your compressed data remain compatible with LHArc.
37 On a 32 bit platform, you can increase it to 16. Using a larger value will
38 only waste time and memory.
39
40 BUFBIT : I/O Buffer size. You can lower it to save memory, or increase it
41 to reduce disk access.
42*/
43#define BITBUFSIZ (16)
44#define UCHARMAX (255)
45
46#define DICBIT (13)
47#define DICSIZ (1<<DICBIT)
48
49#define MATCHBIT (8)
50#define MAXMATCH (1<<MATCHBIT)
51#define THRESHOLD (3)
52#define PERCFLAG (0x8000)
53
54#define NC (UCHARMAX+MAXMATCH+2-THRESHOLD)
55#define CBIT (9)
56#define CODEBIT (16)
57
58#define NP (DICBIT+1)
59#define NT (CODEBIT+3)
60#define PBIT 4
61#define TBIT 5
62#define NPT NT
63
64#define NUL (0)
65#define MAXHASHVAL (3*DICSIZ+((DICSIZ>>9)+1)*UCHARMAX)
66
67#define WINBIT (14)
68#define WINDOWSIZE (1<<WINBIT)
69
70#define BUFBIT (15)
71#define BUFSIZE (1<<BUFBIT)
72
73typedef struct {
74 int OrigSize, CompSize;
75
76 word BitBuf;
77 word SubBitBuf, BitCount;
78
79 word Left[2*NC-1], Right[2*NC-1];
80
81 word PtTable[256];
82 byte PtLen[NPT];
83 word CTable[4096];
84 byte CLen[NC];
85
87
88// The following variables are used by the compression engine only
89
91
92 word CFreq[2*NC-1];
93 word PFreq[2*NP-1];
94 word TFreq[2*NT-1];
95
96 word CCode[NC];
97 word PtCode[NPT];
98
99 word CPos, OutputMask;
101
102 word Pos, MatchPos, Avail;
103 ARPWord Position, Parent, Prev, Next;
104
105 short Remainder, MatchLen;
107
108 byte *FileInPtr, *FileOutPtr;
110 word Failed;
112
114 short Decode_J;
115} ARDATA;
116
117static byte GetC(ARDATA *ar);
118static void PutC(ARDATA *ar, byte c);
119static int BRead(ARDATA *ar, byte *p, word n);
120static void BWrite(ARDATA *ar, byte *p, int n);
121static void FillBuf(ARDATA *ar, word n);
122static word GetBits(ARDATA *ar, short n);
123static void PutBits(ARDATA *ar, word n, word x);
124static void InitGetBits(ARDATA *ar);
125static void InitPutBits(ARDATA *ar);
126static void MakeTable(ARDATA *ar, short nchar, ARPByte bitlen, word tablebits, ARPWord table);
127static void ReadPtLen(ARDATA *ar, short nn, short nbit, short ispecial);
128static void ReadCLen(ARDATA *ar);
129static word DecodeC(ARDATA *ar);
130static word DecodeP(ARDATA *ar);
131static void InitVars(ARDATA *ar);
132static void DecodeBuffer(ARDATA *ar, word count, ARPByte arbuffer);
133static void Decode(ARDATA *ar);
134static void CountLen(ARDATA *ar, short i, word *lencnt, short nparm);
135static void MakeLen(ARDATA *ar, short root, word *lencnt, byte *len, short nparm, ARPWord sortptr);
136static void DownHeap(word *heap, short i, short heapsize, ARPWord freqparm);
137static void MakeCode(short n, ARPByte len, ARPWord code, word *lencnt);
138static short MakeTree(ARDATA *ar, short nparm, ARPWord freqparm, byte *len, ARPWord codeparm);
139static void CountTFreq(ARDATA *ar);
140static void WritePtLen(ARDATA *ar, short n, short nbit, short ispecial);
141static void WriteCLen(ARDATA *ar);
142static void EncodeC(ARDATA *ar, short c);
143static void EncodeP(ARDATA *ar, word p);
144static void SendBlock(ARDATA *ar);
145static word Output(ARDATA *ar, word c, word p, word outputpos);
146static void InitSlide(ARDATA *ar);
147static short Hash(short p, byte c);
148static short Child(ARDATA *ar, short q, byte c);
149static void MakeChild(ARDATA *ar, short q, byte c, short r);
150static void Split(ARDATA *ar, short old);
151static void InsertNode(ARDATA *ar);
152static void DeleteNode(ARDATA *ar);
153static void GetNextMatch(ARDATA *ar);
154static int allocate_memory(ARDATA *ar);
155static void free_memory(ARDATA *ar);
156static void Encode(ARDATA *ar);
157
158/********************************** File I/O **********************************/
159
160static inline byte GetC(ARDATA *ar)
161{
162 byte c;
163 c = *ar->FileInPtr;
164 ar->FileInPtr++;
165 ar->InBufferBytes--;
166 return c;
167}
168
169static inline void PutC(ARDATA *ar, byte c)
170{
171 ar->CBytesWritten++;
172 if(ar->CBytesWritten <= 0x7ffa)
173 {
174 if(ar->FileOutPtr)
175 {
176 *ar->FileOutPtr = c;
177 ar->FileOutPtr++;
178 }
179 }
180}
181
182static int BRead(ARDATA *ar, byte *p, word n)
183{
184 if(n>ar->InBufferBytes) n = ar->InBufferBytes;
185 memcpy(p, ar->FileInPtr, n);
186 ar->FileInPtr += n;
187 ar->InBufferBytes -= n;
188 return n;
189}
190
191static void BWrite(ARDATA *ar, byte *p, int n)
192{
193 if(ar->FileOutPtr)
194 {
195 memcpy(ar->FileOutPtr, p, n);
196 ar->FileOutPtr += n;
197 }
198}
199
200/**************************** Bit handling routines ***************************/
201
202static void FillBuf(ARDATA *ar, word n)
203{
204 ar->BitBuf = ar->BitBuf<<n;
205 while(n > ar->BitCount)
206 {
207 n -= ar->BitCount;
208 ar->BitBuf |= ar->SubBitBuf<<n;
209 if(ar->CompSize)
210 {
211 ar->CompSize--;
212 ar->SubBitBuf = GetC(ar);
213 }
214 else
215 ar->SubBitBuf = 0;
216 ar->BitCount = 8;
217 }
218 ar->BitCount -= n;
219 ar->BitBuf |= ar->SubBitBuf>>ar->BitCount;
220}
221
222static word GetBits(ARDATA *ar, short n)
223{
224 word g = ar->BitBuf>>(BITBUFSIZ-n);
225 FillBuf(ar, n);
226 return g;
227}
228
229static void PutBits(ARDATA *ar, word n, word x)
230{
231 if(n < ar->BitCount)
232 {
233 ar->BitCount -= n;
234 ar->SubBitBuf |= x<<ar->BitCount;
235 }
236 else
237 {
238 n -= ar->BitCount;
239 PutC(ar, ar->SubBitBuf | (x>>n));
240 ar->CompSize++;
241 if(n < 8)
242 {
243 ar->BitCount = 8-n;
244 ar->SubBitBuf = x<<ar->BitCount;
245 }
246 else
247 {
248 PutC(ar, x>>(n-8));
249 ar->CompSize++;
250 ar->BitCount = 16-n;
251 ar->SubBitBuf = x<<ar->BitCount;
252 }
253 }
254}
255
256static void InitGetBits(ARDATA *ar)
257{
258 ar->BitBuf = 0;
259 ar->SubBitBuf = 0;
260 ar->BitCount = 0;
261 FillBuf(ar, BITBUFSIZ);
262}
263
264static void InitPutBits(ARDATA *ar)
265{
266 ar->BitCount = 8;
267 ar->SubBitBuf = 0;
268}
269
270/******************************** Decompression *******************************/
271
272
273static void MakeTable(ARDATA *ar, short nchar, ARPByte bitlen, word tablebits, ARPWord table)
274{
275 word count[17], weight[17];
276 word start[18];
277 ARPWord p;
278 word i, k, len, ch, jutbits, avail;
279 word nextcode, mask;
280
281 for(i=1; i<=16; i++)
282 count[i] = 0;
283 for(i=0; i<nchar; i++)
284 count[bitlen[i]]++;
285 start[1] = 0;
286 for(i=1; i<=16; i++)
287 start[i+1] = start[i] + (count[i]<<(16-i));
288 if(start[17])
289 {
290 ar->Failed = TRUE;
291 return;
292 }
293 jutbits = 16-tablebits;
294 for(i=1; i<=tablebits; i++)
295 {
296 start[i] >>= jutbits;
297 weight[i] = 1<<(tablebits-i);
298 }
299 i = tablebits+1;
300 while(i<=16)
301 {
302 weight[i] = 1<<(16-i);
303 i++;
304 }
305 i = start[tablebits+1]>>jutbits;
306 if(i)
307 {
308 k = 1<<tablebits;
309 while(i != k)
310 {
311 table[i] = 0;
312 i++;
313 }
314 }
315 avail = nchar;
316 mask = 1<<(15-tablebits);
317 for(ch=0; ch<nchar; ch++)
318 {
319 len = bitlen[ch];
320 if(len == 0)
321 continue;
322 k = start[len];
323 nextcode = k+weight[len];
324 if(len <= tablebits)
325 {
326 for(i=k; i<nextcode; i++)
327 table[i] = ch;
328 }
329 else
330 {
331 p = &table[k>>jutbits];
332 i = len-tablebits;
333 while(i)
334 {
335 if(*p == 0)
336 {
337 ar->Right[avail] = 0;
338 ar->Left[avail] = 0;
339 *p = avail;
340 avail++;
341 }
342 if(k & mask)
343 p = &ar->Right[*p];
344 else
345 p = &ar->Left[*p];
346 k <<= 1;
347 i--;
348 }
349 *p = ch;
350 }
351 start[len] = nextcode;
352 }
353}
354
355static void ReadPtLen(ARDATA *ar, short nn, short nbit, short ispecial)
356{
357 short i, c, n;
358 word mask;
359 n = GetBits(ar, nbit);
360 if(n == 0)
361 {
362 c = GetBits(ar, nbit);
363 for(i=0; i<nn; i++)
364 ar->PtLen[i] = 0;
365 for(i=0; i<256; i++)
366 ar->PtTable[i] = c;
367 }
368 else
369 {
370 i = 0;
371 while(i<n)
372 {
373 c = ar->BitBuf>>(BITBUFSIZ-3);
374 if(c == 7)
375 {
376 mask = 1<<(BITBUFSIZ-4);
377 while(mask & ar->BitBuf)
378 {
379 mask >>= 1;
380 c++;
381 }
382 }
383 if(c < 7)
384 FillBuf(ar, 3);
385 else
386 FillBuf(ar, c-3);
387 ar->PtLen[i] = c;
388 i++;
389 if(i == ispecial)
390 {
391 c = GetBits(ar,2)-1;
392 while(c >= 0)
393 {
394 ar->PtLen[i] = 0;
395 i++;
396 c--;
397 }
398 }
399 }
400 while(i < nn)
401 {
402 ar->PtLen[i] = 0;
403 i++;
404 }
405 MakeTable(ar, nn, ar->PtLen, 8, ar->PtTable);
406 }
407}
408
409static void ReadCLen(ARDATA *ar)
410{
411 short i, c, n;
412 word mask;
413 n = GetBits(ar, CBIT);
414 if(n == 0)
415 {
416 c = GetBits(ar, CBIT);
417 for(i=0; i<NC; i++)
418 ar->CLen[i] = 0;
419 for(i=0; i<4096; i++)
420 ar->CTable[i] = c;
421 }
422 else
423 {
424 i = 0;
425 while(i < n)
426 {
427 c = ar->PtTable[ar->BitBuf>>(BITBUFSIZ-8)];
428 if(c >= NT)
429 {
430 mask = 1<<(BITBUFSIZ-9);
431 do
432 {
433 if(ar->BitBuf & mask)
434 c = ar->Right[c];
435 else
436 c = ar->Left[c];
437 mask >>= 1;
438 } while(c>=NT);
439 }
440 FillBuf(ar, ar->PtLen[c]);
441 if(c <= 2)
442 {
443 if(c == 1)
444 c = 2+GetBits(ar, 4);
445 else if(c == 2)
446 c = 19+GetBits(ar, CBIT);
447 while(c >= 0)
448 {
449 ar->CLen[i] = 0;
450 i++;
451 c--;
452 }
453 }
454 else
455 {
456 ar->CLen[i] = c-2;
457 i++;
458 }
459 }
460 while(i < NC)
461 {
462 ar->CLen[i] = 0;
463 i++;
464 }
465 MakeTable(ar, NC, ar->CLen, 12, ar->CTable);
466 }
467}
468
469static word DecodeC(ARDATA *ar)
470{
471 word j, mask;
472 if(ar->BlockSize == 0)
473 {
474 ar->BlockSize = GetBits(ar,16);
475 ReadPtLen(ar, NT, TBIT, 3);
476 if(ar->Failed)
477 return 0;
478 ReadCLen(ar);
479 if(ar->Failed)
480 return 0;
481 ReadPtLen(ar, NP, PBIT, -1);
482 if(ar->Failed)
483 return 0;
484 }
485 ar->BlockSize--;
486 j = ar->CTable[ar->BitBuf>>(BITBUFSIZ-12)];
487 if(j >= NC)
488 {
489 mask = 1<<(BITBUFSIZ-13);
490 do
491 {
492 if(ar->BitBuf & mask)
493 j = ar->Right[j];
494 else
495 j = ar->Left[j];
496 mask >>= 1;
497 } while(j >= NC);
498 }
499 FillBuf(ar, ar->CLen[j]);
500 return j;
501}
502
503static word DecodeP(ARDATA *ar)
504{
505 word j, mask;
506 j = ar->PtTable[ar->BitBuf>>(BITBUFSIZ-8)];
507 if(j >= NP)
508 {
509 mask = 1<<(BITBUFSIZ-9);
510 do
511 {
512 if(ar->BitBuf & mask)
513 j = ar->Right[j];
514 else
515 j = ar->Left[j];
516 mask >>= 1;
517 } while(j >= NP);
518 }
519 FillBuf(ar, ar->PtLen[j]);
520 if(j)
521 {
522 j--;
523 j = (1<<j)+GetBits(ar,j);
524 }
525 return j;
526}
527
528static void InitVars(ARDATA *ar)
529{
530 memset(ar, 0, sizeof(ARDATA));
531}
532
533static void DecodeBuffer(ARDATA *ar, word count, ARPByte arbuffer)
534{
535 word c, r;
536 r = 0;
537 ar->Decode_J--;
538 while(ar->Decode_J >= 0)
539 {
540 arbuffer[r] = arbuffer[ar->Decode_I];
541 ar->Decode_I = (ar->Decode_I+1) & (DICSIZ-1);
542 r++;
543 if(r == count) return;
544 ar->Decode_J--;
545 }
546 while(TRUE)
547 {
548 c = DecodeC(ar);
549 if(ar->Failed) return;
550 if(c <= UCHARMAX)
551 {
552 arbuffer[r] = c;
553 r++;
554 if(r == count) return;
555 }
556 else
557 {
558 ar->Decode_J = c-(UCHARMAX+1-THRESHOLD);
559 ar->Decode_I = (r-DecodeP(ar)-1) & (DICSIZ-1);
560 ar->Decode_J--;
561 while(ar->Decode_J >= 0)
562 {
563 arbuffer[r] = arbuffer[ar->Decode_I];
564 ar->Decode_I = (ar->Decode_I+1) & (DICSIZ-1);
565 r++;
566 if(r == count) return;
567 ar->Decode_J--;
568 }
569 }
570 }
571}
572
573static void Decode(ARDATA *ar)
574{
575 int l;
576 word a;
577 byte dp[DICSIZ];
578 // Initialize decoder variables
579 InitGetBits(ar);
580 ar->BlockSize = 0;
581 ar->Decode_J = 0;
582 l = ar->OrigSize;
583 while(l > 0)
584 {
585 if(l > DICSIZ)
586 a = DICSIZ;
587 else
588 a = l;
589 DecodeBuffer(ar, a, dp);
590 if(ar->Failed) return;
591 BWrite(ar, dp, a);
592 l -= a;
593 }
594}
595
596/********************************* Compression ********************************/
597
598// -------------------------------- Huffman part --------------------------------
599
600static void CountLen(ARDATA *ar, short i, word *lencnt, short nparm)
601{
602 word depth = 0;
603 short buf1[NC/2+1], buf2[NC/2+1];
604 short *old = buf1, *new = buf2;
605 int oldsz, newsz = 1;
606 *new = i;
607 while(newsz)
608 {
609 short *t = old;
610 int n;
611 // Swap old and new buffers
612 old = new; new = t;
613 oldsz = newsz; newsz = 0;
614 // Scan old, make new
615 for(n = 0; n < oldsz; n++)
616 {
617 short j = old[n];
618 if(j < nparm)
619 {
620 if(depth < 16)
621 lencnt[depth]++;
622 else
623 lencnt[16]++;
624 }
625 else
626 {
627 new[newsz] = ar->Left[j];
628 new[newsz+1] = ar->Right[j];
629 newsz += 2;
630 }
631 }
632 depth++;
633 }
634}
635
636static void MakeLen(ARDATA *ar, short root, word *lencnt, byte *len, short nparm, ARPWord sortptr)
637{
638 short i, k;
639 word cum;
640 for(i=0; i<17; i++)
641 lencnt[i] = 0;
642 CountLen(ar, root, lencnt, nparm);
643 cum = 0;
644 for(i=16; i>0; i--)
645 cum += lencnt[i]<<(16-i);
646 while(cum)
647 {
648 lencnt[16]--;
649 for(i=15; i>0; i--)
650 {
651 if(lencnt[i])
652 {
653 lencnt[i]--;
654 lencnt[i+1] += 2;
655 break;
656 }
657 }
658 cum--;
659 }
660 for(i=16; i>0; i--)
661 {
662 k = lencnt[i]-1;
663 while(k >= 0)
664 {
665 k--;
666 len[*sortptr] = i;
667 sortptr++;
668 }
669 }
670}
671
672static void DownHeap(word *heap, short i, short heapsize, ARPWord freqparm)
673{
674 short j, k;
675 k = heap[i];
676 j = i<<1;
677 while(j <= heapsize)
678 {
679 if(j < heapsize && freqparm[heap[j]] > freqparm[heap[j+1]]) j++;
680 if(freqparm[k] <= freqparm[heap[j]]) break;
681 heap[i] = heap[j];
682 i = j;
683 j = i<<1;
684 }
685 heap[i] = k;
686}
687
688static void MakeCode(short n, ARPByte len, ARPWord code, word *lencnt)
689{
690 short i, k;
691 word start[18];
692 start[1] = 0;
693 for(i=1; i<17; i++)
694 start[i+1] = (start[i]+lencnt[i]) << 1;
695 for(i=0; i<n; i++)
696 {
697 k = len[i];
698 code[i] = start[k];
699 start[k]++;
700 }
701}
702
703static short MakeTree(ARDATA *ar, short nparm, ARPWord freqparm, byte *len, ARPWord codeparm)
704{
705 short i, j, k, avail;
706 word lencnt[17];
707 ARPWord sortptr;
708 short heapsize = 0;
709 word heap[NC+1];
710 avail = nparm;
711 heap[1] = 0;
712 for(i=0; i<nparm; i++)
713 {
714 len[i] = 0;
715 if(freqparm[i])
716 {
717 heapsize++;
718 heap[heapsize] = i;
719 }
720 }
721 if(heapsize < 2)
722 {
723 codeparm[heap[1]] = 0;
724 return heap[1];
725 }
726 for(i=heapsize/2; i>0; i--) DownHeap(heap, i, heapsize, freqparm);
727 sortptr = codeparm;
728 do
729 {
730 i = heap[1];
731 if(i < nparm)
732 {
733 *sortptr = i;
734 sortptr++;
735 }
736 heap[1] = heap[heapsize];
737 heapsize--;
738 DownHeap(heap, 1, heapsize, freqparm);
739 j = heap[1];
740 if(j < nparm)
741 {
742 *sortptr = j;
743 sortptr++;
744 }
745 k = avail;
746 avail++;
747 freqparm[k] = freqparm[i]+freqparm[j];
748 heap[1] = k;
749 DownHeap(heap, 1, heapsize, freqparm);
750 ar->Left[k] = i;
751 ar->Right[k] = j;
752 } while(heapsize > 1);
753 MakeLen(ar, k, lencnt, len, nparm, codeparm);
754 MakeCode(nparm, len, codeparm, lencnt);
755 return k;
756}
757
758static void CountTFreq(ARDATA *ar)
759{
760 short i, k, n, count;
761 for(i = 0; i<NT; i++) ar->TFreq[i] = 0;
762 n = NC;
763 while(n>0 && ar->CLen[n-1] == 0)
764 {
765 n--;
766 }
767 i = 0;
768 while(i < n)
769 {
770 k = ar->CLen[i];
771 i++;
772 if(k == 0)
773 {
774 count = 1;
775 while(i<n && ar->CLen[i] == 0)
776 {
777 i++;
778 count++;
779 }
780 if(count <= 2)
781 ar->TFreq[0] += count;
782 else if(count <= 18)
783 ar->TFreq[1]++;
784 else if(count == 19)
785 {
786 ar->TFreq[0]++;
787 ar->TFreq[1]++;
788 }
789 else
790 ar->TFreq[2]++;
791 }
792 else
793 ar->TFreq[k+2]++;
794 }
795}
796
797static void WritePtLen(ARDATA *ar, short n, short nbit, short ispecial)
798{
799 short i, k;
800 while(n>0 && ar->PtLen[n-1] == 0) n--;
801 PutBits(ar, nbit, n);
802 i = 0;
803 while(i < n)
804 {
805 k = ar->PtLen[i];
806 i++;
807 if(k <= 6)
808 PutBits(ar, 3, k);
809 else
810 {
811 k -= 3;
812 PutBits(ar, k, (1<<k)-2);
813 }
814 if(i == ispecial)
815 {
816 while(i<6 && ar->PtLen[i] == 0) i++;
817 PutBits(ar, 2, (i-3) & 3);
818 }
819 }
820}
821
822static void WriteCLen(ARDATA *ar)
823{
824 short i, k, n, count;
825 n = NC;
826 while(n>0 && ar->CLen[n-1] == 0) n--;
827 PutBits(ar, CBIT, n);
828 i = 0;
829 while(i<n)
830 {
831 k = ar->CLen[i];
832 i++;
833 if(k == 0)
834 {
835 count = 1;
836 while(i<n && ar->CLen[i] == 0)
837 {
838 i++;
839 count++;
840 }
841 if(count <= 2)
842 {
843 for(k=0; k<count; k++)
844 PutBits(ar, ar->PtLen[0], ar->PtCode[0]);
845 }
846 else if(count <= 18)
847 {
848 PutBits(ar, ar->PtLen[1], ar->PtCode[1]);
849 PutBits(ar, 4, count-3);
850 }
851 else if(count == 19)
852 {
853 PutBits(ar, ar->PtLen[0], ar->PtCode[0]);
854 PutBits(ar, ar->PtLen[1], ar->PtCode[1]);
855 PutBits(ar, 4, 15);
856 }
857 else
858 {
859 PutBits(ar, ar->PtLen[2], ar->PtCode[2]);
860 PutBits(ar, CBIT, count-20);
861 }
862 }
863 else
864 PutBits(ar, ar->PtLen[k+2], ar->PtCode[k+2]);
865 }
866}
867
868static void EncodeC(ARDATA *ar, short c)
869{
870 PutBits(ar, ar->CLen[c], ar->CCode[c]);
871}
872
873static void EncodeP(ARDATA *ar, word p)
874{
875 word c, q;
876 c = 0;
877 q = p;
878 while(q)
879 {
880 q >>= 1;
881 c++;
882 }
883 PutBits(ar, ar->PtLen[c], ar->PtCode[c]);
884 if(c > 1) PutBits(ar, c-1, p & (0xFFFF>>(17-c)));
885}
886
887static void SendBlock(ARDATA *ar)
888{
889 word i, k, flags, root, pos, size;
890 flags = 0;
891 root = MakeTree(ar, NC, ar->CFreq, ar->CLen, ar->CCode);
892 size = ar->CFreq[root];
893 PutBits(ar, 16, size);
894 if(root >= NC)
895 {
896 CountTFreq(ar);
897 root = MakeTree(ar, NT, ar->TFreq, ar->PtLen, ar->PtCode);
898 if(root >= NT)
899 WritePtLen(ar, NT, TBIT, 3);
900 else
901 {
902 PutBits(ar, TBIT, 0);
903 PutBits(ar, TBIT, root);
904 }
905 WriteCLen(ar);
906 }
907 else
908 {
909 PutBits(ar, TBIT, 0);
910 PutBits(ar, TBIT, 0);
911 PutBits(ar, CBIT, 0);
912 PutBits(ar, CBIT, root);
913 }
914 root = MakeTree(ar, NP, ar->PFreq, ar->PtLen, ar->PtCode);
915 if(root >= NP)
916 WritePtLen(ar, NP, PBIT, -1);
917 else
918 {
919 PutBits(ar, PBIT, 0);
920 PutBits(ar, PBIT, root);
921 }
922 pos = 0;
923 for(i=0; i<size; i++)
924 {
925 if((i & 7) == 0)
926 {
927 flags = ar->Buf[pos];
928 pos++;
929 }
930 else
931 flags <<= 1;
932 if(flags & (1<<7))
933 {
934 k = ar->Buf[pos] + (1<<8);
935 pos++;
936 EncodeC(ar, k);
937 k = ar->Buf[pos] << 8;
938 pos++;
939 k += ar->Buf[pos];
940 pos++;
941 EncodeP(ar, k);
942 }
943 else
944 {
945 k = ar->Buf[pos];
946 pos++;
947 EncodeC(ar, k);
948 }
949 }
950 for(i=0; i<NC; i++) ar->CFreq[i] = 0;
951 for(i=0; i<NP; i++) ar->PFreq[i] = 0;
952}
953
954static word Output(ARDATA *ar, word c, word p, word outputpos)
955{
956 ar->OutputMask >>= 1;
957 if(ar->OutputMask == 0)
958 {
959 ar->OutputMask = 1<<7;
960 if(outputpos >= WINDOWSIZE-24)
961 {
962 SendBlock(ar);
963 outputpos = 0;
964 }
965 ar->CPos = outputpos;
966 outputpos++;
967 ar->Buf[ar->CPos] = 0;
968 }
969 ar->Buf[outputpos] = c;
970 outputpos++;
971 ar->CFreq[c]++;
972 if(c >= (1<<8))
973 {
974 ar->Buf[ar->CPos] |= ar->OutputMask;
975 ar->Buf[outputpos] = p>>8;
976 outputpos++;
977 ar->Buf[outputpos] = p;
978 outputpos++;
979 c = 0;
980 while(p)
981 {
982 p >>= 1;
983 c++;
984 }
985 ar->PFreq[c]++;
986 }
987 return outputpos;
988}
989
990//------------------------------- Lempel-Ziv part ------------------------------
991
992static void InitSlide(ARDATA *ar)
993{
994 word i;
995 for(i=DICSIZ; i<=DICSIZ+UCHARMAX; i++)
996 {
997 ar->Level[i] = 1;
998#ifdef PERCOLATE
999 ar->Position[i] = NUL;
1000#endif
1001 }
1002 for(i=DICSIZ; i<2*DICSIZ; i++) ar->Parent[i] = NUL;
1003 ar->Avail = 1;
1004 for(i=1; i<DICSIZ-1; i++) ar->Next[i] = i+1;
1005 ar->Next[DICSIZ-1] = NUL;
1006 for(i=2*DICSIZ; i<=MAXHASHVAL; i++) ar->Next[i] = NUL;
1007}
1008
1009// Hash Function
1010static inline short Hash(short p, byte c)
1011{
1012 return p+(c<<(DICBIT-9))+2*DICSIZ;
1013}
1014
1015static inline short Child(ARDATA *ar, short q, byte c)
1016{
1017 short r;
1018 r = ar->Next[Hash(q, c)];
1019 ar->Parent[NUL] = q;
1020 while(ar->Parent[r] != q) r = ar->Next[r];
1021 return r;
1022}
1023
1024static inline void MakeChild(ARDATA *ar, short q, byte c, short r)
1025{
1026 short h, t;
1027 h = Hash(q, c);
1028 t = ar->Next[h];
1029 ar->Next[h] = r;
1030 ar->Next[r] = t;
1031 ar->Prev[t] = r;
1032 ar->Prev[r] = h;
1033 ar->Parent[r] = q;
1034 ar->ChildCount[q]++;
1035}
1036
1037static void Split(ARDATA *ar, short old)
1038{
1039 short new, t;
1040 new = ar->Avail;
1041 ar->Avail = ar->Next[new];
1042 ar->ChildCount[new] = 0;
1043 t = ar->Prev[old];
1044 ar->Prev[new] = t;
1045 ar->Next[t] = new;
1046 t = ar->Next[old];
1047 ar->Next[new] = t;
1048 ar->Prev[t] = new;
1049 ar->Parent[new] = ar->Parent[old];
1050 ar->Level[new] = ar->MatchLen;
1051 ar->Position[new] = ar->Pos;
1052 MakeChild(ar, new, ar->Text[ar->MatchPos+ar->MatchLen], old);
1053 MakeChild(ar, new, ar->Text[ar->Pos+ar->MatchLen], ar->Pos);
1054}
1055
1056static void InsertNode(ARDATA *ar)
1057{
1058 short q, r, j, t;
1059 byte c;
1060 ARPByte t1, t2;
1061 if(ar->MatchLen >= 4)
1062 {
1063 ar->MatchLen--;
1064 r = (ar->MatchPos+1) | DICSIZ;
1065 q = ar->Parent[r];
1066 while(q == NUL)
1067 {
1068 r = ar->Next[r];
1069 q = ar->Parent[r];
1070 }
1071 while(ar->Level[q] >= ar->MatchLen)
1072 {
1073 r = q;
1074 q = ar->Parent[q];
1075 }
1076 t = q;
1077#ifdef PERCOLATE
1078 while(ar->Position[t] < 0)
1079 {
1080 ar->Position[t] = ar->Pos;
1081 t = ar->Parent[t];
1082 }
1083 if(t < DICSIZ) ar->Position[t] = ar->Pos | PERCFLAG;
1084#else
1085 while(t < DICSIZ)
1086 {
1087 ar->Position[t] = ar->Pos;
1088 t = ar->Parent[t];
1089 }
1090#endif
1091 }
1092 else
1093 {
1094 q = ar->Text[ar->Pos]+DICSIZ;
1095 c = ar->Text[ar->Pos+1];
1096 r = Child(ar, q, c);
1097 if(r == NUL)
1098 {
1099 MakeChild(ar, q, c, ar->Pos);
1100 ar->MatchLen = 1;
1101 return;
1102 }
1103 ar->MatchLen = 2;
1104 }
1105 while(TRUE)
1106 {
1107 if(r >= DICSIZ)
1108 {
1109 j = MAXMATCH;
1110 ar->MatchPos = r;
1111 }
1112 else
1113 {
1114 j = ar->Level[r];
1115 ar->MatchPos = ar->Position[r] & ~PERCFLAG;
1116 }
1117 if(ar->MatchPos >= ar->Pos) ar->MatchPos -= DICSIZ;
1118 t1 = &ar->Text[ar->Pos+ar->MatchLen];
1119 t2 = &ar->Text[ar->MatchPos+ar->MatchLen];
1120 while(ar->MatchLen < j)
1121 {
1122 if(*t1 != *t2)
1123 {
1124 Split(ar, r);
1125 return;
1126 }
1127 ar->MatchLen++;
1128 t1++;
1129 t2++;
1130 }
1131 if(ar->MatchLen >= MAXMATCH) break;
1132 ar->Position[r] = ar->Pos;
1133 q = r;
1134 r = Child(ar, q, *t1);
1135 if(r == NUL)
1136 {
1137 MakeChild(ar, q, *t1, ar->Pos);
1138 return;
1139 }
1140 ar->MatchLen++;
1141 }
1142 t = ar->Prev[r];
1143 ar->Prev[ar->Pos] = t;
1144 ar->Next[t] = ar->Pos;
1145 t = ar->Next[r];
1146 ar->Next[ar->Pos] = t;
1147 ar->Prev[t] = ar->Pos;
1148 ar->Parent[ar->Pos] = q;
1149 ar->Parent[r] = NUL;
1150 ar->Next[r] = ar->Pos;
1151}
1152
1153static void DeleteNode(ARDATA *ar)
1154{
1155 word r, s, t, u;
1156#ifdef PERCOLATE
1157 short q;
1158#endif
1159 if(ar->Parent[ar->Pos] == NUL) return;
1160 r = ar->Prev[ar->Pos];
1161 s = ar->Next[ar->Pos];
1162 ar->Next[r] = s;
1163 ar->Prev[s] = r;
1164 r = ar->Parent[ar->Pos];
1165 ar->Parent[ar->Pos] = NUL;
1166 ar->ChildCount[r]--;
1167 if(r >= DICSIZ || ar->ChildCount[r] > 1) return;
1168#ifdef PERCOLATE
1169 t = ar->Position[r] & ~PERCFLAG;
1170#else
1171 t = ar->Position[r];
1172#endif
1173 if(t >= ar->Pos) t -= DICSIZ;
1174#ifdef PERCOLATE
1175 s = t;
1176 q = ar->Parent[r];
1177 u = ar->Position[q];
1178 while(u & PERCFLAG)
1179 {
1180 u &= ~PERCFLAG;
1181 if(u >= ar->Pos) u -= DICSIZ;
1182 if(u > s) s = u;
1183 ar->Position[q] = s | DICSIZ;
1184 q = ar->Parent[q];
1185 u = ar->Position[q];
1186 }
1187 if(q < DICSIZ)
1188 {
1189 if(u >= ar->Pos) u -= DICSIZ;
1190 if(u > s) s = u;
1191 ar->Position[q] = s | DICSIZ | PERCFLAG;
1192 }
1193#endif
1194 s = Child(ar, r, ar->Text[t+ar->Level[r]]);
1195 t = ar->Prev[s];
1196 u = ar->Next[s];
1197 ar->Next[t] = u;
1198 ar->Prev[u] = t;
1199 t = ar->Prev[r];
1200 ar->Next[t] = s;
1201 ar->Prev[s] = t;
1202 t = ar->Next[r];
1203 ar->Prev[t] = s;
1204 ar->Next[s] = t;
1205 ar->Parent[s] = ar->Parent[r];
1206 ar->Parent[r] = NUL;
1207 ar->Next[r] = ar->Avail;
1208 ar->Avail = r;
1209}
1210
1211static void GetNextMatch(ARDATA *ar)
1212{
1213 short n;
1214 ar->Remainder--;
1215 ar->Pos++;
1216 if(ar->Pos == 2*DICSIZ)
1217 {
1218 memmove(&ar->Text[0], &ar->Text[DICSIZ], DICSIZ+MAXMATCH);
1219 n = BRead(ar, &ar->Text[DICSIZ+MAXMATCH], DICSIZ);
1220 ar->Remainder += n;
1221 ar->Pos = DICSIZ;
1222 }
1223 DeleteNode(ar);
1224 InsertNode(ar);
1225}
1226
1227static int allocate_memory(ARDATA *ar)
1228{
1229 ar->Text = TAP_MemAlloc(2*DICSIZ+MAXMATCH);
1230 ar->Level = TAP_MemAlloc(DICSIZ+UCHARMAX+1);
1231 ar->ChildCount = TAP_MemAlloc(DICSIZ+UCHARMAX+1);
1232#ifdef PERCOLATE
1233 ar->Position = TAP_MemAlloc((DICSIZ+UCHARMAX+1) << 1);
1234#else
1235 ar->Position = TAP_MemAlloc(DICSIZ << 1);
1236#endif
1237 ar->Parent = TAP_MemAlloc((DICSIZ*2) << 1);
1238 ar->Prev = TAP_MemAlloc((DICSIZ*2) << 1);
1239 ar->Next = TAP_MemAlloc((MAXHASHVAL+1) << 1);
1240
1241 ar->Buf = TAP_MemAlloc(WINDOWSIZE);
1242 return ar->Buf != NULL;
1243}
1244
1245#define FREEMEM(p) if(p) {TAP_MemFree(p); p = NULL;}
1246
1247static void free_memory(ARDATA *ar)
1248{
1249 FREEMEM(ar->Buf);
1250 FREEMEM(ar->Next);
1251 FREEMEM(ar->Prev);
1252 FREEMEM(ar->Parent);
1253 FREEMEM(ar->Position);
1254 FREEMEM(ar->Position);
1255 FREEMEM(ar->ChildCount);
1256 FREEMEM(ar->Level);
1257 FREEMEM(ar->Text);
1258}
1259
1260static void Encode(ARDATA *ar)
1261{
1262 // initialize encoder variables
1263 if(!allocate_memory(ar))
1264 {
1265 LogEntryFBLibPrintf(TRUE, "lh5.Encode: unable to allocate memory");
1266 }
1267 else
1268 {
1269 short lastmatchlen, lastmatchpos;
1270 word outputpos = 0;
1271 InitSlide(ar);
1272 ar->Buf[0] = 0;
1273 memset(ar->CFreq, 0, sizeof(ar->CFreq));
1274 memset(ar->PFreq, 0, sizeof(ar->PFreq));
1275 ar->OutputMask = 0;
1276 InitPutBits(ar);
1277 ar->Remainder = BRead(ar, &ar->Text[DICSIZ], DICSIZ+MAXMATCH);
1278 ar->MatchLen = 0;
1279 ar->Pos = DICSIZ;
1280 InsertNode(ar);
1281 if(ar->MatchLen > ar->Remainder) ar->MatchLen = ar->Remainder;
1282 while(ar->Remainder > 0)
1283 {
1284 lastmatchlen = ar->MatchLen;
1285 lastmatchpos = ar->MatchPos;
1286 GetNextMatch(ar);
1287 if(ar->MatchLen > ar->Remainder) ar->MatchLen = ar->Remainder;
1288 if(ar->MatchLen > lastmatchlen || lastmatchlen < THRESHOLD)
1289 outputpos = Output(ar, ar->Text[ar->Pos-1], 0, outputpos);
1290 else
1291 {
1292 outputpos = Output(ar, lastmatchlen+(UCHARMAX+1-THRESHOLD), (ar->Pos-lastmatchpos-2) & (DICSIZ-1), outputpos);
1293 lastmatchlen--;
1294 while(lastmatchlen > 0)
1295 {
1296 GetNextMatch(ar);
1297 lastmatchlen--;
1298 }
1299 if(ar->MatchLen > ar->Remainder) ar->MatchLen = ar->Remainder;
1300 }
1301 }
1302 // flush buffers
1303 SendBlock(ar);
1304 PutBits(ar, 7,0);
1305 }
1306 free_memory(ar);
1307}
1308
1309word CompressBlock(byte *inputbuffer, word inputsize, byte *outputbuffer)
1310{
1311 TRACEENTER();
1312
1313 if(!inputbuffer || inputsize > 0x7ffa)
1314 {
1315 TRACEEXIT();
1316 return 0;
1317 }
1318
1319 int compsize = 0;
1320 ARDATA *ar = TAP_MemAlloc(sizeof(ARDATA));
1321 if(ar)
1322 {
1323 InitVars(ar);
1324 ar->FileInPtr = inputbuffer;
1325 ar->FileOutPtr = outputbuffer;
1326 ar->InBufferBytes = inputsize;
1327 Encode(ar);
1328 compsize = ar->CompSize;
1329 // Copy the Buffer If encoding failed
1330 if(compsize == 0 || ar->CBytesWritten > 0x7ffa)
1331 {
1332 if(outputbuffer) memcpy(outputbuffer, inputbuffer, inputsize);
1333 compsize = inputsize;
1334 }
1335 TAP_MemFree(ar);
1336 }
1337
1338 TRACEEXIT();
1339 return compsize;
1340}
1341
1342word UncompressBlock(byte *inputbuffer, word inputsize, byte *outputbuffer, word BufferSize)
1343{
1344 TRACEENTER();
1345
1346 if(!inputbuffer)
1347 {
1348 TRACEEXIT();
1349 return 0;
1350 }
1351
1352 ARDATA *ar = TAP_MemAlloc(sizeof(ARDATA));
1353 if(!ar)
1354 {
1355 TRACEEXIT();
1356 return 0;
1357 }
1358
1359 word failed;
1360
1361 InitVars(ar);
1362 ar->FileInPtr = inputbuffer;
1363 ar->FileOutPtr = outputbuffer;
1364 ar->CompSize = inputsize;
1365 ar->InBufferBytes = inputsize;
1366 ar->OrigSize = BufferSize;
1367 Decode(ar);
1368 failed = ar->Failed;
1369 TAP_MemFree(ar);
1370
1371 TRACEEXIT();
1372 return !failed;
1373
1374}
dword BufferSize
Definition: INIOpenFile.c:7
void LogEntryFBLibPrintf(bool Console, char *format,...)
#define NPT
Definition: lh5.c:62
#define NC
Definition: lh5.c:54
#define UCHARMAX
Definition: lh5.c:44
#define TBIT
Definition: lh5.c:61
byte * ARPByte
Definition: lh5.c:18
#define THRESHOLD
Definition: lh5.c:51
#define DICSIZ
Definition: lh5.c:47
#define PERCFLAG
Definition: lh5.c:52
#define MAXHASHVAL
Definition: lh5.c:65
#define PBIT
Definition: lh5.c:60
#define MAXMATCH
Definition: lh5.c:50
#define DICBIT
Definition: lh5.c:46
#define WINDOWSIZE
Definition: lh5.c:68
#define NT
Definition: lh5.c:59
#define BITBUFSIZ
Definition: lh5.c:43
word UncompressBlock(byte *inputbuffer, word inputsize, byte *outputbuffer, word BufferSize)
Definition: lh5.c:1342
#define CBIT
Definition: lh5.c:55
#define FREEMEM(p)
Definition: lh5.c:1245
#define NP
Definition: lh5.c:58
word CompressBlock(byte *inputbuffer, word inputsize, byte *outputbuffer)
Definition: lh5.c:1309
#define NUL
Definition: lh5.c:64
short * ARPWord
Definition: lh5.c:17
#define TRACEEXIT()
Definition: libFireBird.h:1244
#define TRACEENTER()
Definition: libFireBird.h:1243
word Decode_I
Definition: lh5.c:113
short Remainder
Definition: lh5.c:105
word Failed
Definition: lh5.c:110
word SubBitBuf
Definition: lh5.c:77
word Right[2 *NC-1]
Definition: lh5.c:79
byte PtLen[NPT]
Definition: lh5.c:82
dword CompSize
word PtTable[256]
Definition: lh5.c:81
byte * FileOutPtr
Definition: lh5.c:108
short Decode_J
Definition: lh5.c:114
word PtCode[NPT]
Definition: lh5.c:97
byte CLen[NC]
Definition: lh5.c:84
word BlockSize
Definition: lh5.c:86
word Avail
Definition: lh5.c:102
word CFreq[2 *NC-1]
Definition: lh5.c:92
word TFreq[2 *NT-1]
Definition: lh5.c:94
byte * FileInPtr
Definition: lh5.c:108
ARPWord Position
Definition: lh5.c:103
word CTable[4096]
Definition: lh5.c:83
word BitBuf
Definition: lh5.c:76
word BitCount
Definition: lh5.c:77
ARPWord Prev
Definition: lh5.c:103
word PFreq[2 *NP-1]
Definition: lh5.c:93
ARPWord Next
Definition: lh5.c:103
ARPByte Buf
Definition: lh5.c:90
ARPWord Parent
Definition: lh5.c:103
word CCode[NC]
Definition: lh5.c:96
dword OrigSize
ARPByte Level
Definition: lh5.c:106
word MatchPos
Definition: lh5.c:102
word CPos
Definition: lh5.c:99
ARPByte Text
Definition: lh5.c:100
short MatchLen
Definition: lh5.c:105
word OutputMask
Definition: lh5.c:99
dword InBufferBytes
Definition: lh5.c:109
ARPByte ChildCount
Definition: lh5.c:100
int CompSize
Definition: lh5.c:74
dword CBytesWritten
Definition: lh5.c:111
word Left[2 *NC-1]
Definition: lh5.c:79
word Pos
Definition: lh5.c:102