1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591 |
- /** @file
- 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) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Compress.h"
- //
- // Macro Definitions
- //
- #undef UINT8_MAX
- 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 PERC_FLAG 0x8000U
- #define CODE_BIT 16
- #define NIL 0
- #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
- #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
- #define CRCPOLY 0xA001
- #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 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
- //
- STATIC
- VOID
- PutDword(
- IN UINT32 Data
- );
- STATIC
- EFI_STATUS
- AllocateMemory (
- );
- STATIC
- VOID
- FreeMemory (
- );
- STATIC
- VOID
- InitSlide (
- );
- STATIC
- NODE
- Child (
- IN NODE q,
- IN UINT8 c
- );
- STATIC
- VOID
- MakeChild (
- IN NODE q,
- IN UINT8 c,
- IN NODE r
- );
- STATIC
- VOID
- Split (
- IN NODE Old
- );
- STATIC
- VOID
- InsertNode (
- );
- STATIC
- VOID
- DeleteNode (
- );
- STATIC
- VOID
- GetNextMatch (
- );
- STATIC
- EFI_STATUS
- Encode (
- );
- STATIC
- VOID
- CountTFreq (
- );
- STATIC
- VOID
- WritePTLen (
- IN INT32 n,
- IN INT32 nbit,
- IN INT32 Special
- );
- STATIC
- VOID
- WriteCLen (
- );
- STATIC
- VOID
- EncodeC (
- IN INT32 c
- );
- STATIC
- VOID
- EncodeP (
- IN UINT32 p
- );
- STATIC
- VOID
- SendBlock (
- );
- STATIC
- VOID
- Output (
- IN UINT32 c,
- IN UINT32 p
- );
- STATIC
- VOID
- HufEncodeStart (
- );
- STATIC
- VOID
- HufEncodeEnd (
- );
- STATIC
- VOID
- MakeCrcTable (
- );
- STATIC
- VOID
- PutBits (
- IN INT32 n,
- IN UINT32 x
- );
- STATIC
- INT32
- FreadCrc (
- OUT UINT8 *p,
- IN INT32 n
- );
- STATIC
- VOID
- InitPutBits (
- );
- STATIC
- VOID
- CountLen (
- IN INT32 i
- );
- STATIC
- VOID
- MakeLen (
- IN INT32 Root
- );
- STATIC
- VOID
- DownHeap (
- IN INT32 i
- );
- STATIC
- VOID
- MakeCode (
- IN INT32 n,
- IN UINT8 Len[],
- OUT UINT16 Code[]
- );
- STATIC
- INT32
- MakeTree (
- IN INT32 NParm,
- IN UINT16 FreqParm[],
- OUT UINT8 LenParm[],
- OUT UINT16 CodeParm[]
- );
- //
- // Global Variables
- //
- STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
- STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
- STATIC INT16 mHeap[NC + 1];
- STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
- STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
- STATIC UINT32 mCompSize, mOrigSize;
- STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1],
- mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC],
- mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
- STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
- //
- // functions
- //
- EFI_STATUS
- EfiCompress (
- IN UINT8 *SrcBuffer,
- IN UINT32 SrcSize,
- IN UINT8 *DstBuffer,
- IN OUT UINT32 *DstSize
- )
- /*++
- Routine Description:
- The main compression routine.
- Arguments:
- SrcBuffer - The buffer storing the source data
- SrcSize - The size of source data
- DstBuffer - The buffer to store the compressed data
- DstSize - On input, the size of DstBuffer; On output,
- the size of the actual compressed data.
- Returns:
- EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
- DstSize contains the size needed.
- EFI_SUCCESS - Compression is successful.
- --*/
- {
- EFI_STATUS Status = EFI_SUCCESS;
- //
- // 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;
- }
- }
- STATIC
- VOID
- PutDword(
- IN UINT32 Data
- )
- /*++
- Routine Description:
- Put a dword to output stream
- Arguments:
- Data - the dword to put
- Returns: (VOID)
- --*/
- {
- 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);
- }
- }
- STATIC
- EFI_STATUS
- AllocateMemory ()
- /*++
- Routine Description:
- Allocate memory spaces for data structures used in compression process
- Arguments: (VOID)
- Returns:
- EFI_SUCCESS - Memory is allocated successfully
- EFI_OUT_OF_RESOURCES - Allocation fails
- --*/
- {
- UINT32 i;
- mText = malloc (WNDSIZ * 2 + MAXMATCH);
- if (mText == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {
- mText[i] = 0;
- }
- mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel));
- mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount));
- mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition));
- mParent = malloc (WNDSIZ * 2 * sizeof(*mParent));
- mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev));
- mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext));
- if (mLevel == NULL || mChildCount == NULL || mPosition == NULL ||
- mParent == NULL || mPrev == NULL || mNext == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- mBufSiz = 16 * 1024U;
- while ((mBuf = malloc(mBufSiz)) == NULL) {
- mBufSiz = (mBufSiz / 10U) * 9U;
- if (mBufSiz < 4 * 1024U) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
- mBuf[0] = 0;
- return EFI_SUCCESS;
- }
- VOID
- FreeMemory ()
- /*++
- Routine Description:
- Called when compression is completed to free memory previously allocated.
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- if (mText) {
- free (mText);
- }
- if (mLevel) {
- free (mLevel);
- }
- if (mChildCount) {
- free (mChildCount);
- }
- if (mPosition) {
- free (mPosition);
- }
- if (mParent) {
- free (mParent);
- }
- if (mPrev) {
- free (mPrev);
- }
- if (mNext) {
- free (mNext);
- }
- if (mBuf) {
- free (mBuf);
- }
- return;
- }
- STATIC
- VOID
- InitSlide ()
- /*++
- Routine Description:
- Initialize String Info Log data structures
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- NODE i;
- for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) {
- mLevel[i] = 1;
- mPosition[i] = NIL; /* sentinel */
- }
- for (i = WNDSIZ; i < WNDSIZ * 2; i++) {
- mParent[i] = NIL;
- }
- mAvail = 1;
- for (i = 1; i < WNDSIZ - 1; i++) {
- mNext[i] = (NODE)(i + 1);
- }
- mNext[WNDSIZ - 1] = NIL;
- for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) {
- mNext[i] = NIL;
- }
- }
- STATIC
- NODE
- Child (
- IN NODE q,
- IN UINT8 c
- )
- /*++
- Routine Description:
- Find child node given the parent node and the edge character
- Arguments:
- q - the parent node
- c - the edge character
- Returns:
- The child node (NIL if not found)
- --*/
- {
- NODE r;
- r = mNext[HASH(q, c)];
- mParent[NIL] = q; /* sentinel */
- while (mParent[r] != q) {
- r = mNext[r];
- }
- return r;
- }
- STATIC
- VOID
- MakeChild (
- IN NODE q,
- IN UINT8 c,
- IN NODE r
- )
- /*++
- Routine Description:
- Create a new child for a given parent node.
- Arguments:
- q - the parent node
- c - the edge character
- r - the child node
- Returns: (VOID)
- --*/
- {
- NODE h, t;
- h = (NODE)HASH(q, c);
- t = mNext[h];
- mNext[h] = r;
- mNext[r] = t;
- mPrev[t] = r;
- mPrev[r] = h;
- mParent[r] = q;
- mChildCount[q]++;
- }
- STATIC
- VOID
- Split (
- NODE Old
- )
- /*++
- Routine Description:
- Split a node.
- Arguments:
- Old - the node to split
- Returns: (VOID)
- --*/
- {
- NODE New, t;
- New = mAvail;
- mAvail = mNext[New];
- mChildCount[New] = 0;
- t = mPrev[Old];
- mPrev[New] = t;
- mNext[t] = New;
- t = mNext[Old];
- mNext[New] = t;
- mPrev[t] = New;
- mParent[New] = mParent[Old];
- mLevel[New] = (UINT8)mMatchLen;
- mPosition[New] = mPos;
- MakeChild(New, mText[mMatchPos + mMatchLen], Old);
- MakeChild(New, mText[mPos + mMatchLen], mPos);
- }
- STATIC
- VOID
- InsertNode ()
- /*++
- Routine Description:
- Insert string info for current position into the String Info Log
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- NODE q, r, j, t;
- UINT8 c, *t1, *t2;
- if (mMatchLen >= 4) {
- //
- // We have just got a long match, the target tree
- // can be located by MatchPos + 1. Traverse 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--;
- r = (INT16)((mMatchPos + 1) | WNDSIZ);
- while ((q = mParent[r]) == NIL) {
- r = mNext[r];
- }
- while (mLevel[q] >= mMatchLen) {
- r = q; q = mParent[q];
- }
- t = q;
- while (mPosition[t] < 0) {
- mPosition[t] = mPos;
- t = mParent[t];
- }
- if (t < WNDSIZ) {
- mPosition[t] = (NODE)(mPos | PERC_FLAG);
- }
- } else {
- //
- // Locate the target tree
- //
- q = (INT16)(mText[mPos] + WNDSIZ);
- c = mText[mPos + 1];
- if ((r = Child(q, c)) == NIL) {
- MakeChild(q, c, 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 (r >= WNDSIZ) {
- j = MAXMATCH;
- mMatchPos = r;
- } else {
- j = mLevel[r];
- mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG);
- }
- if (mMatchPos >= mPos) {
- mMatchPos -= WNDSIZ;
- }
- t1 = &mText[mPos + mMatchLen];
- t2 = &mText[mMatchPos + mMatchLen];
- while (mMatchLen < j) {
- if (*t1 != *t2) {
- Split(r);
- return;
- }
- mMatchLen++;
- t1++;
- t2++;
- }
- if (mMatchLen >= MAXMATCH) {
- break;
- }
- mPosition[r] = mPos;
- q = r;
- if ((r = Child(q, *t1)) == NIL) {
- MakeChild(q, *t1, mPos);
- return;
- }
- mMatchLen++;
- }
- t = mPrev[r];
- mPrev[mPos] = t;
- mNext[t] = mPos;
- t = mNext[r];
- mNext[mPos] = t;
- mPrev[t] = mPos;
- mParent[mPos] = q;
- mParent[r] = NIL;
- //
- // Special usage of 'next'
- //
- mNext[r] = mPos;
- }
- STATIC
- VOID
- DeleteNode ()
- /*++
- Routine Description:
- Delete outdated string info. (The Usage of PERC_FLAG
- ensures a clean deletion)
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- NODE q, r, s, t, u;
- if (mParent[mPos] == NIL) {
- return;
- }
- r = mPrev[mPos];
- s = mNext[mPos];
- mNext[r] = s;
- mPrev[s] = r;
- r = mParent[mPos];
- mParent[mPos] = NIL;
- if (r >= WNDSIZ || --mChildCount[r] > 1) {
- return;
- }
- t = (NODE)(mPosition[r] & ~PERC_FLAG);
- if (t >= mPos) {
- t -= WNDSIZ;
- }
- s = t;
- q = mParent[r];
- while ((u = mPosition[q]) & PERC_FLAG) {
- u &= ~PERC_FLAG;
- if (u >= mPos) {
- u -= WNDSIZ;
- }
- if (u > s) {
- s = u;
- }
- mPosition[q] = (INT16)(s | WNDSIZ);
- q = mParent[q];
- }
- if (q < WNDSIZ) {
- if (u >= mPos) {
- u -= WNDSIZ;
- }
- if (u > s) {
- s = u;
- }
- mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG);
- }
- s = Child(r, mText[t + mLevel[r]]);
- t = mPrev[s];
- u = mNext[s];
- mNext[t] = u;
- mPrev[u] = t;
- t = mPrev[r];
- mNext[t] = s;
- mPrev[s] = t;
- t = mNext[r];
- mPrev[t] = s;
- mNext[s] = t;
- mParent[s] = mParent[r];
- mParent[r] = NIL;
- mNext[r] = mAvail;
- mAvail = r;
- }
- STATIC
- VOID
- GetNextMatch ()
- /*++
- Routine Description:
- Advance the current position (read in new data if needed).
- Delete outdated string info. Find a match string for current position.
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- INT32 n;
- mRemainder--;
- if (++mPos == WNDSIZ * 2) {
- memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
- n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ);
- mRemainder += n;
- mPos = WNDSIZ;
- }
- DeleteNode();
- InsertNode();
- }
- STATIC
- EFI_STATUS
- Encode ()
- /*++
- Routine Description:
- The main controlling routine for compression process.
- Arguments: (VOID)
- Returns:
- EFI_SUCCESS - The compression is successful
- EFI_OUT_0F_RESOURCES - Not enough memory for compression process
- --*/
- {
- 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;
- GetNextMatch();
- 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
- //
- Output(mText[mPos - 1], 0);
- } else {
- //
- // Outputting a pointer is beneficial enough, do it.
- //
- Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
- (mPos - LastMatchPos - 2) & (WNDSIZ - 1));
- while (--LastMatchLen > 0) {
- GetNextMatch();
- }
- if (mMatchLen > mRemainder) {
- mMatchLen = mRemainder;
- }
- }
- }
- HufEncodeEnd();
- FreeMemory();
- return EFI_SUCCESS;
- }
- STATIC
- VOID
- CountTFreq ()
- /*++
- Routine Description:
- Count the frequencies for the Extra Set
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- INT32 i, k, n, Count;
- for (i = 0; i < NT; i++) {
- mTFreq[i] = 0;
- }
- n = NC;
- while (n > 0 && mCLen[n - 1] == 0) {
- n--;
- }
- i = 0;
- while (i < n) {
- k = mCLen[i++];
- if (k == 0) {
- Count = 1;
- while (i < n && mCLen[i] == 0) {
- i++;
- 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 {
- mTFreq[k + 2]++;
- }
- }
- }
- STATIC
- VOID
- WritePTLen (
- IN INT32 n,
- IN INT32 nbit,
- IN INT32 Special
- )
- /*++
- Routine Description:
- Outputs the code length array for the Extra Set or the Position Set.
- Arguments:
- n - the number of symbols
- nbit - the number of bits needed to represent 'n'
- Special - the special symbol that needs to be take care of
- Returns: (VOID)
- --*/
- {
- INT32 i, k;
- while (n > 0 && mPTLen[n - 1] == 0) {
- n--;
- }
- PutBits(nbit, n);
- i = 0;
- while (i < n) {
- k = mPTLen[i++];
- if (k <= 6) {
- PutBits(3, k);
- } else {
- PutBits(k - 3, (1U << (k - 3)) - 2);
- }
- if (i == Special) {
- while (i < 6 && mPTLen[i] == 0) {
- i++;
- }
- PutBits(2, (i - 3) & 3);
- }
- }
- }
- STATIC
- VOID
- WriteCLen ()
- /*++
- Routine Description:
- Outputs the code length array for Char&Length Set
- Arguments: (VOID)
- Returns: (VOID)
- --*/
- {
- INT32 i, k, n, Count;
- n = NC;
- while (n > 0 && mCLen[n - 1] == 0) {
- n--;
- }
- PutBits(CBIT, n);
- i = 0;
- while (i < n) {
- k = mCLen[i++];
- if (k == 0) {
- Count = 1;
- while (i < n && mCLen[i] == 0) {
- i++;
- Count++;
- }
- if (Count <= 2) {
- for (k = 0; k < Count; k++) {
- 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 {
- PutBits(mPTLen[k + 2], mPTCode[k + 2]);
- }
- }
- }
- STATIC
- VOID
- EncodeC (
- IN INT32 c
- )
- {
- PutBits(mCLen[c], mCCode[c]);
- }
- STATIC
- VOID
- EncodeP (
- IN UINT32 p
- )
- {
- UINT32 c, q;
- c = 0;
- q = p;
- while (q) {
- q >>= 1;
- c++;
- }
- PutBits(mPTLen[c], mPTCode[c]);
- if (c > 1) {
- PutBits(c - 1, p & (0xFFFFU >> (17 - c)));
- }
- }
- STATIC
- VOID
- SendBlock ()
- /*++
- Routine Description:
- Huffman code the block and output it.
- Argument: (VOID)
- Returns: (VOID)
- --*/
- {
- UINT32 i, k, Flags, Root, Pos, 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 (i = 0; i < Size; i++) {
- if (i % UINT8_BIT == 0) {
- Flags = mBuf[Pos++];
- } else {
- Flags <<= 1;
- }
- if (Flags & (1U << (UINT8_BIT - 1))) {
- EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));
- k = mBuf[Pos++] << UINT8_BIT;
- k += mBuf[Pos++];
- EncodeP(k);
- } else {
- EncodeC(mBuf[Pos++]);
- }
- }
- for (i = 0; i < NC; i++) {
- mCFreq[i] = 0;
- }
- for (i = 0; i < NP; i++) {
- mPFreq[i] = 0;
- }
- }
- STATIC
- VOID
- Output (
- IN UINT32 c,
- IN UINT32 p
- )
- /*++
- Routine Description:
- Outputs an Original Character or a Pointer
- Arguments:
- c - The original character or the 'String Length' element of a Pointer
- p - The 'Position' field of a Pointer
- Returns: (VOID)
- --*/
- {
- 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) c;
- mCFreq[c]++;
- if (c >= (1U << UINT8_BIT)) {
- mBuf[CPos] |= mOutputMask;
- mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT);
- mBuf[mOutputPos++] = (UINT8) p;
- c = 0;
- while (p) {
- p >>= 1;
- c++;
- }
- mPFreq[c]++;
- }
- }
- STATIC
- VOID
- HufEncodeStart ()
- {
- INT32 i;
- for (i = 0; i < NC; i++) {
- mCFreq[i] = 0;
- }
- for (i = 0; i < NP; i++) {
- mPFreq[i] = 0;
- }
- mOutputPos = mOutputMask = 0;
- InitPutBits();
- return;
- }
- STATIC
- VOID
- HufEncodeEnd ()
- {
- SendBlock();
- //
- // Flush remaining bits
- //
- PutBits(UINT8_BIT - 1, 0);
- return;
- }
- STATIC
- VOID
- MakeCrcTable ()
- {
- UINT32 i, j, r;
- for (i = 0; i <= UINT8_MAX; i++) {
- r = i;
- for (j = 0; j < UINT8_BIT; j++) {
- if (r & 1) {
- r = (r >> 1) ^ CRCPOLY;
- } else {
- r >>= 1;
- }
- }
- mCrcTable[i] = (UINT16)r;
- }
- }
- STATIC
- VOID
- PutBits (
- IN INT32 n,
- IN UINT32 x
- )
- /*++
- Routine Description:
- Outputs rightmost n bits of x
- Arguments:
- n - the rightmost n bits of the data is used
- x - the data
- Returns: (VOID)
- --*/
- {
- UINT8 Temp;
- if (n < mBitCount) {
- mSubBitBuf |= x << (mBitCount -= n);
- } else {
- Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount)));
- if (mDst < mDstUpperLimit) {
- *mDst++ = Temp;
- }
- mCompSize++;
- if (n < UINT8_BIT) {
- mSubBitBuf = x << (mBitCount = UINT8_BIT - n);
- } else {
- Temp = (UINT8)(x >> (n - UINT8_BIT));
- if (mDst < mDstUpperLimit) {
- *mDst++ = Temp;
- }
- mCompSize++;
- mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n);
- }
- }
- }
- STATIC
- INT32
- FreadCrc (
- OUT UINT8 *p,
- IN INT32 n
- )
- /*++
- Routine Description:
- Read in source data
- Arguments:
- p - the buffer to hold the data
- n - number of bytes to read
- Returns:
- number of bytes actually read
- --*/
- {
- INT32 i;
- for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) {
- *p++ = *mSrc++;
- }
- n = i;
- p -= n;
- mOrigSize += n;
- while (--i >= 0) {
- UPDATE_CRC(*p++);
- }
- return n;
- }
- STATIC
- VOID
- InitPutBits ()
- {
- mBitCount = UINT8_BIT;
- mSubBitBuf = 0;
- }
- STATIC
- VOID
- CountLen (
- IN INT32 i
- )
- /*++
- Routine Description:
- Count the number of each code length for a Huffman tree.
- Arguments:
- i - the top node
- Returns: (VOID)
- --*/
- {
- STATIC INT32 Depth = 0;
- if (i < mN) {
- mLenCnt[(Depth < 16) ? Depth : 16]++;
- } else {
- Depth++;
- CountLen(mLeft [i]);
- CountLen(mRight[i]);
- Depth--;
- }
- }
- STATIC
- VOID
- MakeLen (
- IN INT32 Root
- )
- /*++
- Routine Description:
- Create code length array for a Huffman tree
- Arguments:
- Root - the root of the tree
- --*/
- {
- INT32 i, k;
- UINT32 Cum;
- for (i = 0; i <= 16; i++) {
- mLenCnt[i] = 0;
- }
- CountLen(Root);
- //
- // Adjust the length count array so that
- // no code will be generated longer than its designated length
- //
- Cum = 0;
- for (i = 16; i > 0; i--) {
- Cum += mLenCnt[i] << (16 - i);
- }
- while (Cum != (1U << 16)) {
- mLenCnt[16]--;
- for (i = 15; i > 0; i--) {
- if (mLenCnt[i] != 0) {
- mLenCnt[i]--;
- mLenCnt[i+1] += 2;
- break;
- }
- }
- Cum--;
- }
- for (i = 16; i > 0; i--) {
- k = mLenCnt[i];
- while (--k >= 0) {
- mLen[*mSortPtr++] = (UINT8)i;
- }
- }
- }
- STATIC
- VOID
- DownHeap (
- IN INT32 i
- )
- {
- INT32 j, k;
- //
- // priority queue: send i-th entry down heap
- //
- k = mHeap[i];
- while ((j = 2 * i) <= mHeapSize) {
- if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) {
- j++;
- }
- if (mFreq[k] <= mFreq[mHeap[j]]) {
- break;
- }
- mHeap[i] = mHeap[j];
- i = j;
- }
- mHeap[i] = (INT16)k;
- }
- STATIC
- VOID
- MakeCode (
- IN INT32 n,
- IN UINT8 Len[],
- OUT UINT16 Code[]
- )
- /*++
- Routine Description:
- Assign code to each symbol based on the code length array
- Arguments:
- n - number of symbols
- Len - the code length array
- Code - stores codes for each symbol
- Returns: (VOID)
- --*/
- {
- INT32 i;
- UINT16 Start[18];
- Start[1] = 0;
- for (i = 1; i <= 16; i++) {
- Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1);
- }
- for (i = 0; i < n; i++) {
- Code[i] = Start[Len[i]]++;
- }
- }
- STATIC
- INT32
- MakeTree (
- IN INT32 NParm,
- IN UINT16 FreqParm[],
- OUT UINT8 LenParm[],
- OUT UINT16 CodeParm[]
- )
- /*++
- Routine Description:
- Generates Huffman codes given a frequency distribution of symbols
- Arguments:
- NParm - number of symbols
- FreqParm - frequency of each symbol
- LenParm - code length for each symbol
- CodeParm - code for each symbol
- Returns:
- Root of the Huffman tree.
- --*/
- {
- INT32 i, j, k, Avail;
- //
- // make tree, calculate len[], return root
- //
- mN = NParm;
- mFreq = FreqParm;
- mLen = LenParm;
- Avail = mN;
- mHeapSize = 0;
- mHeap[1] = 0;
- for (i = 0; i < mN; i++) {
- mLen[i] = 0;
- if (mFreq[i]) {
- mHeap[++mHeapSize] = (INT16)i;
- }
- }
- if (mHeapSize < 2) {
- CodeParm[mHeap[1]] = 0;
- return mHeap[1];
- }
- for (i = mHeapSize / 2; i >= 1; i--) {
- //
- // make priority queue
- //
- DownHeap(i);
- }
- mSortPtr = CodeParm;
- do {
- i = mHeap[1];
- if (i < mN) {
- *mSortPtr++ = (UINT16)i;
- }
- mHeap[1] = mHeap[mHeapSize--];
- DownHeap(1);
- j = mHeap[1];
- if (j < mN) {
- *mSortPtr++ = (UINT16)j;
- }
- k = Avail++;
- mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]);
- mHeap[1] = (INT16)k;
- DownHeap(1);
- mLeft[k] = (UINT16)i;
- mRight[k] = (UINT16)j;
- } while (mHeapSize > 1);
- mSortPtr = CodeParm;
- MakeLen(k);
- MakeCode(NParm, LenParm, CodeParm);
- //
- // return root
- //
- return k;
- }
|