diff options
Diffstat (limited to 'Build/source/utils/lzma-utils/src/sdk/7zip/Compress/RangeCoder/RangeCoder.h')
-rw-r--r-- | Build/source/utils/lzma-utils/src/sdk/7zip/Compress/RangeCoder/RangeCoder.h | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/Build/source/utils/lzma-utils/src/sdk/7zip/Compress/RangeCoder/RangeCoder.h b/Build/source/utils/lzma-utils/src/sdk/7zip/Compress/RangeCoder/RangeCoder.h new file mode 100644 index 00000000000..186ae8b0798 --- /dev/null +++ b/Build/source/utils/lzma-utils/src/sdk/7zip/Compress/RangeCoder/RangeCoder.h @@ -0,0 +1,240 @@ +// Compress/RangeCoder/RangeCoder.h + +#ifndef __COMPRESS_RANGECODER_H +#define __COMPRESS_RANGECODER_H + +#include "../../Common/InBuffer.h" +#include "../../Common/OutBuffer.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumTopBits = 24; +const UInt32 kTopValue = (1 << kNumTopBits); + +class CEncoder +{ + UInt32 _ffNum; + Byte _cache; +public: + UInt64 Low; + UInt32 Range; + COutBuffer Stream; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Low = 0; + Range = 0xFFFFFFFF; + _ffNum = 0; + _cache = 0; + } + + void FlushData() + { + // Low += 1; + for(int i = 0; i < 5; i++) + ShiftLow(); + } + + HRESULT FlushStream() { return Stream.Flush(); } + + void ReleaseStream() { Stream.ReleaseStream(); } + + void Encode(UInt32 start, UInt32 size, UInt32 total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + /* + void EncodeDirectBitsDiv(UInt32 value, UInt32 numTotalBits) + { + Low += value * (Range >>= numTotalBits); + Normalize(); + } + + void EncodeDirectBitsDiv2(UInt32 value, UInt32 numTotalBits) + { + if (numTotalBits <= kNumBottomBits) + EncodeDirectBitsDiv(value, numTotalBits); + else + { + EncodeDirectBitsDiv(value >> kNumBottomBits, (numTotalBits - kNumBottomBits)); + EncodeDirectBitsDiv(value & ((1 << kBottomValueBits) - 1), kNumBottomBits); + } + } + */ + void ShiftLow() + { + if (Low < (UInt32)0xFF000000 || UInt32(Low >> 32) == 1) + { + Stream.WriteByte(Byte(_cache + Byte(Low >> 32))); + for (;_ffNum != 0; _ffNum--) + Stream.WriteByte(Byte(0xFF + Byte(Low >> 32))); + _cache = Byte(UInt32(Low) >> 24); + } + else + _ffNum++; + Low = UInt32(Low) << 8; + } + + void EncodeDirectBits(UInt32 value, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((value >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _ffNum; } +}; + +class CDecoder +{ +public: + CInBuffer Stream; + UInt32 Range; + UInt32 Code; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | Stream.ReadByte(); + Range <<= 8; + } + } + + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Code = 0; + Range = 0xFFFFFFFF; + for(int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.ReadByte(); + } + + void ReleaseStream() { Stream.ReleaseStream(); } + + UInt32 GetThreshold(UInt32 total) + { + return (Code) / ( Range /= total); + } + + void Decode(UInt32 start, UInt32 size) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + /* + UInt32 DecodeDirectBitsDiv(UInt32 numTotalBits) + { + Range >>= numTotalBits; + UInt32 threshold = Code / Range; + Code -= threshold * Range; + + Normalize(); + return threshold; + } + + UInt32 DecodeDirectBitsDiv2(UInt32 numTotalBits) + { + if (numTotalBits <= kNumBottomBits) + return DecodeDirectBitsDiv(numTotalBits); + UInt32 result = DecodeDirectBitsDiv(numTotalBits - kNumBottomBits) << kNumBottomBits; + return (result | DecodeDirectBitsDiv(kNumBottomBits)); + } + */ + + UInt32 DecodeDirectBits(int numTotalBits) + { + UInt32 range = Range; + UInt32 code = Code; + UInt32 result = 0; + for (int i = numTotalBits; i != 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + UInt32 t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + UInt32 symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } +}; + +}} + +#endif |