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