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