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