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