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