1using System; 2 3namespace SevenZip.Compression.RangeCoder 4{ 5 class Encoder 6 { 7 public const uint kTopValue = (1 << 24); 8 9 System.IO.Stream Stream; 10 11 public UInt64 Low; 12 public uint Range; 13 uint _cacheSize; 14 byte _cache; 15 16 long StartPosition; 17 18 public void SetStream(System.IO.Stream stream) 19 { 20 Stream = stream; 21 } 22 23 public void ReleaseStream() 24 { 25 Stream = null; 26 } 27 28 public void Init() 29 { 30 StartPosition = Stream.Position; 31 32 Low = 0; 33 Range = 0xFFFFFFFF; 34 _cacheSize = 1; 35 _cache = 0; 36 } 37 38 public void FlushData() 39 { 40 for (int i = 0; i < 5; i++) 41 ShiftLow(); 42 } 43 44 public void FlushStream() 45 { 46 Stream.Flush(); 47 } 48 49 public void CloseStream() 50 { 51 Stream.Close(); 52 } 53 54 public void Encode(uint start, uint size, uint total) 55 { 56 Low += start * (Range /= total); 57 Range *= size; 58 while (Range < kTopValue) 59 { 60 Range <<= 8; 61 ShiftLow(); 62 } 63 } 64 65 public void ShiftLow() 66 { 67 if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) 68 { 69 byte temp = _cache; 70 do 71 { 72 Stream.WriteByte((byte)(temp + (Low >> 32))); 73 temp = 0xFF; 74 } 75 while (--_cacheSize != 0); 76 _cache = (byte)(((uint)Low) >> 24); 77 } 78 _cacheSize++; 79 Low = ((uint)Low) << 8; 80 } 81 82 public void EncodeDirectBits(uint v, int numTotalBits) 83 { 84 for (int i = numTotalBits - 1; i >= 0; i--) 85 { 86 Range >>= 1; 87 if (((v >> i) & 1) == 1) 88 Low += Range; 89 if (Range < kTopValue) 90 { 91 Range <<= 8; 92 ShiftLow(); 93 } 94 } 95 } 96 97 public void EncodeBit(uint size0, int numTotalBits, uint symbol) 98 { 99 uint newBound = (Range >> numTotalBits) * size0; 100 if (symbol == 0) 101 Range = newBound; 102 else 103 { 104 Low += newBound; 105 Range -= newBound; 106 } 107 while (Range < kTopValue) 108 { 109 Range <<= 8; 110 ShiftLow(); 111 } 112 } 113 114 public long GetProcessedSizeAdd() 115 { 116 return _cacheSize + 117 Stream.Position - StartPosition + 4; 118 // (long)Stream.GetProcessedSize(); 119 } 120 } 121 122 class Decoder 123 { 124 public const uint kTopValue = (1 << 24); 125 public uint Range; 126 public uint Code; 127 // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); 128 public System.IO.Stream Stream; 129 130 public void Init(System.IO.Stream stream) 131 { 132 // Stream.Init(stream); 133 Stream = stream; 134 135 Code = 0; 136 Range = 0xFFFFFFFF; 137 for (int i = 0; i < 5; i++) 138 Code = (Code << 8) | (byte)Stream.ReadByte(); 139 } 140 141 public void ReleaseStream() 142 { 143 // Stream.ReleaseStream(); 144 Stream = null; 145 } 146 147 public void CloseStream() 148 { 149 Stream.Close(); 150 } 151 152 public void Normalize() 153 { 154 while (Range < kTopValue) 155 { 156 Code = (Code << 8) | (byte)Stream.ReadByte(); 157 Range <<= 8; 158 } 159 } 160 161 public void Normalize2() 162 { 163 if (Range < kTopValue) 164 { 165 Code = (Code << 8) | (byte)Stream.ReadByte(); 166 Range <<= 8; 167 } 168 } 169 170 public uint GetThreshold(uint total) 171 { 172 return Code / (Range /= total); 173 } 174 175 public void Decode(uint start, uint size, uint total) 176 { 177 Code -= start * Range; 178 Range *= size; 179 Normalize(); 180 } 181 182 public uint DecodeDirectBits(int numTotalBits) 183 { 184 uint range = Range; 185 uint code = Code; 186 uint result = 0; 187 for (int i = numTotalBits; i > 0; i--) 188 { 189 range >>= 1; 190 /* 191 result <<= 1; 192 if (code >= range) 193 { 194 code -= range; 195 result |= 1; 196 } 197 */ 198 uint t = (code - range) >> 31; 199 code -= range & (t - 1); 200 result = (result << 1) | (1 - t); 201 202 if (range < kTopValue) 203 { 204 code = (code << 8) | (byte)Stream.ReadByte(); 205 range <<= 8; 206 } 207 } 208 Range = range; 209 Code = code; 210 return result; 211 } 212 213 public uint DecodeBit(uint size0, int numTotalBits) 214 { 215 uint newBound = (Range >> numTotalBits) * size0; 216 uint symbol; 217 if (Code < newBound) 218 { 219 symbol = 0; 220 Range = newBound; 221 } 222 else 223 { 224 symbol = 1; 225 Code -= newBound; 226 Range -= newBound; 227 } 228 Normalize(); 229 return symbol; 230 } 231 232 // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } 233 } 234} 235