Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/RangeCoder.h @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // Compress/RangeCoder.h3 #ifndef __COMPRESS_RANGE_CODER_H4 #define __COMPRESS_RANGE_CODER_H6 #include "../Common/InBuffer.h"7 #include "../Common/OutBuffer.h"9 namespace NCompress {10 namespace NRangeCoder {12 const int kNumTopBits = 24;13 const UInt32 kTopValue = (1 << kNumTopBits);15 class CEncoder16 {17 UInt32 _cacheSize;18 Byte _cache;19 public:20 UInt64 Low;21 UInt32 Range;22 COutBuffer Stream;23 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }25 void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }26 void Init()27 {28 Stream.Init();29 Low = 0;30 Range = 0xFFFFFFFF;31 _cacheSize = 1;32 _cache = 0;33 }35 void FlushData()36 {37 // Low += 1;38 for(int i = 0; i < 5; i++)39 ShiftLow();40 }42 HRESULT FlushStream() { return Stream.Flush(); }44 void ReleaseStream() { Stream.ReleaseStream(); }46 void Encode(UInt32 start, UInt32 size, UInt32 total)47 {48 Low += start * (Range /= total);49 Range *= size;50 while (Range < kTopValue)51 {52 Range <<= 8;53 ShiftLow();54 }55 }57 void ShiftLow()58 {59 if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)60 {61 Byte temp = _cache;62 do63 {64 Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));65 temp = 0xFF;66 }67 while(--_cacheSize != 0);68 _cache = (Byte)((UInt32)Low >> 24);69 }70 _cacheSize++;71 Low = (UInt32)Low << 8;72 }74 void EncodeDirectBits(UInt32 value, int numBits)75 {76 for (numBits--; numBits >= 0; numBits--)77 {78 Range >>= 1;79 Low += Range & (0 - ((value >> numBits) & 1));80 if (Range < kTopValue)81 {82 Range <<= 8;83 ShiftLow();84 }85 }86 }88 void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)89 {90 UInt32 newBound = (Range >> numTotalBits) * size0;91 if (symbol == 0)92 Range = newBound;93 else94 {95 Low += newBound;96 Range -= newBound;97 }98 while (Range < kTopValue)99 {100 Range <<= 8;101 ShiftLow();102 }103 }105 UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }106 };108 class CDecoder109 {110 public:111 CInBuffer Stream;112 UInt32 Range;113 UInt32 Code;114 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }116 void Normalize()117 {118 while (Range < kTopValue)119 {120 Code = (Code << 8) | Stream.ReadByte();121 Range <<= 8;122 }123 }125 void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }126 void Init()127 {128 Stream.Init();129 Code = 0;130 Range = 0xFFFFFFFF;131 for(int i = 0; i < 5; i++)132 Code = (Code << 8) | Stream.ReadByte();133 }135 void ReleaseStream() { Stream.ReleaseStream(); }137 UInt32 GetThreshold(UInt32 total)138 {139 return (Code) / ( Range /= total);140 }142 void Decode(UInt32 start, UInt32 size)143 {144 Code -= start * Range;145 Range *= size;146 Normalize();147 }149 UInt32 DecodeDirectBits(int numTotalBits)150 {151 UInt32 range = Range;152 UInt32 code = Code;153 UInt32 result = 0;154 for (int i = numTotalBits; i != 0; i--)155 {156 range >>= 1;157 /*158 result <<= 1;159 if (code >= range)160 {161 code -= range;162 result |= 1;163 }164 */165 UInt32 t = (code - range) >> 31;166 code -= range & (t - 1);167 result = (result << 1) | (1 - t);169 if (range < kTopValue)170 {171 code = (code << 8) | Stream.ReadByte();172 range <<= 8;173 }174 }175 Range = range;176 Code = code;177 return result;178 }180 UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)181 {182 UInt32 newBound = (Range >> numTotalBits) * size0;183 UInt32 symbol;184 if (Code < newBound)185 {186 symbol = 0;187 Range = newBound;188 }189 else190 {191 symbol = 1;192 Code -= newBound;193 Range -= newBound;194 }195 Normalize();196 return symbol;197 }199 UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }200 };202 }}204 #endif