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