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