private bool ReadFilter(BitInput Inp, UnpackFilter Filter) { if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 16) { if (!UnpReadBuf()) { return(false); } } Filter.BlockStart = ReadFilterData(Inp); Filter.BlockLength = ReadFilterData(Inp); if (Filter.BlockLength > MAX_FILTER_BLOCK_SIZE) { Filter.BlockLength = 0; } Filter.Type = (byte)(Inp.fgetbits() >> 13); Inp.faddbits(3); if (Filter.Type == FILTER_DELTA) { Filter.Channels = (byte)((Inp.fgetbits() >> 11) + 1); Inp.faddbits(5); } return(true); }
private bool ReadBlockHeader(BitInput Inp, ref UnpackBlockHeader Header) { Header.HeaderSize = 0; if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 7) { if (!UnpReadBuf()) { return(false); } } Inp.faddbits((uint)((8 - Inp.InBit) & 7)); byte BlockFlags = (byte)(Inp.fgetbits() >> 8); Inp.faddbits(8); uint ByteCount = (uint)(((BlockFlags >> 3) & 3) + 1); // Block size byte count. if (ByteCount == 4) { return(false); } Header.HeaderSize = (int)(2 + ByteCount); Header.BlockBitSize = (BlockFlags & 7) + 1; byte SavedCheckSum = (byte)(Inp.fgetbits() >> 8); Inp.faddbits(8); int BlockSize = 0; for (uint I = 0; I < ByteCount; I++) { BlockSize += (int)((Inp.fgetbits() >> 8) << (int)(I * 8)); Inp.addbits(8); } Header.BlockSize = BlockSize; byte CheckSum = (byte)(0x5a ^ BlockFlags ^ BlockSize ^ (BlockSize >> 8) ^ (BlockSize >> 16)); if (CheckSum != SavedCheckSum) { return(false); } Header.BlockStart = Inp.InAddr; ReadBorder = Math.Min(ReadBorder, Header.BlockStart + Header.BlockSize - 1); Header.LastBlockInFile = (BlockFlags & 0x40) != 0; Header.TablePresent = (BlockFlags & 0x80) != 0; return(true); }
private uint ReadFilterData(BitInput Inp) { uint ByteCount = (Inp.fgetbits() >> 14) + 1; Inp.addbits(2); uint Data = 0; for (uint I = 0; I < ByteCount; I++) { Data += (Inp.fgetbits() >> 8) << (int)(I * 8); Inp.addbits(8); } return(Data); }
private uint DecodeNumber(BitInput Inp, DecodeTable Dec) { // Left aligned 15 bit length raw bit field. uint BitField = Inp.getbits() & 0xfffe; if (BitField < Dec.DecodeLen[Dec.QuickBits]) { uint Code = BitField >> (int)(16 - Dec.QuickBits); Inp.addbits(Dec.QuickLen[Code]); return(Dec.QuickNum[Code]); } // Detect the real bit length for current code. uint Bits = 15; for (uint I = Dec.QuickBits + 1; I < 15; I++) { if (BitField < Dec.DecodeLen[I]) { Bits = I; break; } } Inp.addbits(Bits); // Calculate the distance from the start code for current bit length. uint Dist = BitField - Dec.DecodeLen[Bits - 1]; // Start codes are left aligned, but we need the normal right aligned // number. So we shift the distance to the right. Dist >>= (int)(16 - Bits); // Now we can calculate the position in the code list. It is the sum // of first position for current bit length and right aligned distance // between our bit field and start code for current bit length. uint Pos = Dec.DecodePos[Bits] + Dist; // Out of bounds safety check required for damaged archives. if (Pos >= Dec.MaxNum) { Pos = 0; } // Convert the position in the code list to position in alphabet // and return it. return(Dec.DecodeNum[Pos]); }
private uint SlotToLength(BitInput Inp, uint Slot) { uint LBits, Length = 2; if (Slot < 8) { LBits = 0; Length += Slot; } else { LBits = Slot / 4 - 1; Length += (4 | (Slot & 3)) << (int)LBits; } if (LBits > 0) { Length += Inp.getbits() >> (int)(16 - LBits); Inp.addbits(LBits); } return(Length); }
private bool ReadTables(BitInput Inp, ref UnpackBlockHeader Header, ref UnpackBlockTables Tables) { if (!Header.TablePresent) { return(true); } if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 25) { if (!UnpReadBuf()) { return(false); } } byte[] BitLength = new byte[BC]; for (uint I = 0; I < BC; I++) { uint Length = (byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); if (Length == 15) { uint ZeroCount = (byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); if (ZeroCount == 0) { BitLength[I] = 15; } else { ZeroCount += 2; while (ZeroCount-- > 0 && I < BitLength.Length) { BitLength[I++] = 0; } I--; } } else { BitLength[I] = (byte)Length; } } MakeDecodeTables(BitLength, 0, Tables.BD, BC); byte[] Table = new byte[HUFF_TABLE_SIZE]; const uint TableSize = HUFF_TABLE_SIZE; for (uint I = 0; I < TableSize;) { if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 5) { if (!UnpReadBuf()) { return(false); } } uint Number = DecodeNumber(Inp, Tables.BD); if (Number < 16) { Table[I] = (byte)Number; I++; } else if (Number < 18) { uint N; if (Number == 16) { N = (Inp.fgetbits() >> 13) + 3; Inp.faddbits(3); } else { N = (Inp.fgetbits() >> 9) + 11; Inp.faddbits(7); } if (I == 0) { // We cannot have "repeat previous" code at the first position. // Multiple such codes would shift Inp position without changing I, // which can lead to reading beyond of Inp boundary in mutithreading // mode, where Inp.ExternalBuffer disables bounds check and we just // reserve a lot of buffer space to not need such check normally. return(false); } else { while (N-- > 0 && I < TableSize) { Table[I] = Table[I - 1]; I++; } } } else { uint N; if (Number == 18) { N = (Inp.fgetbits() >> 13) + 3; Inp.faddbits(3); } else { N = (Inp.fgetbits() >> 9) + 11; Inp.faddbits(7); } while (N-- > 0 && I < TableSize) { Table[I++] = 0; } } } TablesRead5 = true; if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop) { return(false); } MakeDecodeTables(Table, 0, Tables.LD, NC); MakeDecodeTables(Table, (int)NC, Tables.DD, DC); MakeDecodeTables(Table, (int)(NC + DC), Tables.LDD, LDC); MakeDecodeTables(Table, (int)(NC + DC + LDC), Tables.RD, RC); return(true); }