123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /* Copyright (C) Teemu Suutari */
- #ifndef DYNAMICHUFFMANDECODER_HPP
- #define DYNAMICHUFFMANDECODER_HPP
- #include <cstddef>
- #include <cstdint>
- // For exception
- #include "Decompressor.hpp"
- namespace ancient::internal
- {
- template<uint32_t maxCount>
- class DynamicHuffmanDecoder
- {
- public:
- DynamicHuffmanDecoder(uint32_t initialCount=maxCount) :
- _initialCount(initialCount)
- {
- if (_initialCount>maxCount) throw Decompressor::DecompressionError();
- reset();
- }
- ~DynamicHuffmanDecoder()
- {
- // nothing needed
- }
- void reset()
- {
- _count=_initialCount;
- if (!_count) return;
- for (uint32_t i=0;i<_count;i++)
- {
- _nodes[i].frequency=1;
- _nodes[i].index=i+(maxCount-_count)*2;
- _nodes[i].parent=maxCount*2-_count+(i>>1);
- _nodes[i].leaves[0]=0;
- _nodes[i].leaves[1]=0;
- _codeMap[i+(maxCount-_count)*2]=i;
- }
- for (uint32_t i=maxCount*2-_count,j=0;i<maxCount*2-1;i++,j+=2)
- {
- uint32_t l=(j>=_count)?j+(maxCount-_count)*2:j;
- uint32_t r=(j+1>=_count)?j+1+(maxCount-_count)*2:(j+1);
- _nodes[i].frequency=_nodes[l].frequency+_nodes[r].frequency;
- _nodes[i].index=i;
- _nodes[i].parent=maxCount+(i>>1);
- _nodes[i].leaves[0]=l;
- _nodes[i].leaves[1]=r;
- _codeMap[i]=i;
- }
- }
- template<typename F>
- uint32_t decode(F bitReader) const
- {
- if (!_count) throw Decompressor::DecompressionError();
- if (_count==1) return 0;
- uint32_t code=maxCount*2-2;
- while (code>=maxCount)
- code=_nodes[code].leaves[bitReader()?1:0];
- return code;
- }
- void update(uint32_t code)
- {
- if (code>=_count) throw Decompressor::DecompressionError();
- // this is a bug in LH2. Nobody else uses this codepath, so we can let it be...
- if (_count==1)
- {
- _nodes[0].frequency=1;
- return;
- }
- while (code!=maxCount*2-2)
- {
- _nodes[code].frequency++;
- uint32_t index=_nodes[code].index;
- uint32_t destIndex=index;
- uint32_t freq=_nodes[code].frequency;
- while (destIndex!=maxCount*2-2 && freq>_nodes[_codeMap[destIndex+1]].frequency) destIndex++;
- if (index!=destIndex)
- {
- auto getParentLeaf=[&](uint32_t currentCode)->uint32_t&
- {
- Node &parent=_nodes[_nodes[currentCode].parent];
- return parent.leaves[(parent.leaves[0]==currentCode)?0:1];
- };
- uint32_t destCode=_codeMap[destIndex];
- std::swap(_nodes[code].index,_nodes[destCode].index);
- std::swap(_codeMap[index],_codeMap[destIndex]);
- std::swap(getParentLeaf(code),getParentLeaf(destCode));
- std::swap(_nodes[code].parent,_nodes[destCode].parent);
- }
- code=_nodes[code].parent;
- }
- _nodes[code].frequency++;
- }
- // halve the frequencies rounding upwards
- void halve()
- {
- if (!_count) return;
- else if (_count==1)
- {
- _nodes[0].frequency=(_nodes[0].frequency+1)>>1;
- return;
- }
- for (uint32_t i=(maxCount-_count)*2,j=(maxCount-_count)*2;i<maxCount*2-1&&j<maxCount*2-_count;i++)
- if (_codeMap[i]<maxCount) _nodes[_codeMap[i]].index=j++;
- for (uint32_t i=0;i<_count;i++)
- {
- _nodes[i].frequency=(_nodes[i].frequency+1)>>1;
- _nodes[i].parent=maxCount+(_nodes[i].index>>1);
- _codeMap[_nodes[i].index]=i;
- }
- for (uint32_t i=maxCount*2-_count,j=(maxCount-_count)*2;i<maxCount*2-1;i++,j+=2)
- {
- uint32_t l=_codeMap[j];
- uint32_t r=_codeMap[j+1];
- uint32_t freq=_nodes[l].frequency+_nodes[r].frequency;
- _nodes[i].frequency=freq;
- _nodes[i].index=i;
- _nodes[i].parent=maxCount+(i>>1);
- _nodes[i].leaves[0]=l;
- _nodes[i].leaves[1]=r;
- _codeMap[i]=i;
- for (uint32_t k=i;freq<_nodes[_codeMap[k-1]].frequency;k--)
- {
- uint32_t &code=_codeMap[k];
- uint32_t &destCode=_codeMap[k-1];
- std::swap(_nodes[code].index,_nodes[destCode].index);
- std::swap(_nodes[code].parent,_nodes[destCode].parent);
- std::swap(code,destCode);
- }
- }
- }
- // Defined as in LH2
- void addCode()
- {
- if (_count>=maxCount) throw Decompressor::DecompressionError();
- uint32_t newIndex=(maxCount-_count-1)*2;
- if (!_count)
- {
- _nodes[0].frequency=0;
- _nodes[0].index=newIndex-1;
- _nodes[0].parent=maxCount*2-2;
- _nodes[0].leaves[0]=0;
- _nodes[0].leaves[1]=0;
- _codeMap[newIndex-1]=0;
- _count++;
- } else {
- _nodes[_count].frequency=0;
- _nodes[_count].index=newIndex;
- _nodes[_count].parent=maxCount*2-_count-1;
- _nodes[_count].leaves[0]=0;
- _nodes[_count].leaves[1]=0;
- _codeMap[newIndex]=_count;
- uint32_t insertIndex=newIndex+2;
- uint32_t repNode;
- uint32_t parentNode;
- uint32_t insertNode=maxCount*2-_count-1;
- if (_count>1)
- {
- _codeMap[insertIndex-1]=_codeMap[insertIndex];
- _nodes[_codeMap[insertIndex-1]].index--;
- repNode=_codeMap[(maxCount-_count)*2];
- parentNode=_nodes[repNode].parent;
- _nodes[parentNode].leaves[(_nodes[parentNode].leaves[0]==repNode)?0:1]=insertNode;
- _nodes[repNode].parent=insertNode;
- } else {
- repNode=0;
- parentNode=maxCount*2-1;
- }
- _nodes[insertNode].frequency=_nodes[repNode].frequency;
- _nodes[insertNode].index=insertIndex;
- _nodes[insertNode].parent=parentNode;
- _nodes[insertNode].leaves[0]=_count;
- _nodes[insertNode].leaves[1]=repNode;
- _codeMap[insertIndex]=insertNode;
- Node &parent=_nodes[parentNode];
- if (_count>1 && _nodes[parent.leaves[0]].index>_nodes[parent.leaves[1]].index)
- std::swap(parent.leaves[0],parent.leaves[1]);
- _count++;
- }
- }
- uint32_t getMaxFrequency() const
- {
- return _nodes[maxCount*2-2].frequency;
- }
- private:
- struct Node
- {
- uint32_t frequency;
- uint32_t index;
- uint32_t parent;
- uint32_t leaves[2];
- };
- uint32_t _initialCount;
- uint32_t _count;
- Node _nodes[maxCount*2-1];
- uint32_t _codeMap[maxCount*2-1];
- };
- }
- #endif
|