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