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