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