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