Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
InflaterManaged.cs
Go to the documentation of this file.
2
3internal sealed class InflaterManaged
4{
5 private static readonly byte[] s_extraLengthBits = new byte[29]
6 {
7 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
8 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
9 4, 4, 4, 4, 5, 5, 5, 5, 16
10 };
11
12 private static readonly int[] s_lengthBase = new int[29]
13 {
14 3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
15 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
16 67, 83, 99, 115, 131, 163, 195, 227, 3
17 };
18
19 private static readonly int[] s_distanceBasePosition = new int[32]
20 {
21 1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
22 33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
23 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
24 32769, 49153
25 };
26
27 private static readonly byte[] s_codeOrder = new byte[19]
28 {
29 16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
30 11, 4, 12, 3, 13, 2, 14, 1, 15
31 };
32
33 private static readonly byte[] s_staticDistanceTreeTable = new byte[32]
34 {
35 0, 16, 8, 24, 4, 20, 12, 28, 2, 18,
36 10, 26, 6, 22, 14, 30, 1, 17, 9, 25,
37 5, 21, 13, 29, 3, 19, 11, 27, 7, 23,
38 15, 31
39 };
40
41 private readonly OutputWindow _output;
42
43 private readonly InputBuffer _input;
44
46
48
50
51 private int _bfinal;
52
54
55 private readonly byte[] _blockLengthBuffer = new byte[4];
56
57 private int _blockLength;
58
59 private int _length;
60
61 private int _distanceCode;
62
63 private int _extraBits;
64
65 private int _loopCounter;
66
68
69 private int _distanceCodeCount;
70
72
73 private int _codeArraySize;
74
75 private int _lengthCode;
76
77 private readonly byte[] _codeList;
78
79 private readonly byte[] _codeLengthTreeCodeLength;
80
81 private readonly bool _deflate64;
82
84
85 private readonly long _uncompressedSize;
86
88
89 internal InflaterManaged(bool deflate64, long uncompressedSize)
90 {
91 _output = new OutputWindow();
92 _input = new InputBuffer();
93 _codeList = new byte[320];
94 _codeLengthTreeCodeLength = new byte[19];
95 _deflate64 = deflate64;
96 _uncompressedSize = uncompressedSize;
97 _state = InflaterState.ReadingBFinal;
98 }
99
100 public void SetInput(byte[] inputBytes, int offset, int length)
101 {
102 _input.SetInput(inputBytes, offset, length);
103 }
104
105 public bool Finished()
106 {
107 if (_state != InflaterState.Done)
108 {
109 return _state == InflaterState.VerifyingFooter;
110 }
111 return true;
112 }
113
115 {
116 int num = 0;
117 do
118 {
119 int num2 = 0;
120 if (_uncompressedSize == -1)
121 {
122 num2 = _output.CopyTo(bytes);
123 }
125 {
126 bytes = bytes.Slice(0, (int)Math.Min(bytes.Length, _uncompressedSize - _currentInflatedCount));
127 num2 = _output.CopyTo(bytes);
128 _currentInflatedCount += num2;
129 }
130 else
131 {
132 _state = InflaterState.Done;
134 }
135 if (num2 > 0)
136 {
137 bytes = bytes.Slice(num2, bytes.Length - num2);
138 num += num2;
139 }
140 }
141 while (!bytes.IsEmpty && !Finished() && Decode());
142 return num;
143 }
144
145 private bool Decode()
146 {
147 bool end_of_block = false;
148 bool flag = false;
149 if (Finished())
150 {
151 return true;
152 }
153 if (_state == InflaterState.ReadingBFinal)
154 {
156 {
157 return false;
158 }
160 _state = InflaterState.ReadingBType;
161 }
162 if (_state == InflaterState.ReadingBType)
163 {
165 {
166 _state = InflaterState.ReadingBType;
167 return false;
168 }
170 if (_blockType == BlockType.Dynamic)
171 {
172 _state = InflaterState.ReadingNumLitCodes;
173 }
174 else if (_blockType == BlockType.Static)
175 {
178 _state = InflaterState.DecodeTop;
179 }
180 else
181 {
182 if (_blockType != 0)
183 {
185 }
186 _state = InflaterState.UncompressedAligning;
187 }
188 }
189 if (_blockType == BlockType.Dynamic)
190 {
191 flag = ((_state >= InflaterState.DecodeTop) ? DecodeBlock(out end_of_block) : DecodeDynamicBlockHeader());
192 }
193 else if (_blockType == BlockType.Static)
194 {
195 flag = DecodeBlock(out end_of_block);
196 }
197 else
198 {
199 if (_blockType != 0)
200 {
202 }
203 flag = DecodeUncompressedBlock(out end_of_block);
204 }
205 if (end_of_block && _bfinal != 0)
206 {
207 _state = InflaterState.Done;
208 }
209 return flag;
210 }
211
212 private bool DecodeUncompressedBlock(out bool end_of_block)
213 {
214 end_of_block = false;
215 while (true)
216 {
217 switch (_state)
218 {
219 case InflaterState.UncompressedAligning:
221 _state = InflaterState.UncompressedByte1;
222 goto case InflaterState.UncompressedByte1;
223 case InflaterState.UncompressedByte1:
224 case InflaterState.UncompressedByte2:
225 case InflaterState.UncompressedByte3:
226 case InflaterState.UncompressedByte4:
227 {
228 int bits = _input.GetBits(8);
229 if (bits < 0)
230 {
231 return false;
232 }
233 _blockLengthBuffer[(int)(_state - 16)] = (byte)bits;
234 if (_state == InflaterState.UncompressedByte4)
235 {
237 int num2 = _blockLengthBuffer[2] + _blockLengthBuffer[3] * 256;
238 if ((ushort)_blockLength != (ushort)(~num2))
239 {
241 }
242 }
243 break;
244 }
245 case InflaterState.DecodingUncompressed:
246 {
248 _blockLength -= num;
249 if (_blockLength == 0)
250 {
251 _state = InflaterState.ReadingBFinal;
252 end_of_block = true;
253 return true;
254 }
255 if (_output.FreeBytes == 0)
256 {
257 return true;
258 }
259 return false;
260 }
261 default:
263 }
264 _state++;
265 }
266 }
267
268 private bool DecodeBlock(out bool end_of_block_code_seen)
269 {
270 end_of_block_code_seen = false;
271 int num = _output.FreeBytes;
272 while (num > 65536)
273 {
274 switch (_state)
275 {
276 case InflaterState.DecodeTop:
277 {
278 int nextSymbol = _literalLengthTree.GetNextSymbol(_input);
279 if (nextSymbol < 0)
280 {
281 return false;
282 }
283 if (nextSymbol < 256)
284 {
285 _output.Write((byte)nextSymbol);
286 num--;
287 break;
288 }
289 if (nextSymbol == 256)
290 {
291 end_of_block_code_seen = true;
292 _state = InflaterState.ReadingBFinal;
293 return true;
294 }
295 nextSymbol -= 257;
296 if (nextSymbol < 8)
297 {
298 nextSymbol += 3;
299 _extraBits = 0;
300 }
301 else if (!_deflate64 && nextSymbol == 28)
302 {
303 nextSymbol = 258;
304 _extraBits = 0;
305 }
306 else
307 {
308 if (nextSymbol < 0 || nextSymbol >= s_extraLengthBits.Length)
309 {
311 }
312 _extraBits = s_extraLengthBits[nextSymbol];
313 }
314 _length = nextSymbol;
315 goto case InflaterState.HaveInitialLength;
316 }
317 case InflaterState.HaveInitialLength:
318 if (_extraBits > 0)
319 {
320 _state = InflaterState.HaveInitialLength;
321 int bits2 = _input.GetBits(_extraBits);
322 if (bits2 < 0)
323 {
324 return false;
325 }
326 if (_length < 0 || _length >= s_lengthBase.Length)
327 {
329 }
330 _length = s_lengthBase[_length] + bits2;
331 }
332 _state = InflaterState.HaveFullLength;
333 goto case InflaterState.HaveFullLength;
334 case InflaterState.HaveFullLength:
335 if (_blockType == BlockType.Dynamic)
336 {
338 }
339 else
340 {
342 if (_distanceCode >= 0)
343 {
345 }
346 }
347 if (_distanceCode < 0)
348 {
349 return false;
350 }
351 _state = InflaterState.HaveDistCode;
352 goto case InflaterState.HaveDistCode;
353 case InflaterState.HaveDistCode:
354 {
355 int distance;
356 if (_distanceCode > 3)
357 {
358 _extraBits = _distanceCode - 2 >> 1;
359 int bits = _input.GetBits(_extraBits);
360 if (bits < 0)
361 {
362 return false;
363 }
364 distance = s_distanceBasePosition[_distanceCode] + bits;
365 }
366 else
367 {
368 distance = _distanceCode + 1;
369 }
371 num -= _length;
372 _state = InflaterState.DecodeTop;
373 break;
374 }
375 default:
377 }
378 }
379 return true;
380 }
381
383 {
384 switch (_state)
385 {
386 case InflaterState.ReadingNumLitCodes:
389 {
390 return false;
391 }
393 _state = InflaterState.ReadingNumDistCodes;
394 goto case InflaterState.ReadingNumDistCodes;
395 case InflaterState.ReadingNumDistCodes:
397 if (_distanceCodeCount < 0)
398 {
399 return false;
400 }
402 _state = InflaterState.ReadingNumCodeLengthCodes;
403 goto case InflaterState.ReadingNumCodeLengthCodes;
404 case InflaterState.ReadingNumCodeLengthCodes:
406 if (_codeLengthCodeCount < 0)
407 {
408 return false;
409 }
411 _loopCounter = 0;
412 _state = InflaterState.ReadingCodeLengthCodes;
413 goto case InflaterState.ReadingCodeLengthCodes;
414 case InflaterState.ReadingCodeLengthCodes:
415 {
417 {
418 int bits = _input.GetBits(3);
419 if (bits < 0)
420 {
421 return false;
422 }
424 _loopCounter++;
425 }
426 for (int l = _codeLengthCodeCount; l < s_codeOrder.Length; l++)
427 {
429 }
432 _loopCounter = 0;
433 _state = InflaterState.ReadingTreeCodesBefore;
434 goto case InflaterState.ReadingTreeCodesBefore;
435 }
436 case InflaterState.ReadingTreeCodesBefore:
437 case InflaterState.ReadingTreeCodesAfter:
438 {
440 {
441 if (_state == InflaterState.ReadingTreeCodesBefore && (_lengthCode = _codeLengthTree.GetNextSymbol(_input)) < 0)
442 {
443 return false;
444 }
445 if (_lengthCode <= 15)
446 {
448 }
449 else if (_lengthCode == 16)
450 {
452 {
453 _state = InflaterState.ReadingTreeCodesAfter;
454 return false;
455 }
456 if (_loopCounter == 0)
457 {
458 throw new InvalidDataException();
459 }
460 byte b = _codeList[_loopCounter - 1];
461 int num = _input.GetBits(2) + 3;
462 if (_loopCounter + num > _codeArraySize)
463 {
464 throw new InvalidDataException();
465 }
466 for (int i = 0; i < num; i++)
467 {
468 _codeList[_loopCounter++] = b;
469 }
470 }
471 else if (_lengthCode == 17)
472 {
474 {
475 _state = InflaterState.ReadingTreeCodesAfter;
476 return false;
477 }
478 int num = _input.GetBits(3) + 3;
479 if (_loopCounter + num > _codeArraySize)
480 {
481 throw new InvalidDataException();
482 }
483 for (int j = 0; j < num; j++)
484 {
485 _codeList[_loopCounter++] = 0;
486 }
487 }
488 else
489 {
491 {
492 _state = InflaterState.ReadingTreeCodesAfter;
493 return false;
494 }
495 int num = _input.GetBits(7) + 11;
496 if (_loopCounter + num > _codeArraySize)
497 {
498 throw new InvalidDataException();
499 }
500 for (int k = 0; k < num; k++)
501 {
502 _codeList[_loopCounter++] = 0;
503 }
504 }
505 _state = InflaterState.ReadingTreeCodesBefore;
506 }
507 byte[] array = new byte[288];
508 byte[] array2 = new byte[32];
511 if (array[256] == 0)
512 {
513 throw new InvalidDataException();
514 }
516 _distanceTree = new HuffmanTree(array2);
517 _state = InflaterState.DecodeTop;
518 return true;
519 }
520 default:
522 }
523 }
524
525 public void Dispose()
526 {
527 }
528}
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
int GetNextSymbol(InputBuffer input)
static HuffmanTree StaticDistanceTree
static HuffmanTree StaticLiteralLengthTree
static readonly byte[] s_staticDistanceTreeTable
void SetInput(byte[] inputBytes, int offset, int length)
static readonly byte[] s_extraLengthBits
bool DecodeUncompressedBlock(out bool end_of_block)
static readonly int[] s_distanceBasePosition
bool DecodeBlock(out bool end_of_block_code_seen)
InflaterManaged(bool deflate64, long uncompressedSize)
void SetInput(Memory< byte > buffer)
void WriteLengthDistance(int length, int distance)
int CopyTo(Span< byte > output)
int CopyFrom(InputBuffer input, int length)
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static string UnknownBlockType
Definition SR.cs:36
static string UnknownState
Definition SR.cs:38
static string GenericInvalidData
Definition SR.cs:20
static string InvalidBlockLength
Definition SR.cs:24
Definition SR.cs:7