#include "stdafx.h" #include "compressionhelper.h" CStaticCharCompressor::CStaticCharCompressor() { m_dwRootIndex=0xffffffff; } void CStaticCharCompressor::InitFromStatistics( const DWORD indwPriority[256] ) { std::multiset Sorter; m_Nodes.clear(); m_Nodes.reserve(256*2-1); for(DWORD i=0;i<256;i++) { m_Nodes.push_back( SNode((unsigned char)i) ); Sorter.insert( SPriIndex(i,indwPriority[i]+1) ); // +1 to ensure if we add two priorites the value is raising } // iterate through all nodes from lowest to highest priority for(;;) { DWORD dwIndex1,dwIndex2; DWORD dwPriority; // get element with lowest priorty { std::multiset::iterator top = Sorter.begin(); assert(top!=Sorter.end()); // cannot be because we always remove two and add one const SPriIndex &ref = *top; dwIndex1=ref.m_dwIndex; dwPriority=ref.m_dwPriority; Sorter.erase(top); } // get element with second lowest priorty { std::multiset::iterator top = Sorter.begin(); if(top==Sorter.end()) { m_dwRootIndex=dwIndex1; break; } const SPriIndex &ref = *top; dwIndex2=ref.m_dwIndex; dwPriority+=ref.m_dwPriority; Sorter.erase(top); } DWORD dwNextIndex = m_Nodes.size(); m_Nodes.push_back( SNode(dwIndex1,dwIndex2) ); Sorter.insert( SPriIndex(dwNextIndex,dwPriority) ); } // build m_CharToBit { for(DWORD i=0;i<256;i++) { bool bRet=GetCharFromBits_slow( (unsigned char)i, m_dwRootIndex, m_CharToBit[i] ); assert(bRet); // it must be there } } } bool CStaticCharCompressor::GetCharFromBits_slow( const unsigned char inVal, const DWORD indwIndex, SBitToChar &outDat ) { SNode &ref = m_Nodes[indwIndex]; if(ref.IsLeaf()) { if(ref.m_Value==inVal) return true; } else { outDat.m_BitCount++; assert(outDat.m_BitCount<16); outDat.m_Bitfield<<=1; // one outDat.m_Bitfield|=0x1; if(GetCharFromBits_slow(inVal,ref.m_dwIndexOne,outDat)) return true; // zero outDat.m_Bitfield&=~0x1; if(GetCharFromBits_slow(inVal,ref.m_dwIndexZero,outDat)) return true; outDat.m_Bitfield>>=1; outDat.m_BitCount--; } return false; } bool CStaticCharCompressor::Write( CStream &outStream, const unsigned char inChar ) { assert(m_dwRootIndex!=0xffffffff); // instance is not initialized SBitToChar &ref=m_CharToBit[inChar]; /* #ifdef _DEBUG CStream test; unsigned char cTest; test.WriteNumberInBits((DWORD)(ref.m_Bitfield),ref.m_BitCount); Read(test,cTest); assert(cTest==inChar); #endif */ for(DWORD i=0;i