1 using System;
2 
3 namespace 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 
SetStream(System.IO.Stream stream)18 		public void SetStream(System.IO.Stream stream)
19 		{
20 			Stream = stream;
21 		}
22 
ReleaseStream()23 		public void ReleaseStream()
24 		{
25 			Stream = null;
26 		}
27 
Init()28 		public void Init()
29 		{
30 			StartPosition = Stream.Position;
31 
32 			Low = 0;
33 			Range = 0xFFFFFFFF;
34 			_cacheSize = 1;
35 			_cache = 0;
36 		}
37 
FlushData()38 		public void FlushData()
39 		{
40 			for (int i = 0; i < 5; i++)
41 				ShiftLow();
42 		}
43 
FlushStream()44 		public void FlushStream()
45 		{
46 			Stream.Flush();
47 		}
48 
CloseStream()49 		public void CloseStream()
50 		{
51 			Stream.Close();
52 		}
53 
Encode(uint start, uint size, uint total)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 
ShiftLow()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 
EncodeDirectBits(uint v, int numTotalBits)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 
EncodeBit(uint size0, int numTotalBits, uint symbol)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 
GetProcessedSizeAdd()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 
Init(System.IO.Stream stream)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 
ReleaseStream()141 		public void ReleaseStream()
142 		{
143 			// Stream.ReleaseStream();
144 			Stream = null;
145 		}
146 
CloseStream()147 		public void CloseStream()
148 		{
149 			Stream.Close();
150 		}
151 
Normalize()152 		public void Normalize()
153 		{
154 			while (Range < kTopValue)
155 			{
156 				Code = (Code << 8) | (byte)Stream.ReadByte();
157 				Range <<= 8;
158 			}
159 		}
160 
Normalize2()161 		public void Normalize2()
162 		{
163 			if (Range < kTopValue)
164 			{
165 				Code = (Code << 8) | (byte)Stream.ReadByte();
166 				Range <<= 8;
167 			}
168 		}
169 
GetThreshold(uint total)170 		public uint GetThreshold(uint total)
171 		{
172 			return Code / (Range /= total);
173 		}
174 
Decode(uint start, uint size, uint total)175 		public void Decode(uint start, uint size, uint total)
176 		{
177 			Code -= start * Range;
178 			Range *= size;
179 			Normalize();
180 		}
181 
DecodeDirectBits(int numTotalBits)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 
DecodeBit(uint size0, int numTotalBits)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