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