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