REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the ShellPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			1392 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1392 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Main file for compression routine.
 | 
						|
 | 
						|
  Compression routine. The compression algorithm is a mixture of
 | 
						|
  LZ77 and Huffman coding. LZ77 transforms the source data into a
 | 
						|
  sequence of Original Characters and Pointers to repeated strings.
 | 
						|
  This sequence is further divided into Blocks and Huffman codings
 | 
						|
  are applied to each Block.
 | 
						|
 | 
						|
  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/ShellLib.h>
 | 
						|
 | 
						|
#include "Compress.h"
 | 
						|
 | 
						|
//
 | 
						|
// Macro Definitions
 | 
						|
//
 | 
						|
typedef INT16 NODE;
 | 
						|
#define UINT8_MAX     0xff
 | 
						|
#define UINT8_BIT     8
 | 
						|
#define THRESHOLD     3
 | 
						|
#define INIT_CRC      0
 | 
						|
#define WNDBIT        13
 | 
						|
#define WNDSIZ        (1U << WNDBIT)
 | 
						|
#define MAXMATCH      256
 | 
						|
#define BLKSIZ        (1U << 14)      // 16 * 1024U
 | 
						|
#define PERC_FLAG     0x8000U
 | 
						|
#define CODE_BIT      16
 | 
						|
#define NIL           0
 | 
						|
#define MAX_HASH_VAL  (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
 | 
						|
#define HASH(LoopVar7, LoopVar5)  ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2)
 | 
						|
#define CRCPOLY  0xA001
 | 
						|
#define UPDATE_CRC(LoopVar5)  mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 0xFF] ^ (mCrc >> UINT8_BIT)
 | 
						|
 | 
						|
//
 | 
						|
// C: the Char&Len Set; P: the Position Set; T: the exTra Set
 | 
						|
//
 | 
						|
#define NC    (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
 | 
						|
#define CBIT  9
 | 
						|
#define NP    (WNDBIT + 1)
 | 
						|
#define PBIT  4
 | 
						|
#define NT    (CODE_BIT + 3)
 | 
						|
#define TBIT  5
 | 
						|
#if NT > NP
 | 
						|
#define                 NPT  NT
 | 
						|
#else
 | 
						|
#define                 NPT  NP
 | 
						|
#endif
 | 
						|
//
 | 
						|
// Function Prototypes
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Put a dword to output stream
 | 
						|
 | 
						|
  @param[in] Data    The dword to put.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PutDword (
 | 
						|
  IN UINT32  Data
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
//  Global Variables
 | 
						|
//
 | 
						|
STATIC UINT8  *mSrc;
 | 
						|
STATIC UINT8  *mDst;
 | 
						|
STATIC UINT8  *mSrcUpperLimit;
 | 
						|
STATIC UINT8  *mDstUpperLimit;
 | 
						|
 | 
						|
STATIC UINT8   *mLevel;
 | 
						|
STATIC UINT8   *mText;
 | 
						|
STATIC UINT8   *mChildCount;
 | 
						|
STATIC UINT8   *mBuf;
 | 
						|
STATIC UINT8   mCLen[NC];
 | 
						|
STATIC UINT8   mPTLen[NPT];
 | 
						|
STATIC UINT8   *mLen;
 | 
						|
STATIC INT16   mHeap[NC + 1];
 | 
						|
STATIC INT32   mRemainder;
 | 
						|
STATIC INT32   mMatchLen;
 | 
						|
STATIC INT32   mBitCount;
 | 
						|
STATIC INT32   mHeapSize;
 | 
						|
STATIC INT32   mTempInt32;
 | 
						|
STATIC UINT32  mBufSiz = 0;
 | 
						|
STATIC UINT32  mOutputPos;
 | 
						|
STATIC UINT32  mOutputMask;
 | 
						|
STATIC UINT32  mSubBitBuf;
 | 
						|
STATIC UINT32  mCrc;
 | 
						|
STATIC UINT32  mCompSize;
 | 
						|
STATIC UINT32  mOrigSize;
 | 
						|
 | 
						|
STATIC UINT16  *mFreq;
 | 
						|
STATIC UINT16  *mSortPtr;
 | 
						|
STATIC UINT16  mLenCnt[17];
 | 
						|
STATIC UINT16  mLeft[2 * NC - 1];
 | 
						|
STATIC UINT16  mRight[2 * NC - 1];
 | 
						|
STATIC UINT16  mCrcTable[UINT8_MAX + 1];
 | 
						|
STATIC UINT16  mCFreq[2 * NC - 1];
 | 
						|
STATIC UINT16  mCCode[NC];
 | 
						|
STATIC UINT16  mPFreq[2 * NP - 1];
 | 
						|
STATIC UINT16  mPTCode[NPT];
 | 
						|
STATIC UINT16  mTFreq[2 * NT - 1];
 | 
						|
 | 
						|
STATIC NODE  mPos;
 | 
						|
STATIC NODE  mMatchPos;
 | 
						|
STATIC NODE  mAvail;
 | 
						|
STATIC NODE  *mPosition;
 | 
						|
STATIC NODE  *mParent;
 | 
						|
STATIC NODE  *mPrev;
 | 
						|
STATIC NODE  *mNext        = NULL;
 | 
						|
INT32        mHuffmanDepth = 0;
 | 
						|
 | 
						|
/**
 | 
						|
  Make a CRC table.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
MakeCrcTable (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  LoopVar1;
 | 
						|
 | 
						|
  UINT32  LoopVar2;
 | 
						|
 | 
						|
  UINT32  LoopVar4;
 | 
						|
 | 
						|
  for (LoopVar1 = 0; LoopVar1 <= UINT8_MAX; LoopVar1++) {
 | 
						|
    LoopVar4 = LoopVar1;
 | 
						|
    for (LoopVar2 = 0; LoopVar2 < UINT8_BIT; LoopVar2++) {
 | 
						|
      if ((LoopVar4 & 1) != 0) {
 | 
						|
        LoopVar4 = (LoopVar4 >> 1) ^ CRCPOLY;
 | 
						|
      } else {
 | 
						|
        LoopVar4 >>= 1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    mCrcTable[LoopVar1] = (UINT16)LoopVar4;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Put a dword to output stream
 | 
						|
 | 
						|
  @param[in] Data    The dword to put.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PutDword (
 | 
						|
  IN UINT32  Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (mDst < mDstUpperLimit) {
 | 
						|
    *mDst++ = (UINT8)(((UINT8)(Data)) & 0xff);
 | 
						|
  }
 | 
						|
 | 
						|
  if (mDst < mDstUpperLimit) {
 | 
						|
    *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff);
 | 
						|
  }
 | 
						|
 | 
						|
  if (mDst < mDstUpperLimit) {
 | 
						|
    *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff);
 | 
						|
  }
 | 
						|
 | 
						|
  if (mDst < mDstUpperLimit) {
 | 
						|
    *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocate memory spaces for data structures used in compression process.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Memory was allocated successfully.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
AllocateMemory (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mText       = AllocateZeroPool (WNDSIZ * 2 + MAXMATCH);
 | 
						|
  mLevel      = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
 | 
						|
  mChildCount = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
 | 
						|
  mPosition   = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
 | 
						|
  mParent     = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mParent));
 | 
						|
  mPrev       = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mPrev));
 | 
						|
  mNext       = AllocateZeroPool ((MAX_HASH_VAL + 1) * sizeof (*mNext));
 | 
						|
 | 
						|
  mBufSiz = BLKSIZ;
 | 
						|
  mBuf    = AllocateZeroPool (mBufSiz);
 | 
						|
  while (mBuf == NULL) {
 | 
						|
    mBufSiz = (mBufSiz / 10U) * 9U;
 | 
						|
    if (mBufSiz < 4 * 1024U) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    mBuf = AllocateZeroPool (mBufSiz);
 | 
						|
  }
 | 
						|
 | 
						|
  mBuf[0] = 0;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Called when compression is completed to free memory previously allocated.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FreeMemory (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SHELL_FREE_NON_NULL (mText);
 | 
						|
  SHELL_FREE_NON_NULL (mLevel);
 | 
						|
  SHELL_FREE_NON_NULL (mChildCount);
 | 
						|
  SHELL_FREE_NON_NULL (mPosition);
 | 
						|
  SHELL_FREE_NON_NULL (mParent);
 | 
						|
  SHELL_FREE_NON_NULL (mPrev);
 | 
						|
  SHELL_FREE_NON_NULL (mNext);
 | 
						|
  SHELL_FREE_NON_NULL (mBuf);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize String Info Log data structures.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InitSlide (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  NODE  LoopVar1;
 | 
						|
 | 
						|
  SetMem (mLevel + WNDSIZ, (UINT8_MAX + 1) * sizeof (UINT8), 1);
 | 
						|
  SetMem (mPosition + WNDSIZ, (UINT8_MAX + 1) * sizeof (NODE), 0);
 | 
						|
 | 
						|
  SetMem (mParent + WNDSIZ, WNDSIZ * sizeof (NODE), 0);
 | 
						|
 | 
						|
  mAvail = 1;
 | 
						|
  for (LoopVar1 = 1; LoopVar1 < WNDSIZ - 1; LoopVar1++) {
 | 
						|
    mNext[LoopVar1] = (NODE)(LoopVar1 + 1);
 | 
						|
  }
 | 
						|
 | 
						|
  mNext[WNDSIZ - 1] = NIL;
 | 
						|
  SetMem (mNext + WNDSIZ * 2, (MAX_HASH_VAL - WNDSIZ * 2 + 1) * sizeof (NODE), 0);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find child node given the parent node and the edge character
 | 
						|
 | 
						|
  @param[in] LoopVar6       The parent node.
 | 
						|
  @param[in] LoopVar5       The edge character.
 | 
						|
 | 
						|
  @return             The child node.
 | 
						|
  @retval NIL(Zero)   No child could be found.
 | 
						|
 | 
						|
**/
 | 
						|
NODE
 | 
						|
Child (
 | 
						|
  IN NODE   LoopVar6,
 | 
						|
  IN UINT8  LoopVar5
 | 
						|
  )
 | 
						|
{
 | 
						|
  NODE  LoopVar4;
 | 
						|
 | 
						|
  LoopVar4     = mNext[HASH (LoopVar6, LoopVar5)];
 | 
						|
  mParent[NIL] = LoopVar6;   /* sentinel */
 | 
						|
  while (mParent[LoopVar4] != LoopVar6) {
 | 
						|
    LoopVar4 = mNext[LoopVar4];
 | 
						|
  }
 | 
						|
 | 
						|
  return LoopVar4;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a new child for a given parent node.
 | 
						|
 | 
						|
  @param[in] LoopVar6       The parent node.
 | 
						|
  @param[in] LoopVar5       The edge character.
 | 
						|
  @param[in] LoopVar4       The child node.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
MakeChild (
 | 
						|
  IN NODE   LoopVar6,
 | 
						|
  IN UINT8  LoopVar5,
 | 
						|
  IN NODE   LoopVar4
 | 
						|
  )
 | 
						|
{
 | 
						|
  NODE  LoopVar12;
 | 
						|
 | 
						|
  NODE  LoopVar10;
 | 
						|
 | 
						|
  LoopVar12         = (NODE)HASH (LoopVar6, LoopVar5);
 | 
						|
  LoopVar10         = mNext[LoopVar12];
 | 
						|
  mNext[LoopVar12]  = LoopVar4;
 | 
						|
  mNext[LoopVar4]   = LoopVar10;
 | 
						|
  mPrev[LoopVar10]  = LoopVar4;
 | 
						|
  mPrev[LoopVar4]   = LoopVar12;
 | 
						|
  mParent[LoopVar4] = LoopVar6;
 | 
						|
  mChildCount[LoopVar6]++;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Split a node.
 | 
						|
 | 
						|
  @param[in] Old     The node to split.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Split (
 | 
						|
  IN NODE  Old
 | 
						|
  )
 | 
						|
{
 | 
						|
  NODE  New;
 | 
						|
 | 
						|
  NODE  LoopVar10;
 | 
						|
 | 
						|
  New              = mAvail;
 | 
						|
  mAvail           = mNext[New];
 | 
						|
  mChildCount[New] = 0;
 | 
						|
  LoopVar10        = mPrev[Old];
 | 
						|
  mPrev[New]       = LoopVar10;
 | 
						|
  mNext[LoopVar10] = New;
 | 
						|
  LoopVar10        = mNext[Old];
 | 
						|
  mNext[New]       = LoopVar10;
 | 
						|
  mPrev[LoopVar10] = New;
 | 
						|
  mParent[New]     = mParent[Old];
 | 
						|
  mLevel[New]      = (UINT8)mMatchLen;
 | 
						|
  mPosition[New]   = mPos;
 | 
						|
  MakeChild (New, mText[mMatchPos + mMatchLen], Old);
 | 
						|
  MakeChild (New, mText[mPos + mMatchLen], mPos);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert string info for current position into the String Info Log.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InsertNode (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  NODE  LoopVar6;
 | 
						|
 | 
						|
  NODE  LoopVar4;
 | 
						|
 | 
						|
  NODE  LoopVar2;
 | 
						|
 | 
						|
  NODE   LoopVar10;
 | 
						|
  UINT8  LoopVar5;
 | 
						|
  UINT8  *TempString3;
 | 
						|
  UINT8  *TempString2;
 | 
						|
 | 
						|
  if (mMatchLen >= 4) {
 | 
						|
    //
 | 
						|
    // We have just got a long match, the target tree
 | 
						|
    // can be located by MatchPos + 1. Travese the tree
 | 
						|
    // from bottom up to get to a proper starting point.
 | 
						|
    // The usage of PERC_FLAG ensures proper node deletion
 | 
						|
    // in DeleteNode() later.
 | 
						|
    //
 | 
						|
    mMatchLen--;
 | 
						|
    LoopVar4 = (NODE)((mMatchPos + 1) | WNDSIZ);
 | 
						|
    LoopVar6 = mParent[LoopVar4];
 | 
						|
    while (LoopVar6 == NIL) {
 | 
						|
      LoopVar4 = mNext[LoopVar4];
 | 
						|
      LoopVar6 = mParent[LoopVar4];
 | 
						|
    }
 | 
						|
 | 
						|
    while (mLevel[LoopVar6] >= mMatchLen) {
 | 
						|
      LoopVar4 = LoopVar6;
 | 
						|
      LoopVar6 = mParent[LoopVar6];
 | 
						|
    }
 | 
						|
 | 
						|
    LoopVar10 = LoopVar6;
 | 
						|
    while (mPosition[LoopVar10] < 0) {
 | 
						|
      mPosition[LoopVar10] = mPos;
 | 
						|
      LoopVar10            = mParent[LoopVar10];
 | 
						|
    }
 | 
						|
 | 
						|
    if (LoopVar10 < WNDSIZ) {
 | 
						|
      mPosition[LoopVar10] = (NODE)(mPos | PERC_FLAG);
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Locate the target tree
 | 
						|
    //
 | 
						|
    LoopVar6 = (NODE)(mText[mPos] + WNDSIZ);
 | 
						|
    LoopVar5 = mText[mPos + 1];
 | 
						|
    LoopVar4 = Child (LoopVar6, LoopVar5);
 | 
						|
    if (LoopVar4 == NIL) {
 | 
						|
      MakeChild (LoopVar6, LoopVar5, mPos);
 | 
						|
      mMatchLen = 1;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    mMatchLen = 2;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Traverse down the tree to find a match.
 | 
						|
  // Update Position value along the route.
 | 
						|
  // Node split or creation is involved.
 | 
						|
  //
 | 
						|
  for ( ; ;) {
 | 
						|
    if (LoopVar4 >= WNDSIZ) {
 | 
						|
      LoopVar2  = MAXMATCH;
 | 
						|
      mMatchPos = LoopVar4;
 | 
						|
    } else {
 | 
						|
      LoopVar2  = mLevel[LoopVar4];
 | 
						|
      mMatchPos = (NODE)(mPosition[LoopVar4] & ~PERC_FLAG);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mMatchPos >= mPos) {
 | 
						|
      mMatchPos -= WNDSIZ;
 | 
						|
    }
 | 
						|
 | 
						|
    TempString3 = &mText[mPos + mMatchLen];
 | 
						|
    TempString2 = &mText[mMatchPos + mMatchLen];
 | 
						|
    while (mMatchLen < LoopVar2) {
 | 
						|
      if (*TempString3 != *TempString2) {
 | 
						|
        Split (LoopVar4);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      mMatchLen++;
 | 
						|
      TempString3++;
 | 
						|
      TempString2++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mMatchLen >= MAXMATCH) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    mPosition[LoopVar4] = mPos;
 | 
						|
    LoopVar6            = LoopVar4;
 | 
						|
    LoopVar4            = Child (LoopVar6, *TempString3);
 | 
						|
    if (LoopVar4 == NIL) {
 | 
						|
      MakeChild (LoopVar6, *TempString3, mPos);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    mMatchLen++;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar10         = mPrev[LoopVar4];
 | 
						|
  mPrev[mPos]       = LoopVar10;
 | 
						|
  mNext[LoopVar10]  = mPos;
 | 
						|
  LoopVar10         = mNext[LoopVar4];
 | 
						|
  mNext[mPos]       = LoopVar10;
 | 
						|
  mPrev[LoopVar10]  = mPos;
 | 
						|
  mParent[mPos]     = LoopVar6;
 | 
						|
  mParent[LoopVar4] = NIL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Special usage of 'next'
 | 
						|
  //
 | 
						|
  mNext[LoopVar4] = mPos;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Delete outdated string info. (The Usage of PERC_FLAG
 | 
						|
  ensures a clean deletion).
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DeleteNode (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  NODE  LoopVar6;
 | 
						|
 | 
						|
  NODE  LoopVar4;
 | 
						|
 | 
						|
  NODE  LoopVar11;
 | 
						|
 | 
						|
  NODE  LoopVar10;
 | 
						|
 | 
						|
  NODE  LoopVar9;
 | 
						|
 | 
						|
  if (mParent[mPos] == NIL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar4         = mPrev[mPos];
 | 
						|
  LoopVar11        = mNext[mPos];
 | 
						|
  mNext[LoopVar4]  = LoopVar11;
 | 
						|
  mPrev[LoopVar11] = LoopVar4;
 | 
						|
  LoopVar4         = mParent[mPos];
 | 
						|
  mParent[mPos]    = NIL;
 | 
						|
  if (LoopVar4 >= WNDSIZ) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mChildCount[LoopVar4]--;
 | 
						|
  if (mChildCount[LoopVar4] > 1) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar10 = (NODE)(mPosition[LoopVar4] & ~PERC_FLAG);
 | 
						|
  if (LoopVar10 >= mPos) {
 | 
						|
    LoopVar10 -= WNDSIZ;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar11 = LoopVar10;
 | 
						|
  LoopVar6  = mParent[LoopVar4];
 | 
						|
  LoopVar9  = mPosition[LoopVar6];
 | 
						|
  while ((LoopVar9 & PERC_FLAG) != 0) {
 | 
						|
    LoopVar9 &= ~PERC_FLAG;
 | 
						|
    if (LoopVar9 >= mPos) {
 | 
						|
      LoopVar9 -= WNDSIZ;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LoopVar9 > LoopVar11) {
 | 
						|
      LoopVar11 = LoopVar9;
 | 
						|
    }
 | 
						|
 | 
						|
    mPosition[LoopVar6] = (NODE)(LoopVar11 | WNDSIZ);
 | 
						|
    LoopVar6            = mParent[LoopVar6];
 | 
						|
    LoopVar9            = mPosition[LoopVar6];
 | 
						|
  }
 | 
						|
 | 
						|
  if (LoopVar6 < WNDSIZ) {
 | 
						|
    if (LoopVar9 >= mPos) {
 | 
						|
      LoopVar9 -= WNDSIZ;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LoopVar9 > LoopVar11) {
 | 
						|
      LoopVar11 = LoopVar9;
 | 
						|
    }
 | 
						|
 | 
						|
    mPosition[LoopVar6] = (NODE)(LoopVar11 | WNDSIZ | PERC_FLAG);
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar11          = Child (LoopVar4, mText[LoopVar10 + mLevel[LoopVar4]]);
 | 
						|
  LoopVar10          = mPrev[LoopVar11];
 | 
						|
  LoopVar9           = mNext[LoopVar11];
 | 
						|
  mNext[LoopVar10]   = LoopVar9;
 | 
						|
  mPrev[LoopVar9]    = LoopVar10;
 | 
						|
  LoopVar10          = mPrev[LoopVar4];
 | 
						|
  mNext[LoopVar10]   = LoopVar11;
 | 
						|
  mPrev[LoopVar11]   = LoopVar10;
 | 
						|
  LoopVar10          = mNext[LoopVar4];
 | 
						|
  mPrev[LoopVar10]   = LoopVar11;
 | 
						|
  mNext[LoopVar11]   = LoopVar10;
 | 
						|
  mParent[LoopVar11] = mParent[LoopVar4];
 | 
						|
  mParent[LoopVar4]  = NIL;
 | 
						|
  mNext[LoopVar4]    = mAvail;
 | 
						|
  mAvail             = LoopVar4;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read in source data
 | 
						|
 | 
						|
  @param[out] LoopVar7   The buffer to hold the data.
 | 
						|
  @param[in] LoopVar8    The number of bytes to read.
 | 
						|
 | 
						|
  @return The number of bytes actually read.
 | 
						|
**/
 | 
						|
INT32
 | 
						|
FreadCrc (
 | 
						|
  OUT UINT8  *LoopVar7,
 | 
						|
  IN  INT32  LoopVar8
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  for (LoopVar1 = 0; mSrc < mSrcUpperLimit && LoopVar1 < LoopVar8; LoopVar1++) {
 | 
						|
    *LoopVar7++ = *mSrc++;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar8 = LoopVar1;
 | 
						|
 | 
						|
  LoopVar7  -= LoopVar8;
 | 
						|
  mOrigSize += LoopVar8;
 | 
						|
  LoopVar1--;
 | 
						|
  while (LoopVar1 >= 0) {
 | 
						|
    UPDATE_CRC (*LoopVar7++);
 | 
						|
    LoopVar1--;
 | 
						|
  }
 | 
						|
 | 
						|
  return LoopVar8;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Advance the current position (read in new data if needed).
 | 
						|
  Delete outdated string info. Find a match string for current position.
 | 
						|
 | 
						|
  @retval TRUE      The operation was successful.
 | 
						|
  @retval FALSE     The operation failed due to insufficient memory.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
GetNextMatch (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar8;
 | 
						|
  VOID   *Temp;
 | 
						|
 | 
						|
  mRemainder--;
 | 
						|
  mPos++;
 | 
						|
  if (mPos == WNDSIZ * 2) {
 | 
						|
    Temp = AllocateZeroPool (WNDSIZ + MAXMATCH);
 | 
						|
    if (Temp == NULL) {
 | 
						|
      return (FALSE);
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (Temp, &mText[WNDSIZ], WNDSIZ + MAXMATCH);
 | 
						|
    CopyMem (&mText[0], Temp, WNDSIZ + MAXMATCH);
 | 
						|
    FreePool (Temp);
 | 
						|
    LoopVar8    = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
 | 
						|
    mRemainder += LoopVar8;
 | 
						|
    mPos        = WNDSIZ;
 | 
						|
  }
 | 
						|
 | 
						|
  DeleteNode ();
 | 
						|
  InsertNode ();
 | 
						|
 | 
						|
  return (TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send entry LoopVar1 down the queue.
 | 
						|
 | 
						|
  @param[in] LoopVar1    The index of the item to move.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DownHeap (
 | 
						|
  IN INT32  i
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  INT32  LoopVar2;
 | 
						|
 | 
						|
  //
 | 
						|
  // priority queue: send i-th entry down heap
 | 
						|
  //
 | 
						|
  LoopVar2 = mHeap[i];
 | 
						|
  LoopVar1 = 2 * i;
 | 
						|
  while (LoopVar1 <= mHeapSize) {
 | 
						|
    if ((LoopVar1 < mHeapSize) && (mFreq[mHeap[LoopVar1]] > mFreq[mHeap[LoopVar1 + 1]])) {
 | 
						|
      LoopVar1++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mFreq[LoopVar2] <= mFreq[mHeap[LoopVar1]]) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    mHeap[i] = mHeap[LoopVar1];
 | 
						|
    i        = LoopVar1;
 | 
						|
    LoopVar1 = 2 * i;
 | 
						|
  }
 | 
						|
 | 
						|
  mHeap[i] = (INT16)LoopVar2;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Count the number of each code length for a Huffman tree.
 | 
						|
 | 
						|
  @param[in] LoopVar1      The top node.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CountLen (
 | 
						|
  IN INT32  LoopVar1
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (LoopVar1 < mTempInt32) {
 | 
						|
    mLenCnt[(mHuffmanDepth < 16) ? mHuffmanDepth : 16]++;
 | 
						|
  } else {
 | 
						|
    mHuffmanDepth++;
 | 
						|
    CountLen (mLeft[LoopVar1]);
 | 
						|
    CountLen (mRight[LoopVar1]);
 | 
						|
    mHuffmanDepth--;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create code length array for a Huffman tree.
 | 
						|
 | 
						|
  @param[in] Root   The root of the tree.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
MakeLen (
 | 
						|
  IN INT32  Root
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  INT32   LoopVar2;
 | 
						|
  UINT32  Cum;
 | 
						|
 | 
						|
  for (LoopVar1 = 0; LoopVar1 <= 16; LoopVar1++) {
 | 
						|
    mLenCnt[LoopVar1] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  CountLen (Root);
 | 
						|
 | 
						|
  //
 | 
						|
  // Adjust the length count array so that
 | 
						|
  // no code will be generated longer than its designated length
 | 
						|
  //
 | 
						|
  Cum = 0;
 | 
						|
  for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {
 | 
						|
    Cum += mLenCnt[LoopVar1] << (16 - LoopVar1);
 | 
						|
  }
 | 
						|
 | 
						|
  while (Cum != (1U << 16)) {
 | 
						|
    mLenCnt[16]--;
 | 
						|
    for (LoopVar1 = 15; LoopVar1 > 0; LoopVar1--) {
 | 
						|
      if (mLenCnt[LoopVar1] != 0) {
 | 
						|
        mLenCnt[LoopVar1]--;
 | 
						|
        mLenCnt[LoopVar1 + 1] += 2;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Cum--;
 | 
						|
  }
 | 
						|
 | 
						|
  for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {
 | 
						|
    LoopVar2 = mLenCnt[LoopVar1];
 | 
						|
    LoopVar2--;
 | 
						|
    while (LoopVar2 >= 0) {
 | 
						|
      mLen[*mSortPtr++] = (UINT8)LoopVar1;
 | 
						|
      LoopVar2--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Assign code to each symbol based on the code length array.
 | 
						|
 | 
						|
  @param[in] LoopVar8      The number of symbols.
 | 
						|
  @param[in] Len    The code length array.
 | 
						|
  @param[out] Code  The stores codes for each symbol.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
MakeCode (
 | 
						|
  IN  INT32   LoopVar8,
 | 
						|
  IN  UINT8   Len[],
 | 
						|
  OUT UINT16  Code[]
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32   LoopVar1;
 | 
						|
  UINT16  Start[18];
 | 
						|
 | 
						|
  Start[1] = 0;
 | 
						|
  for (LoopVar1 = 1; LoopVar1 <= 16; LoopVar1++) {
 | 
						|
    Start[LoopVar1 + 1] = (UINT16)((Start[LoopVar1] + mLenCnt[LoopVar1]) << 1);
 | 
						|
  }
 | 
						|
 | 
						|
  for (LoopVar1 = 0; LoopVar1 < LoopVar8; LoopVar1++) {
 | 
						|
    Code[LoopVar1] = Start[Len[LoopVar1]]++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generates Huffman codes given a frequency distribution of symbols.
 | 
						|
 | 
						|
  @param[in] NParm      The number of symbols.
 | 
						|
  @param[in] FreqParm   The frequency of each symbol.
 | 
						|
  @param[out] LenParm   The code length for each symbol.
 | 
						|
  @param[out] CodeParm  The code for each symbol.
 | 
						|
 | 
						|
  @return The root of the Huffman tree.
 | 
						|
**/
 | 
						|
INT32
 | 
						|
MakeTree (
 | 
						|
  IN  INT32   NParm,
 | 
						|
  IN  UINT16  FreqParm[],
 | 
						|
  OUT UINT8   LenParm[],
 | 
						|
  OUT UINT16  CodeParm[]
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  INT32  LoopVar2;
 | 
						|
 | 
						|
  INT32  LoopVar3;
 | 
						|
 | 
						|
  INT32  Avail;
 | 
						|
 | 
						|
  //
 | 
						|
  // make tree, calculate len[], return root
 | 
						|
  //
 | 
						|
  mTempInt32 = NParm;
 | 
						|
  mFreq      = FreqParm;
 | 
						|
  mLen       = LenParm;
 | 
						|
  Avail      = mTempInt32;
 | 
						|
  mHeapSize  = 0;
 | 
						|
  mHeap[1]   = 0;
 | 
						|
  for (LoopVar1 = 0; LoopVar1 < mTempInt32; LoopVar1++) {
 | 
						|
    mLen[LoopVar1] = 0;
 | 
						|
    if ((mFreq[LoopVar1]) != 0) {
 | 
						|
      mHeapSize++;
 | 
						|
      mHeap[mHeapSize] = (INT16)LoopVar1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (mHeapSize < 2) {
 | 
						|
    CodeParm[mHeap[1]] = 0;
 | 
						|
    return mHeap[1];
 | 
						|
  }
 | 
						|
 | 
						|
  for (LoopVar1 = mHeapSize / 2; LoopVar1 >= 1; LoopVar1--) {
 | 
						|
    //
 | 
						|
    // make priority queue
 | 
						|
    //
 | 
						|
    DownHeap (LoopVar1);
 | 
						|
  }
 | 
						|
 | 
						|
  mSortPtr = CodeParm;
 | 
						|
  do {
 | 
						|
    LoopVar1 = mHeap[1];
 | 
						|
    if (LoopVar1 < mTempInt32) {
 | 
						|
      *mSortPtr++ = (UINT16)LoopVar1;
 | 
						|
    }
 | 
						|
 | 
						|
    mHeap[1] = mHeap[mHeapSize--];
 | 
						|
    DownHeap (1);
 | 
						|
    LoopVar2 = mHeap[1];
 | 
						|
    if (LoopVar2 < mTempInt32) {
 | 
						|
      *mSortPtr++ = (UINT16)LoopVar2;
 | 
						|
    }
 | 
						|
 | 
						|
    LoopVar3        = Avail++;
 | 
						|
    mFreq[LoopVar3] = (UINT16)(mFreq[LoopVar1] + mFreq[LoopVar2]);
 | 
						|
    mHeap[1]        = (INT16)LoopVar3;
 | 
						|
    DownHeap (1);
 | 
						|
    mLeft[LoopVar3]  = (UINT16)LoopVar1;
 | 
						|
    mRight[LoopVar3] = (UINT16)LoopVar2;
 | 
						|
  } while (mHeapSize > 1);
 | 
						|
 | 
						|
  mSortPtr = CodeParm;
 | 
						|
  MakeLen (LoopVar3);
 | 
						|
  MakeCode (NParm, LenParm, CodeParm);
 | 
						|
 | 
						|
  //
 | 
						|
  // return root
 | 
						|
  //
 | 
						|
  return LoopVar3;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Outputs rightmost LoopVar8 bits of x
 | 
						|
 | 
						|
  @param[in] LoopVar8   The rightmost LoopVar8 bits of the data is used.
 | 
						|
  @param[in] x   The data.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PutBits (
 | 
						|
  IN INT32   LoopVar8,
 | 
						|
  IN UINT32  x
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Temp;
 | 
						|
 | 
						|
  if (LoopVar8 < mBitCount) {
 | 
						|
    mSubBitBuf |= x << (mBitCount -= LoopVar8);
 | 
						|
  } else {
 | 
						|
    Temp = (UINT8)(mSubBitBuf | (x >> (LoopVar8 -= mBitCount)));
 | 
						|
    if (mDst < mDstUpperLimit) {
 | 
						|
      *mDst++ = Temp;
 | 
						|
    }
 | 
						|
 | 
						|
    mCompSize++;
 | 
						|
 | 
						|
    if (LoopVar8 < UINT8_BIT) {
 | 
						|
      mSubBitBuf = x << (mBitCount = UINT8_BIT - LoopVar8);
 | 
						|
    } else {
 | 
						|
      Temp = (UINT8)(x >> (LoopVar8 - UINT8_BIT));
 | 
						|
      if (mDst < mDstUpperLimit) {
 | 
						|
        *mDst++ = Temp;
 | 
						|
      }
 | 
						|
 | 
						|
      mCompSize++;
 | 
						|
 | 
						|
      mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - LoopVar8);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Encode a signed 32 bit number.
 | 
						|
 | 
						|
  @param[in] LoopVar5     The number to encode.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EncodeC (
 | 
						|
  IN INT32  LoopVar5
 | 
						|
  )
 | 
						|
{
 | 
						|
  PutBits (mCLen[LoopVar5], mCCode[LoopVar5]);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Encode a unsigned 32 bit number.
 | 
						|
 | 
						|
  @param[in] LoopVar7     The number to encode.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EncodeP (
 | 
						|
  IN UINT32  LoopVar7
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  LoopVar5;
 | 
						|
 | 
						|
  UINT32  LoopVar6;
 | 
						|
 | 
						|
  LoopVar5 = 0;
 | 
						|
  LoopVar6 = LoopVar7;
 | 
						|
  while (LoopVar6 != 0) {
 | 
						|
    LoopVar6 >>= 1;
 | 
						|
    LoopVar5++;
 | 
						|
  }
 | 
						|
 | 
						|
  PutBits (mPTLen[LoopVar5], mPTCode[LoopVar5]);
 | 
						|
  if (LoopVar5 > 1) {
 | 
						|
    PutBits (LoopVar5 - 1, LoopVar7 & (0xFFFFU >> (17 - LoopVar5)));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Count the frequencies for the Extra Set.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CountTFreq (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  INT32  LoopVar3;
 | 
						|
 | 
						|
  INT32  LoopVar8;
 | 
						|
 | 
						|
  INT32  Count;
 | 
						|
 | 
						|
  for (LoopVar1 = 0; LoopVar1 < NT; LoopVar1++) {
 | 
						|
    mTFreq[LoopVar1] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar8 = NC;
 | 
						|
  while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {
 | 
						|
    LoopVar8--;
 | 
						|
  }
 | 
						|
 | 
						|
  LoopVar1 = 0;
 | 
						|
  while (LoopVar1 < LoopVar8) {
 | 
						|
    LoopVar3 = mCLen[LoopVar1++];
 | 
						|
    if (LoopVar3 == 0) {
 | 
						|
      Count = 1;
 | 
						|
      while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {
 | 
						|
        LoopVar1++;
 | 
						|
        Count++;
 | 
						|
      }
 | 
						|
 | 
						|
      if (Count <= 2) {
 | 
						|
        mTFreq[0] = (UINT16)(mTFreq[0] + Count);
 | 
						|
      } else if (Count <= 18) {
 | 
						|
        mTFreq[1]++;
 | 
						|
      } else if (Count == 19) {
 | 
						|
        mTFreq[0]++;
 | 
						|
        mTFreq[1]++;
 | 
						|
      } else {
 | 
						|
        mTFreq[2]++;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      ASSERT ((LoopVar3+2) < (2 * NT - 1));
 | 
						|
      mTFreq[LoopVar3 + 2]++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Outputs the code length array for the Extra Set or the Position Set.
 | 
						|
 | 
						|
  @param[in] LoopVar8       The number of symbols.
 | 
						|
  @param[in] nbit           The number of bits needed to represent 'LoopVar8'.
 | 
						|
  @param[in] Special        The special symbol that needs to be take care of.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
WritePTLen (
 | 
						|
  IN INT32  LoopVar8,
 | 
						|
  IN INT32  nbit,
 | 
						|
  IN INT32  Special
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  INT32  LoopVar3;
 | 
						|
 | 
						|
  while (LoopVar8 > 0 && mPTLen[LoopVar8 - 1] == 0) {
 | 
						|
    LoopVar8--;
 | 
						|
  }
 | 
						|
 | 
						|
  PutBits (nbit, LoopVar8);
 | 
						|
  LoopVar1 = 0;
 | 
						|
  while (LoopVar1 < LoopVar8) {
 | 
						|
    LoopVar3 = mPTLen[LoopVar1++];
 | 
						|
    if (LoopVar3 <= 6) {
 | 
						|
      PutBits (3, LoopVar3);
 | 
						|
    } else {
 | 
						|
      PutBits (LoopVar3 - 3, (1U << (LoopVar3 - 3)) - 2);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LoopVar1 == Special) {
 | 
						|
      while (LoopVar1 < 6 && mPTLen[LoopVar1] == 0) {
 | 
						|
        LoopVar1++;
 | 
						|
      }
 | 
						|
 | 
						|
      PutBits (2, (LoopVar1 - 3) & 3);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Outputs the code length array for Char&Length Set.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
WriteCLen (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32  LoopVar1;
 | 
						|
 | 
						|
  INT32  LoopVar3;
 | 
						|
 | 
						|
  INT32  LoopVar8;
 | 
						|
 | 
						|
  INT32  Count;
 | 
						|
 | 
						|
  LoopVar8 = NC;
 | 
						|
  while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {
 | 
						|
    LoopVar8--;
 | 
						|
  }
 | 
						|
 | 
						|
  PutBits (CBIT, LoopVar8);
 | 
						|
  LoopVar1 = 0;
 | 
						|
  while (LoopVar1 < LoopVar8) {
 | 
						|
    LoopVar3 = mCLen[LoopVar1++];
 | 
						|
    if (LoopVar3 == 0) {
 | 
						|
      Count = 1;
 | 
						|
      while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {
 | 
						|
        LoopVar1++;
 | 
						|
        Count++;
 | 
						|
      }
 | 
						|
 | 
						|
      if (Count <= 2) {
 | 
						|
        for (LoopVar3 = 0; LoopVar3 < Count; LoopVar3++) {
 | 
						|
          PutBits (mPTLen[0], mPTCode[0]);
 | 
						|
        }
 | 
						|
      } else if (Count <= 18) {
 | 
						|
        PutBits (mPTLen[1], mPTCode[1]);
 | 
						|
        PutBits (4, Count - 3);
 | 
						|
      } else if (Count == 19) {
 | 
						|
        PutBits (mPTLen[0], mPTCode[0]);
 | 
						|
        PutBits (mPTLen[1], mPTCode[1]);
 | 
						|
        PutBits (4, 15);
 | 
						|
      } else {
 | 
						|
        PutBits (mPTLen[2], mPTCode[2]);
 | 
						|
        PutBits (CBIT, Count - 20);
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      ASSERT ((LoopVar3+2) < NPT);
 | 
						|
      PutBits (mPTLen[LoopVar3 + 2], mPTCode[LoopVar3 + 2]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Huffman code the block and output it.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SendBlock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  LoopVar1;
 | 
						|
 | 
						|
  UINT32  LoopVar3;
 | 
						|
 | 
						|
  UINT32  Flags;
 | 
						|
 | 
						|
  UINT32  Root;
 | 
						|
 | 
						|
  UINT32  Pos;
 | 
						|
 | 
						|
  UINT32  Size;
 | 
						|
 | 
						|
  Flags = 0;
 | 
						|
 | 
						|
  Root = MakeTree (NC, mCFreq, mCLen, mCCode);
 | 
						|
  Size = mCFreq[Root];
 | 
						|
  PutBits (16, Size);
 | 
						|
  if (Root >= NC) {
 | 
						|
    CountTFreq ();
 | 
						|
    Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
 | 
						|
    if (Root >= NT) {
 | 
						|
      WritePTLen (NT, TBIT, 3);
 | 
						|
    } else {
 | 
						|
      PutBits (TBIT, 0);
 | 
						|
      PutBits (TBIT, Root);
 | 
						|
    }
 | 
						|
 | 
						|
    WriteCLen ();
 | 
						|
  } else {
 | 
						|
    PutBits (TBIT, 0);
 | 
						|
    PutBits (TBIT, 0);
 | 
						|
    PutBits (CBIT, 0);
 | 
						|
    PutBits (CBIT, Root);
 | 
						|
  }
 | 
						|
 | 
						|
  Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
 | 
						|
  if (Root >= NP) {
 | 
						|
    WritePTLen (NP, PBIT, -1);
 | 
						|
  } else {
 | 
						|
    PutBits (PBIT, 0);
 | 
						|
    PutBits (PBIT, Root);
 | 
						|
  }
 | 
						|
 | 
						|
  Pos = 0;
 | 
						|
  for (LoopVar1 = 0; LoopVar1 < Size; LoopVar1++) {
 | 
						|
    if (LoopVar1 % UINT8_BIT == 0) {
 | 
						|
      Flags = mBuf[Pos++];
 | 
						|
    } else {
 | 
						|
      Flags <<= 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Flags & (1U << (UINT8_BIT - 1))) != 0) {
 | 
						|
      EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
 | 
						|
      LoopVar3  = mBuf[Pos++] << UINT8_BIT;
 | 
						|
      LoopVar3 += mBuf[Pos++];
 | 
						|
 | 
						|
      EncodeP (LoopVar3);
 | 
						|
    } else {
 | 
						|
      EncodeC (mBuf[Pos++]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  SetMem (mCFreq, NC * sizeof (UINT16), 0);
 | 
						|
  SetMem (mPFreq, NP * sizeof (UINT16), 0);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start the huffman encoding.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
HufEncodeStart (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SetMem (mCFreq, NC * sizeof (UINT16), 0);
 | 
						|
  SetMem (mPFreq, NP * sizeof (UINT16), 0);
 | 
						|
 | 
						|
  mOutputPos = mOutputMask = 0;
 | 
						|
 | 
						|
  mBitCount  = UINT8_BIT;
 | 
						|
  mSubBitBuf = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Outputs an Original Character or a Pointer.
 | 
						|
 | 
						|
  @param[in] LoopVar5     The original character or the 'String Length' element of
 | 
						|
                   a Pointer.
 | 
						|
  @param[in] LoopVar7     The 'Position' field of a Pointer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CompressOutput (
 | 
						|
  IN UINT32  LoopVar5,
 | 
						|
  IN UINT32  LoopVar7
 | 
						|
  )
 | 
						|
{
 | 
						|
  STATIC UINT32  CPos;
 | 
						|
 | 
						|
  if ((mOutputMask >>= 1) == 0) {
 | 
						|
    mOutputMask = 1U << (UINT8_BIT - 1);
 | 
						|
    if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {
 | 
						|
      SendBlock ();
 | 
						|
      mOutputPos = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    CPos       = mOutputPos++;
 | 
						|
    mBuf[CPos] = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  mBuf[mOutputPos++] = (UINT8)LoopVar5;
 | 
						|
  mCFreq[LoopVar5]++;
 | 
						|
  if (LoopVar5 >= (1U << UINT8_BIT)) {
 | 
						|
    mBuf[CPos]         = (UINT8)(mBuf[CPos]|mOutputMask);
 | 
						|
    mBuf[mOutputPos++] = (UINT8)(LoopVar7 >> UINT8_BIT);
 | 
						|
    mBuf[mOutputPos++] = (UINT8)LoopVar7;
 | 
						|
    LoopVar5           = 0;
 | 
						|
    while (LoopVar7 != 0) {
 | 
						|
      LoopVar7 >>= 1;
 | 
						|
      LoopVar5++;
 | 
						|
    }
 | 
						|
 | 
						|
    mPFreq[LoopVar5]++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  End the huffman encoding.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
HufEncodeEnd (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  SendBlock ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Flush remaining bits
 | 
						|
  //
 | 
						|
  PutBits (UINT8_BIT - 1, 0);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The main controlling routine for compression process.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The compression is successful.
 | 
						|
  @retval EFI_OUT_0F_RESOURCES  Not enough memory for compression process.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Encode (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  INT32       LastMatchLen;
 | 
						|
  NODE        LastMatchPos;
 | 
						|
 | 
						|
  Status = AllocateMemory ();
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreeMemory ();
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  InitSlide ();
 | 
						|
 | 
						|
  HufEncodeStart ();
 | 
						|
 | 
						|
  mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
 | 
						|
 | 
						|
  mMatchLen = 0;
 | 
						|
  mPos      = WNDSIZ;
 | 
						|
  InsertNode ();
 | 
						|
  if (mMatchLen > mRemainder) {
 | 
						|
    mMatchLen = mRemainder;
 | 
						|
  }
 | 
						|
 | 
						|
  while (mRemainder > 0) {
 | 
						|
    LastMatchLen = mMatchLen;
 | 
						|
    LastMatchPos = mMatchPos;
 | 
						|
    if (!GetNextMatch ()) {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mMatchLen > mRemainder) {
 | 
						|
      mMatchLen = mRemainder;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((mMatchLen > LastMatchLen) || (LastMatchLen < THRESHOLD)) {
 | 
						|
      //
 | 
						|
      // Not enough benefits are gained by outputting a pointer,
 | 
						|
      // so just output the original character
 | 
						|
      //
 | 
						|
      CompressOutput (mText[mPos - 1], 0);
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Outputting a pointer is beneficial enough, do it.
 | 
						|
      //
 | 
						|
 | 
						|
      CompressOutput (
 | 
						|
        LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
 | 
						|
        (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
 | 
						|
        );
 | 
						|
      LastMatchLen--;
 | 
						|
      while (LastMatchLen > 0) {
 | 
						|
        if (!GetNextMatch ()) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        }
 | 
						|
 | 
						|
        LastMatchLen--;
 | 
						|
      }
 | 
						|
 | 
						|
      if (mMatchLen > mRemainder) {
 | 
						|
        mMatchLen = mRemainder;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  HufEncodeEnd ();
 | 
						|
  FreeMemory ();
 | 
						|
  return (Status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The compression routine.
 | 
						|
 | 
						|
  @param[in]       SrcBuffer     The buffer containing the source data.
 | 
						|
  @param[in]       SrcSize       Number of bytes in SrcBuffer.
 | 
						|
  @param[in]       DstBuffer     The buffer to put the compressed image in.
 | 
						|
  @param[in, out]  DstSize       On input the size (in bytes) of DstBuffer, on
 | 
						|
                                 return the number of bytes placed in DstBuffer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The compression was sucessful.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.  DstSize is required.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Compress (
 | 
						|
  IN      VOID    *SrcBuffer,
 | 
						|
  IN      UINT64  SrcSize,
 | 
						|
  IN      VOID    *DstBuffer,
 | 
						|
  IN OUT  UINT64  *DstSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initializations
 | 
						|
  //
 | 
						|
  mBufSiz     = 0;
 | 
						|
  mBuf        = NULL;
 | 
						|
  mText       = NULL;
 | 
						|
  mLevel      = NULL;
 | 
						|
  mChildCount = NULL;
 | 
						|
  mPosition   = NULL;
 | 
						|
  mParent     = NULL;
 | 
						|
  mPrev       = NULL;
 | 
						|
  mNext       = NULL;
 | 
						|
 | 
						|
  mSrc           = SrcBuffer;
 | 
						|
  mSrcUpperLimit = mSrc + SrcSize;
 | 
						|
  mDst           = DstBuffer;
 | 
						|
  mDstUpperLimit = mDst +*DstSize;
 | 
						|
 | 
						|
  PutDword (0L);
 | 
						|
  PutDword (0L);
 | 
						|
 | 
						|
  MakeCrcTable ();
 | 
						|
 | 
						|
  mOrigSize = mCompSize = 0;
 | 
						|
  mCrc      = INIT_CRC;
 | 
						|
 | 
						|
  //
 | 
						|
  // Compress it
 | 
						|
  //
 | 
						|
  Status = Encode ();
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Null terminate the compressed data
 | 
						|
  //
 | 
						|
  if (mDst < mDstUpperLimit) {
 | 
						|
    *mDst++ = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill in compressed size and original size
 | 
						|
  //
 | 
						|
  mDst = DstBuffer;
 | 
						|
  PutDword (mCompSize + 1);
 | 
						|
  PutDword (mOrigSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Return
 | 
						|
  //
 | 
						|
  if (mCompSize + 1 + 8 > *DstSize) {
 | 
						|
    *DstSize = mCompSize + 1 + 8;
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  } else {
 | 
						|
    *DstSize = mCompSize + 1 + 8;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
}
 |