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