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