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