Upload 2.0.2
[physicsfs] / lzma / CS / 7zip / Compress / RangeCoder / RangeCoder.cs
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
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 }