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