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