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