Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(261)

Side by Side Diff: utility/eficompress.c

Issue 6508006: Enable EFIv1 compression in bmpbklk_utility. (Closed) Base URL: http://git.chromium.org/git/vboot_reference.git@master
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD Licens e
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 EfiCompress.c
15
16 Abstract:
17
18 Compression routine. The compression algorithm is a mixture of
19 LZ77 and Huffman coding. LZ77 transforms the source data into a
20 sequence of Original Characters and Pointers to repeated strings.
21 This sequence is further divided into Blocks and Huffman codings
22 are applied to each Block.
23
24 --*/
25
26 #include <errno.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34
35 #include "eficompress.h"
36
37
38 //
39 // Macro Definitions
40 //
41
42 typedef INT16 NODE;
43 #define UINT8_BIT 8
44 #define THRESHOLD 3
45 #define INIT_CRC 0
46 #define WNDBIT 13
47 #define WNDSIZ (1U << WNDBIT)
48 #define MAXMATCH 256
49 #define PERC_FLAG 0x8000U
50 #define CODE_BIT 16
51 #define NIL 0
52 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
53 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
54 #define CRCPOLY 0xA001
55 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8 _BIT)
56
57 //
58 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
59 //
60
61 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
62 #define CBIT 9
63 #define NP (WNDBIT + 1)
64 #define PBIT 4
65 #define NT (CODE_BIT + 3)
66 #define TBIT 5
67 #if NT > NP
68 #define NPT NT
69 #else
70 #define NPT NP
71 #endif
72
73 //
74 // Function Prototypes
75 //
76
77 STATIC
78 VOID
79 PutDword(
80 IN UINT32 Data
81 );
82
83 STATIC
84 EFI_STATUS
85 AllocateMemory (
86 );
87
88 STATIC
89 VOID
90 FreeMemory (
91 );
92
93 STATIC
94 VOID
95 InitSlide (
96 );
97
98 STATIC
99 NODE
100 Child (
101 IN NODE q,
102 IN UINT8 c
103 );
104
105 STATIC
106 VOID
107 MakeChild (
108 IN NODE q,
109 IN UINT8 c,
110 IN NODE r
111 );
112
113 STATIC
114 VOID
115 Split (
116 IN NODE Old
117 );
118
119 STATIC
120 VOID
121 InsertNode (
122 );
123
124 STATIC
125 VOID
126 DeleteNode (
127 );
128
129 STATIC
130 VOID
131 GetNextMatch (
132 );
133
134 STATIC
135 EFI_STATUS
136 Encode (
137 );
138
139 STATIC
140 VOID
141 CountTFreq (
142 );
143
144 STATIC
145 VOID
146 WritePTLen (
147 IN INT32 n,
148 IN INT32 nbit,
149 IN INT32 Special
150 );
151
152 STATIC
153 VOID
154 WriteCLen (
155 );
156
157 STATIC
158 VOID
159 EncodeC (
160 IN INT32 c
161 );
162
163 STATIC
164 VOID
165 EncodeP (
166 IN UINT32 p
167 );
168
169 STATIC
170 VOID
171 SendBlock (
172 );
173
174 STATIC
175 VOID
176 Output (
177 IN UINT32 c,
178 IN UINT32 p
179 );
180
181 STATIC
182 VOID
183 HufEncodeStart (
184 );
185
186 STATIC
187 VOID
188 HufEncodeEnd (
189 );
190
191 STATIC
192 VOID
193 MakeCrcTable (
194 );
195
196 STATIC
197 VOID
198 PutBits (
199 IN INT32 n,
200 IN UINT32 x
201 );
202
203 STATIC
204 INT32
205 FreadCrc (
206 OUT UINT8 *p,
207 IN INT32 n
208 );
209
210 STATIC
211 VOID
212 InitPutBits (
213 );
214
215 STATIC
216 VOID
217 CountLen (
218 IN INT32 i
219 );
220
221 STATIC
222 VOID
223 MakeLen (
224 IN INT32 Root
225 );
226
227 STATIC
228 VOID
229 DownHeap (
230 IN INT32 i
231 );
232
233 STATIC
234 VOID
235 MakeCode (
236 IN INT32 n,
237 IN UINT8 Len[],
238 OUT UINT16 Code[]
239 );
240
241 STATIC
242 INT32
243 MakeTree (
244 IN INT32 NParm,
245 IN UINT16 FreqParm[],
246 OUT UINT8 LenParm[],
247 OUT UINT16 CodeParm[]
248 );
249
250
251 //
252 // Global Variables
253 //
254
255 STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
256
257 STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLe n;
258 STATIC INT16 mHeap[NC + 1];
259 STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
260 STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
261 STATIC UINT32 mCompSize, mOrigSize;
262
263 STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1],
264 mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1], mCCode[NC],
265 mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
266
267 STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NU LL;
268
269
270 //
271 // functions
272 //
273
274 EFI_STATUS
275 EfiCompress (
276 IN UINT8 *SrcBuffer,
277 IN UINT32 SrcSize,
278 IN UINT8 *DstBuffer,
279 IN OUT UINT32 *DstSize
280 )
281 /*++
282
283 Routine Description:
284
285 The main compression routine.
286
287 Arguments:
288
289 SrcBuffer - The buffer storing the source data
290 SrcSize - The size of source data
291 DstBuffer - The buffer to store the compressed data
292 DstSize - On input, the size of DstBuffer; On output,
293 the size of the actual compressed data.
294
295 Returns:
296
297 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
298 DstSize contains the size needed.
299 EFI_SUCCESS - Compression is successful.
300
301 --*/
302 {
303 EFI_STATUS Status = EFI_SUCCESS;
304
305 //
306 // Initializations
307 //
308 mBufSiz = 0;
309 mBuf = NULL;
310 mText = NULL;
311 mLevel = NULL;
312 mChildCount = NULL;
313 mPosition = NULL;
314 mParent = NULL;
315 mPrev = NULL;
316 mNext = NULL;
317
318
319 mSrc = SrcBuffer;
320 mSrcUpperLimit = mSrc + SrcSize;
321 mDst = DstBuffer;
322 mDstUpperLimit = mDst + *DstSize;
323
324 PutDword(0L);
325 PutDword(0L);
326
327 MakeCrcTable ();
328
329 mOrigSize = mCompSize = 0;
330 mCrc = INIT_CRC;
331
332 //
333 // Compress it
334 //
335
336 Status = Encode();
337 if (EFI_ERROR (Status)) {
338 return EFI_OUT_OF_RESOURCES;
339 }
340
341 //
342 // Null terminate the compressed data
343 //
344 if (mDst < mDstUpperLimit) {
345 *mDst++ = 0;
346 }
347
348 //
349 // Fill in compressed size and original size
350 //
351 mDst = DstBuffer;
352 PutDword(mCompSize+1);
353 PutDword(mOrigSize);
354
355 //
356 // Return
357 //
358
359 if (mCompSize + 1 + 8 > *DstSize) {
360 *DstSize = mCompSize + 1 + 8;
361 return EFI_BUFFER_TOO_SMALL;
362 } else {
363 *DstSize = mCompSize + 1 + 8;
364 return EFI_SUCCESS;
365 }
366
367 }
368
369 STATIC
370 VOID
371 PutDword(
372 IN UINT32 Data
373 )
374 /*++
375
376 Routine Description:
377
378 Put a dword to output stream
379
380 Arguments:
381
382 Data - the dword to put
383
384 Returns: (VOID)
385
386 --*/
387 {
388 if (mDst < mDstUpperLimit) {
389 *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff);
390 }
391
392 if (mDst < mDstUpperLimit) {
393 *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff);
394 }
395
396 if (mDst < mDstUpperLimit) {
397 *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff);
398 }
399
400 if (mDst < mDstUpperLimit) {
401 *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff);
402 }
403 }
404
405 STATIC
406 EFI_STATUS
407 AllocateMemory ()
408 /*++
409
410 Routine Description:
411
412 Allocate memory spaces for data structures used in compression process
413
414 Argements: (VOID)
415
416 Returns:
417
418 EFI_SUCCESS - Memory is allocated successfully
419 EFI_OUT_OF_RESOURCES - Allocation fails
420
421 --*/
422 {
423 UINT32 i;
424
425 mText = malloc (WNDSIZ * 2 + MAXMATCH);
426 for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {
427 mText[i] = 0;
428 }
429
430 mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel));
431 mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount));
432 mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition));
433 mParent = malloc (WNDSIZ * 2 * sizeof(*mParent));
434 mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev));
435 mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext));
436
437 mBufSiz = 16 * 1024U;
438 while ((mBuf = malloc(mBufSiz)) == NULL) {
439 mBufSiz = (mBufSiz / 10U) * 9U;
440 if (mBufSiz < 4 * 1024U) {
441 return EFI_OUT_OF_RESOURCES;
442 }
443 }
444 mBuf[0] = 0;
445
446 return EFI_SUCCESS;
447 }
448
449 VOID
450 FreeMemory ()
451 /*++
452
453 Routine Description:
454
455 Called when compression is completed to free memory previously allocated.
456
457 Arguments: (VOID)
458
459 Returns: (VOID)
460
461 --*/
462 {
463 if (mText) {
464 free (mText);
465 }
466
467 if (mLevel) {
468 free (mLevel);
469 }
470
471 if (mChildCount) {
472 free (mChildCount);
473 }
474
475 if (mPosition) {
476 free (mPosition);
477 }
478
479 if (mParent) {
480 free (mParent);
481 }
482
483 if (mPrev) {
484 free (mPrev);
485 }
486
487 if (mNext) {
488 free (mNext);
489 }
490
491 if (mBuf) {
492 free (mBuf);
493 }
494
495 return;
496 }
497
498
499 STATIC
500 VOID
501 InitSlide ()
502 /*++
503
504 Routine Description:
505
506 Initialize String Info Log data structures
507
508 Arguments: (VOID)
509
510 Returns: (VOID)
511
512 --*/
513 {
514 NODE i;
515
516 for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) {
517 mLevel[i] = 1;
518 mPosition[i] = NIL; /* sentinel */
519 }
520 for (i = WNDSIZ; i < WNDSIZ * 2; i++) {
521 mParent[i] = NIL;
522 }
523 mAvail = 1;
524 for (i = 1; i < WNDSIZ - 1; i++) {
525 mNext[i] = (NODE)(i + 1);
526 }
527
528 mNext[WNDSIZ - 1] = NIL;
529 for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) {
530 mNext[i] = NIL;
531 }
532 }
533
534
535 STATIC
536 NODE
537 Child (
538 IN NODE q,
539 IN UINT8 c
540 )
541 /*++
542
543 Routine Description:
544
545 Find child node given the parent node and the edge character
546
547 Arguments:
548
549 q - the parent node
550 c - the edge character
551
552 Returns:
553
554 The child node (NIL if not found)
555
556 --*/
557 {
558 NODE r;
559
560 r = mNext[HASH(q, c)];
561 mParent[NIL] = q; /* sentinel */
562 while (mParent[r] != q) {
563 r = mNext[r];
564 }
565
566 return r;
567 }
568
569 STATIC
570 VOID
571 MakeChild (
572 IN NODE q,
573 IN UINT8 c,
574 IN NODE r
575 )
576 /*++
577
578 Routine Description:
579
580 Create a new child for a given parent node.
581
582 Arguments:
583
584 q - the parent node
585 c - the edge character
586 r - the child node
587
588 Returns: (VOID)
589
590 --*/
591 {
592 NODE h, t;
593
594 h = (NODE)HASH(q, c);
595 t = mNext[h];
596 mNext[h] = r;
597 mNext[r] = t;
598 mPrev[t] = r;
599 mPrev[r] = h;
600 mParent[r] = q;
601 mChildCount[q]++;
602 }
603
604 STATIC
605 VOID
606 Split (
607 NODE Old
608 )
609 /*++
610
611 Routine Description:
612
613 Split a node.
614
615 Arguments:
616
617 Old - the node to split
618
619 Returns: (VOID)
620
621 --*/
622 {
623 NODE New, t;
624
625 New = mAvail;
626 mAvail = mNext[New];
627 mChildCount[New] = 0;
628 t = mPrev[Old];
629 mPrev[New] = t;
630 mNext[t] = New;
631 t = mNext[Old];
632 mNext[New] = t;
633 mPrev[t] = New;
634 mParent[New] = mParent[Old];
635 mLevel[New] = (UINT8)mMatchLen;
636 mPosition[New] = mPos;
637 MakeChild(New, mText[mMatchPos + mMatchLen], Old);
638 MakeChild(New, mText[mPos + mMatchLen], mPos);
639 }
640
641 STATIC
642 VOID
643 InsertNode ()
644 /*++
645
646 Routine Description:
647
648 Insert string info for current position into the String Info Log
649
650 Arguments: (VOID)
651
652 Returns: (VOID)
653
654 --*/
655 {
656 NODE q, r, j, t;
657 UINT8 c, *t1, *t2;
658
659 if (mMatchLen >= 4) {
660
661 //
662 // We have just got a long match, the target tree
663 // can be located by MatchPos + 1. Travese the tree
664 // from bottom up to get to a proper starting point.
665 // The usage of PERC_FLAG ensures proper node deletion
666 // in DeleteNode() later.
667 //
668
669 mMatchLen--;
670 r = (INT16)((mMatchPos + 1) | WNDSIZ);
671 while ((q = mParent[r]) == NIL) {
672 r = mNext[r];
673 }
674 while (mLevel[q] >= mMatchLen) {
675 r = q; q = mParent[q];
676 }
677 t = q;
678 while (mPosition[t] < 0) {
679 mPosition[t] = mPos;
680 t = mParent[t];
681 }
682 if (t < WNDSIZ) {
683 mPosition[t] = (NODE)(mPos | PERC_FLAG);
684 }
685 } else {
686
687 //
688 // Locate the target tree
689 //
690
691 q = (INT16)(mText[mPos] + WNDSIZ);
692 c = mText[mPos + 1];
693 if ((r = Child(q, c)) == NIL) {
694 MakeChild(q, c, mPos);
695 mMatchLen = 1;
696 return;
697 }
698 mMatchLen = 2;
699 }
700
701 //
702 // Traverse down the tree to find a match.
703 // Update Position value along the route.
704 // Node split or creation is involved.
705 //
706
707 for ( ; ; ) {
708 if (r >= WNDSIZ) {
709 j = MAXMATCH;
710 mMatchPos = r;
711 } else {
712 j = mLevel[r];
713 mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG);
714 }
715 if (mMatchPos >= mPos) {
716 mMatchPos -= WNDSIZ;
717 }
718 t1 = &mText[mPos + mMatchLen];
719 t2 = &mText[mMatchPos + mMatchLen];
720 while (mMatchLen < j) {
721 if (*t1 != *t2) {
722 Split(r);
723 return;
724 }
725 mMatchLen++;
726 t1++;
727 t2++;
728 }
729 if (mMatchLen >= MAXMATCH) {
730 break;
731 }
732 mPosition[r] = mPos;
733 q = r;
734 if ((r = Child(q, *t1)) == NIL) {
735 MakeChild(q, *t1, mPos);
736 return;
737 }
738 mMatchLen++;
739 }
740 t = mPrev[r];
741 mPrev[mPos] = t;
742 mNext[t] = mPos;
743 t = mNext[r];
744 mNext[mPos] = t;
745 mPrev[t] = mPos;
746 mParent[mPos] = q;
747 mParent[r] = NIL;
748
749 //
750 // Special usage of 'next'
751 //
752 mNext[r] = mPos;
753
754 }
755
756 STATIC
757 VOID
758 DeleteNode ()
759 /*++
760
761 Routine Description:
762
763 Delete outdated string info. (The Usage of PERC_FLAG
764 ensures a clean deletion)
765
766 Arguments: (VOID)
767
768 Returns: (VOID)
769
770 --*/
771 {
772 NODE q, r, s, t, u;
773
774 if (mParent[mPos] == NIL) {
775 return;
776 }
777
778 r = mPrev[mPos];
779 s = mNext[mPos];
780 mNext[r] = s;
781 mPrev[s] = r;
782 r = mParent[mPos];
783 mParent[mPos] = NIL;
784 if (r >= WNDSIZ || --mChildCount[r] > 1) {
785 return;
786 }
787 t = (NODE)(mPosition[r] & ~PERC_FLAG);
788 if (t >= mPos) {
789 t -= WNDSIZ;
790 }
791 s = t;
792 q = mParent[r];
793 while ((u = mPosition[q]) & PERC_FLAG) {
794 u &= ~PERC_FLAG;
795 if (u >= mPos) {
796 u -= WNDSIZ;
797 }
798 if (u > s) {
799 s = u;
800 }
801 mPosition[q] = (INT16)(s | WNDSIZ);
802 q = mParent[q];
803 }
804 if (q < WNDSIZ) {
805 if (u >= mPos) {
806 u -= WNDSIZ;
807 }
808 if (u > s) {
809 s = u;
810 }
811 mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG);
812 }
813 s = Child(r, mText[t + mLevel[r]]);
814 t = mPrev[s];
815 u = mNext[s];
816 mNext[t] = u;
817 mPrev[u] = t;
818 t = mPrev[r];
819 mNext[t] = s;
820 mPrev[s] = t;
821 t = mNext[r];
822 mPrev[t] = s;
823 mNext[s] = t;
824 mParent[s] = mParent[r];
825 mParent[r] = NIL;
826 mNext[r] = mAvail;
827 mAvail = r;
828 }
829
830 STATIC
831 VOID
832 GetNextMatch ()
833 /*++
834
835 Routine Description:
836
837 Advance the current position (read in new data if needed).
838 Delete outdated string info. Find a match string for current position.
839
840 Arguments: (VOID)
841
842 Returns: (VOID)
843
844 --*/
845 {
846 INT32 n;
847
848 mRemainder--;
849 if (++mPos == WNDSIZ * 2) {
850 memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
851 n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ);
852 mRemainder += n;
853 mPos = WNDSIZ;
854 }
855 DeleteNode();
856 InsertNode();
857 }
858
859 STATIC
860 EFI_STATUS
861 Encode ()
862 /*++
863
864 Routine Description:
865
866 The main controlling routine for compression process.
867
868 Arguments: (VOID)
869
870 Returns:
871
872 EFI_SUCCESS - The compression is successful
873 EFI_OUT_0F_RESOURCES - Not enough memory for compression process
874
875 --*/
876 {
877 EFI_STATUS Status;
878 INT32 LastMatchLen;
879 NODE LastMatchPos;
880
881 Status = AllocateMemory();
882 if (EFI_ERROR(Status)) {
883 FreeMemory();
884 return Status;
885 }
886
887 InitSlide();
888
889 HufEncodeStart();
890
891 mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH);
892
893 mMatchLen = 0;
894 mPos = WNDSIZ;
895 InsertNode();
896 if (mMatchLen > mRemainder) {
897 mMatchLen = mRemainder;
898 }
899 while (mRemainder > 0) {
900 LastMatchLen = mMatchLen;
901 LastMatchPos = mMatchPos;
902 GetNextMatch();
903 if (mMatchLen > mRemainder) {
904 mMatchLen = mRemainder;
905 }
906
907 if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
908
909 //
910 // Not enough benefits are gained by outputting a pointer,
911 // so just output the original character
912 //
913
914 Output(mText[mPos - 1], 0);
915 } else {
916
917 //
918 // Outputting a pointer is beneficial enough, do it.
919 //
920
921 Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
922 (mPos - LastMatchPos - 2) & (WNDSIZ - 1));
923 while (--LastMatchLen > 0) {
924 GetNextMatch();
925 }
926 if (mMatchLen > mRemainder) {
927 mMatchLen = mRemainder;
928 }
929 }
930 }
931
932 HufEncodeEnd();
933 FreeMemory();
934 return EFI_SUCCESS;
935 }
936
937 STATIC
938 VOID
939 CountTFreq ()
940 /*++
941
942 Routine Description:
943
944 Count the frequencies for the Extra Set
945
946 Arguments: (VOID)
947
948 Returns: (VOID)
949
950 --*/
951 {
952 INT32 i, k, n, Count;
953
954 for (i = 0; i < NT; i++) {
955 mTFreq[i] = 0;
956 }
957 n = NC;
958 while (n > 0 && mCLen[n - 1] == 0) {
959 n--;
960 }
961 i = 0;
962 while (i < n) {
963 k = mCLen[i++];
964 if (k == 0) {
965 Count = 1;
966 while (i < n && mCLen[i] == 0) {
967 i++;
968 Count++;
969 }
970 if (Count <= 2) {
971 mTFreq[0] = (UINT16)(mTFreq[0] + Count);
972 } else if (Count <= 18) {
973 mTFreq[1]++;
974 } else if (Count == 19) {
975 mTFreq[0]++;
976 mTFreq[1]++;
977 } else {
978 mTFreq[2]++;
979 }
980 } else {
981 mTFreq[k + 2]++;
982 }
983 }
984 }
985
986 STATIC
987 VOID
988 WritePTLen (
989 IN INT32 n,
990 IN INT32 nbit,
991 IN INT32 Special
992 )
993 /*++
994
995 Routine Description:
996
997 Outputs the code length array for the Extra Set or the Position Set.
998
999 Arguments:
1000
1001 n - the number of symbols
1002 nbit - the number of bits needed to represent 'n'
1003 Special - the special symbol that needs to be take care of
1004
1005 Returns: (VOID)
1006
1007 --*/
1008 {
1009 INT32 i, k;
1010
1011 while (n > 0 && mPTLen[n - 1] == 0) {
1012 n--;
1013 }
1014 PutBits(nbit, n);
1015 i = 0;
1016 while (i < n) {
1017 k = mPTLen[i++];
1018 if (k <= 6) {
1019 PutBits(3, k);
1020 } else {
1021 PutBits(k - 3, (1U << (k - 3)) - 2);
1022 }
1023 if (i == Special) {
1024 while (i < 6 && mPTLen[i] == 0) {
1025 i++;
1026 }
1027 PutBits(2, (i - 3) & 3);
1028 }
1029 }
1030 }
1031
1032 STATIC
1033 VOID
1034 WriteCLen ()
1035 /*++
1036
1037 Routine Description:
1038
1039 Outputs the code length array for Char&Length Set
1040
1041 Arguments: (VOID)
1042
1043 Returns: (VOID)
1044
1045 --*/
1046 {
1047 INT32 i, k, n, Count;
1048
1049 n = NC;
1050 while (n > 0 && mCLen[n - 1] == 0) {
1051 n--;
1052 }
1053 PutBits(CBIT, n);
1054 i = 0;
1055 while (i < n) {
1056 k = mCLen[i++];
1057 if (k == 0) {
1058 Count = 1;
1059 while (i < n && mCLen[i] == 0) {
1060 i++;
1061 Count++;
1062 }
1063 if (Count <= 2) {
1064 for (k = 0; k < Count; k++) {
1065 PutBits(mPTLen[0], mPTCode[0]);
1066 }
1067 } else if (Count <= 18) {
1068 PutBits(mPTLen[1], mPTCode[1]);
1069 PutBits(4, Count - 3);
1070 } else if (Count == 19) {
1071 PutBits(mPTLen[0], mPTCode[0]);
1072 PutBits(mPTLen[1], mPTCode[1]);
1073 PutBits(4, 15);
1074 } else {
1075 PutBits(mPTLen[2], mPTCode[2]);
1076 PutBits(CBIT, Count - 20);
1077 }
1078 } else {
1079 PutBits(mPTLen[k + 2], mPTCode[k + 2]);
1080 }
1081 }
1082 }
1083
1084 STATIC
1085 VOID
1086 EncodeC (
1087 IN INT32 c
1088 )
1089 {
1090 PutBits(mCLen[c], mCCode[c]);
1091 }
1092
1093 STATIC
1094 VOID
1095 EncodeP (
1096 IN UINT32 p
1097 )
1098 {
1099 UINT32 c, q;
1100
1101 c = 0;
1102 q = p;
1103 while (q) {
1104 q >>= 1;
1105 c++;
1106 }
1107 PutBits(mPTLen[c], mPTCode[c]);
1108 if (c > 1) {
1109 PutBits(c - 1, p & (0xFFFFU >> (17 - c)));
1110 }
1111 }
1112
1113 STATIC
1114 VOID
1115 SendBlock ()
1116 /*++
1117
1118 Routine Description:
1119
1120 Huffman code the block and output it.
1121
1122 Argument: (VOID)
1123
1124 Returns: (VOID)
1125
1126 --*/
1127 {
1128 UINT32 i, k, Flags, Root, Pos, Size;
1129 Flags = 0;
1130
1131 Root = MakeTree(NC, mCFreq, mCLen, mCCode);
1132 Size = mCFreq[Root];
1133 PutBits(16, Size);
1134 if (Root >= NC) {
1135 CountTFreq();
1136 Root = MakeTree(NT, mTFreq, mPTLen, mPTCode);
1137 if (Root >= NT) {
1138 WritePTLen(NT, TBIT, 3);
1139 } else {
1140 PutBits(TBIT, 0);
1141 PutBits(TBIT, Root);
1142 }
1143 WriteCLen();
1144 } else {
1145 PutBits(TBIT, 0);
1146 PutBits(TBIT, 0);
1147 PutBits(CBIT, 0);
1148 PutBits(CBIT, Root);
1149 }
1150 Root = MakeTree(NP, mPFreq, mPTLen, mPTCode);
1151 if (Root >= NP) {
1152 WritePTLen(NP, PBIT, -1);
1153 } else {
1154 PutBits(PBIT, 0);
1155 PutBits(PBIT, Root);
1156 }
1157 Pos = 0;
1158 for (i = 0; i < Size; i++) {
1159 if (i % UINT8_BIT == 0) {
1160 Flags = mBuf[Pos++];
1161 } else {
1162 Flags <<= 1;
1163 }
1164 if (Flags & (1U << (UINT8_BIT - 1))) {
1165 EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));
1166 k = mBuf[Pos++] << UINT8_BIT;
1167 k += mBuf[Pos++];
1168 EncodeP(k);
1169 } else {
1170 EncodeC(mBuf[Pos++]);
1171 }
1172 }
1173 for (i = 0; i < NC; i++) {
1174 mCFreq[i] = 0;
1175 }
1176 for (i = 0; i < NP; i++) {
1177 mPFreq[i] = 0;
1178 }
1179 }
1180
1181
1182 STATIC
1183 VOID
1184 Output (
1185 IN UINT32 c,
1186 IN UINT32 p
1187 )
1188 /*++
1189
1190 Routine Description:
1191
1192 Outputs an Original Character or a Pointer
1193
1194 Arguments:
1195
1196 c - The original character or the 'String Length' element of a Pointer
1197 p - The 'Position' field of a Pointer
1198
1199 Returns: (VOID)
1200
1201 --*/
1202 {
1203 STATIC UINT32 CPos;
1204
1205 if ((mOutputMask >>= 1) == 0) {
1206 mOutputMask = 1U << (UINT8_BIT - 1);
1207 if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {
1208 SendBlock();
1209 mOutputPos = 0;
1210 }
1211 CPos = mOutputPos++;
1212 mBuf[CPos] = 0;
1213 }
1214 mBuf[mOutputPos++] = (UINT8) c;
1215 mCFreq[c]++;
1216 if (c >= (1U << UINT8_BIT)) {
1217 mBuf[CPos] |= mOutputMask;
1218 mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT);
1219 mBuf[mOutputPos++] = (UINT8) p;
1220 c = 0;
1221 while (p) {
1222 p >>= 1;
1223 c++;
1224 }
1225 mPFreq[c]++;
1226 }
1227 }
1228
1229 STATIC
1230 VOID
1231 HufEncodeStart ()
1232 {
1233 INT32 i;
1234
1235 for (i = 0; i < NC; i++) {
1236 mCFreq[i] = 0;
1237 }
1238 for (i = 0; i < NP; i++) {
1239 mPFreq[i] = 0;
1240 }
1241 mOutputPos = mOutputMask = 0;
1242 InitPutBits();
1243 return;
1244 }
1245
1246 STATIC
1247 VOID
1248 HufEncodeEnd ()
1249 {
1250 SendBlock();
1251
1252 //
1253 // Flush remaining bits
1254 //
1255 PutBits(UINT8_BIT - 1, 0);
1256
1257 return;
1258 }
1259
1260
1261 STATIC
1262 VOID
1263 MakeCrcTable ()
1264 {
1265 UINT32 i, j, r;
1266
1267 for (i = 0; i <= UINT8_MAX; i++) {
1268 r = i;
1269 for (j = 0; j < UINT8_BIT; j++) {
1270 if (r & 1) {
1271 r = (r >> 1) ^ CRCPOLY;
1272 } else {
1273 r >>= 1;
1274 }
1275 }
1276 mCrcTable[i] = (UINT16)r;
1277 }
1278 }
1279
1280 STATIC
1281 VOID
1282 PutBits (
1283 IN INT32 n,
1284 IN UINT32 x
1285 )
1286 /*++
1287
1288 Routine Description:
1289
1290 Outputs rightmost n bits of x
1291
1292 Argments:
1293
1294 n - the rightmost n bits of the data is used
1295 x - the data
1296
1297 Returns: (VOID)
1298
1299 --*/
1300 {
1301 UINT8 Temp;
1302
1303 if (n < mBitCount) {
1304 mSubBitBuf |= x << (mBitCount -= n);
1305 } else {
1306
1307 Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount)));
1308 if (mDst < mDstUpperLimit) {
1309 *mDst++ = Temp;
1310 }
1311 mCompSize++;
1312
1313 if (n < UINT8_BIT) {
1314 mSubBitBuf = x << (mBitCount = UINT8_BIT - n);
1315 } else {
1316
1317 Temp = (UINT8)(x >> (n - UINT8_BIT));
1318 if (mDst < mDstUpperLimit) {
1319 *mDst++ = Temp;
1320 }
1321 mCompSize++;
1322
1323 mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n);
1324 }
1325 }
1326 }
1327
1328 STATIC
1329 INT32
1330 FreadCrc (
1331 OUT UINT8 *p,
1332 IN INT32 n
1333 )
1334 /*++
1335
1336 Routine Description:
1337
1338 Read in source data
1339
1340 Arguments:
1341
1342 p - the buffer to hold the data
1343 n - number of bytes to read
1344
1345 Returns:
1346
1347 number of bytes actually read
1348
1349 --*/
1350 {
1351 INT32 i;
1352
1353 for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) {
1354 *p++ = *mSrc++;
1355 }
1356 n = i;
1357
1358 p -= n;
1359 mOrigSize += n;
1360 while (--i >= 0) {
1361 UPDATE_CRC(*p++);
1362 }
1363 return n;
1364 }
1365
1366
1367 STATIC
1368 VOID
1369 InitPutBits ()
1370 {
1371 mBitCount = UINT8_BIT;
1372 mSubBitBuf = 0;
1373 }
1374
1375 STATIC
1376 VOID
1377 CountLen (
1378 IN INT32 i
1379 )
1380 /*++
1381
1382 Routine Description:
1383
1384 Count the number of each code length for a Huffman tree.
1385
1386 Arguments:
1387
1388 i - the top node
1389
1390 Returns: (VOID)
1391
1392 --*/
1393 {
1394 STATIC INT32 Depth = 0;
1395
1396 if (i < mN) {
1397 mLenCnt[(Depth < 16) ? Depth : 16]++;
1398 } else {
1399 Depth++;
1400 CountLen(mLeft [i]);
1401 CountLen(mRight[i]);
1402 Depth--;
1403 }
1404 }
1405
1406 STATIC
1407 VOID
1408 MakeLen (
1409 IN INT32 Root
1410 )
1411 /*++
1412
1413 Routine Description:
1414
1415 Create code length array for a Huffman tree
1416
1417 Arguments:
1418
1419 Root - the root of the tree
1420
1421 --*/
1422 {
1423 INT32 i, k;
1424 UINT32 Cum;
1425
1426 for (i = 0; i <= 16; i++) {
1427 mLenCnt[i] = 0;
1428 }
1429 CountLen(Root);
1430
1431 //
1432 // Adjust the length count array so that
1433 // no code will be generated longer than its designated length
1434 //
1435
1436 Cum = 0;
1437 for (i = 16; i > 0; i--) {
1438 Cum += mLenCnt[i] << (16 - i);
1439 }
1440 while (Cum != (1U << 16)) {
1441 mLenCnt[16]--;
1442 for (i = 15; i > 0; i--) {
1443 if (mLenCnt[i] != 0) {
1444 mLenCnt[i]--;
1445 mLenCnt[i+1] += 2;
1446 break;
1447 }
1448 }
1449 Cum--;
1450 }
1451 for (i = 16; i > 0; i--) {
1452 k = mLenCnt[i];
1453 while (--k >= 0) {
1454 mLen[*mSortPtr++] = (UINT8)i;
1455 }
1456 }
1457 }
1458
1459 STATIC
1460 VOID
1461 DownHeap (
1462 IN INT32 i
1463 )
1464 {
1465 INT32 j, k;
1466
1467 //
1468 // priority queue: send i-th entry down heap
1469 //
1470
1471 k = mHeap[i];
1472 while ((j = 2 * i) <= mHeapSize) {
1473 if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) {
1474 j++;
1475 }
1476 if (mFreq[k] <= mFreq[mHeap[j]]) {
1477 break;
1478 }
1479 mHeap[i] = mHeap[j];
1480 i = j;
1481 }
1482 mHeap[i] = (INT16)k;
1483 }
1484
1485 STATIC
1486 VOID
1487 MakeCode (
1488 IN INT32 n,
1489 IN UINT8 Len[],
1490 OUT UINT16 Code[]
1491 )
1492 /*++
1493
1494 Routine Description:
1495
1496 Assign code to each symbol based on the code length array
1497
1498 Arguments:
1499
1500 n - number of symbols
1501 Len - the code length array
1502 Code - stores codes for each symbol
1503
1504 Returns: (VOID)
1505
1506 --*/
1507 {
1508 INT32 i;
1509 UINT16 Start[18];
1510
1511 Start[1] = 0;
1512 for (i = 1; i <= 16; i++) {
1513 Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1);
1514 }
1515 for (i = 0; i < n; i++) {
1516 Code[i] = Start[Len[i]]++;
1517 }
1518 }
1519
1520 STATIC
1521 INT32
1522 MakeTree (
1523 IN INT32 NParm,
1524 IN UINT16 FreqParm[],
1525 OUT UINT8 LenParm[],
1526 OUT UINT16 CodeParm[]
1527 )
1528 /*++
1529
1530 Routine Description:
1531
1532 Generates Huffman codes given a frequency distribution of symbols
1533
1534 Arguments:
1535
1536 NParm - number of symbols
1537 FreqParm - frequency of each symbol
1538 LenParm - code length for each symbol
1539 CodeParm - code for each symbol
1540
1541 Returns:
1542
1543 Root of the Huffman tree.
1544
1545 --*/
1546 {
1547 INT32 i, j, k, Avail;
1548
1549 //
1550 // make tree, calculate len[], return root
1551 //
1552
1553 mN = NParm;
1554 mFreq = FreqParm;
1555 mLen = LenParm;
1556 Avail = mN;
1557 mHeapSize = 0;
1558 mHeap[1] = 0;
1559 for (i = 0; i < mN; i++) {
1560 mLen[i] = 0;
1561 if (mFreq[i]) {
1562 mHeap[++mHeapSize] = (INT16)i;
1563 }
1564 }
1565 if (mHeapSize < 2) {
1566 CodeParm[mHeap[1]] = 0;
1567 return mHeap[1];
1568 }
1569 for (i = mHeapSize / 2; i >= 1; i--) {
1570
1571 //
1572 // make priority queue
1573 //
1574 DownHeap(i);
1575 }
1576 mSortPtr = CodeParm;
1577 do {
1578 i = mHeap[1];
1579 if (i < mN) {
1580 *mSortPtr++ = (UINT16)i;
1581 }
1582 mHeap[1] = mHeap[mHeapSize--];
1583 DownHeap(1);
1584 j = mHeap[1];
1585 if (j < mN) {
1586 *mSortPtr++ = (UINT16)j;
1587 }
1588 k = Avail++;
1589 mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]);
1590 mHeap[1] = (INT16)k;
1591 DownHeap(1);
1592 mLeft[k] = (UINT16)i;
1593 mRight[k] = (UINT16)j;
1594 } while (mHeapSize > 1);
1595
1596 mSortPtr = CodeParm;
1597 MakeLen(k);
1598 MakeCode(NParm, LenParm, CodeParm);
1599
1600 //
1601 // return root
1602 //
1603 return k;
1604 }
OLDNEW
« utility/bmpblk_util.c ('K') | « utility/bmpblk_utility.cc ('k') | utility/efidecompress.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698