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