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