Rev 4 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "literalhufftree.h"#include <math.h>#include <crtdbg.h>#include <stdio.h>#include "ByteReader.h"#include "Macros.h"//#include "WarnOff.h"extern bool g_bError;LiteralHuffTree::LiteralHuffTree(void){ZERO( m_dwOccurr );ZERO( m_tree );m_ucTreeItems = 0;}LiteralHuffTree::~LiteralHuffTree(void){}//// Purpose:// A root procedure//BOOL LiteralHuffTree::Generate( PBYTE buff, DWORD cb ){if ( !buff || !cb )return FALSE; // ERRGetByteOccurrences( buff, cb );BuildInternalTree();LinkTreeElements();GenerateBitSequences();return TRUE; // OK}//// Purpose:// A root procedure//BOOL LiteralHuffTree::GenerateWithOccurrences(){BuildInternalTree();LinkTreeElements();return GenerateBitSequences();}//// Purpose:// A root procedure//BOOL LiteralHuffTree::GenerateAdaptiveModel(){//// init the occurrences with 1 for each symbol in the alphabet//for ( UINT i = 0; i < ARRAY_ITEMS(m_dwOccurr); i++ )m_dwOccurr[i] = 1;//// generate the tree, ...//BuildInternalTree();LinkTreeElements();GenerateBitSequences();return TRUE; // OK}//// Purpose:// Scan the specified buffer and log the occurrence// of each byte//void LiteralHuffTree::GetByteOccurrences( PBYTE pby, DWORD cb ){ZERO( m_dwOccurr );while( cb ){m_dwOccurr[ *pby ]++;--cb;++pby;}return;}//// Purpose:// Transfer the occurrences array into m_tree items//void LiteralHuffTree::BuildInternalTree(){ZERO( m_tree );for ( UINT u = 0; u < 256; u++ ){m_tree[u].id = u;m_tree[u].dwcOccurr = m_dwOccurr[u];m_tree[u].dwRightId = (DWORD)-1; // indicates the end of a branchm_tree[u].dwLeftId = (DWORD)-1; // indicates the end of a branch}m_ucTreeItems = 256;return;}//// Purpose:// Builds the Huffman tree linkage by adding branch items in the chain//// Remarks:// (biggest probability first)//void LiteralHuffTree::LinkTreeElements(){PLHT_ITEM pitem1, pitem2, pitem, pLastLink;LHT_ITEM branch, pseudoitem;if ( !m_ucTreeItems )return; // no items in our treepseudoitem.dwcOccurr = MAXDWORD;pLastLink = NULL;for (;;){//// search unlinked items with the lowest occurrences//pitem1 = NULL;pitem2 = NULL;pitem1 = &pseudoitem;UINT u;for ( u = 0; u < m_ucTreeItems; u++ ){pitem = &m_tree[u];if ( !pitem->bLinked && pitem->dwcOccurr > 0 && pitem->dwcOccurr < pitem1->dwcOccurr )pitem1 = pitem;}pitem1->bLinked = TRUE; // mark the found items linked !pitem2 = &pseudoitem;for ( u = 0; u < m_ucTreeItems; u++ ){pitem = &m_tree[u];if ( !pitem->bLinked && pitem->dwcOccurr > 0 && pitem->dwcOccurr < pitem2->dwcOccurr)pitem2 = pitem;}pitem2->bLinked = TRUE; // mark the found items linked !//// did we link all items ?//if ( pitem1->dwcOccurr == MAXDWORD || pitem2->dwcOccurr == MAXDWORD ){if ( pLastLink )pLastLink->dwDadId = MAXDWORD; // indicates root itembreak; // exit for(;;) loop}_ASSERT( m_ucTreeItems < ARRAY_ITEMS(m_tree) );//// add a branch item linking the 2//ZERO( branch )branch.id = m_ucTreeItems;branch.bLinked = FALSE;branch.dwLeftId = pitem1->id;branch.dwRightId = pitem2->id;branch.dwcOccurr = pitem1->dwcOccurr + pitem2->dwcOccurr;pitem1->dwDadId = pitem2->dwDadId = branch.id;m_tree[ m_ucTreeItems++ ] = branch;pLastLink = &m_tree[ m_ucTreeItems - 1 ];}return;}//// Purpose:// Trace the tree for non-branch items to find out// their corresponding bit sequences//bool LiteralHuffTree::GenerateBitSequences(){PLHT_ITEM pitem, ptrace, ptrace2;DWORD cbitsBig = 0, cbitsSmall = 0xFF;for ( UINT u = 0; u < m_ucTreeItems; u++ ){pitem = &m_tree[u];if ( !pitem->dwcOccurr )continue; // this literal is never usedif ( pitem->dwLeftId == (DWORD)-1 && pitem->dwRightId == (DWORD)-1 ){//// handle a non-branch chain element//ptrace = pitem;while( ptrace->dwDadId != (DWORD)-1 ){ptrace2 = &m_tree[ ptrace->dwDadId ];if ( ptrace->id == ptrace2->dwRightId )pitem->dwSequence |= HT_RIGHT;elsepitem->dwSequence |= HT_LEFT;++pitem->bySequLen;pitem->dwSequence <<= 1;ptrace = ptrace2;}pitem->dwSequence >>= 1;/* if ( pitem->bySequLen >= 15 ){g_bError = true;return false;}*/}}return true;}//// Purpose:// Calculates the number of bits that eats to// biggest occurrence value in the set////DWORD LiteralHuffTree::GetBitCountForOccurrence(){DWORD dwMax = 0;// get the biggest occurrence valuefor ( UINT u = 0; u < 256; u++ )if ( m_tree[u].dwcOccurr > dwMax )dwMax = m_tree[u].dwcOccurr;// calculate how much bits we'll need to store this valuefloat f = (float)log((double)dwMax) / (float)log(2.0f);DWORD c = (DWORD)f;if ( (float)c < f ) // is f a decimal number ?c++;return c;}//// Purpose:// This routine returns the data field of the HT_ITEM structure// which is identified by reading bits form the ByteReader class//DWORD LiteralHuffTree::QueryLiteralByBitSequence( PByteReader reader ){PLHT_ITEM pitem;pitem = &m_tree[m_ucTreeItems - 1];while ( pitem->dwLeftId != -1 && pitem->dwRightId != -1 )switch( reader->ReadBit() ){case HT_LEFT:pitem = &m_tree[pitem->dwLeftId];break;case HT_RIGHT:pitem = &m_tree[pitem->dwRightId];break;}return pitem->id;}