private static int DecodeValue(ref BitBuffer bitBuffer, Node node) { // This cannot cause an infinite loop if the tables are correct. while (node.Value == -1) { node = node[bitBuffer.GetBit()]; } return(node.Value); }
private static int DecodeValue(ref BitBuffer bitBuffer, Node node) { // This cannot cause an infinite loop if the tables are correct. while (node.Value == -1) node = node[bitBuffer.GetBit()]; return node.Value; }
// 'explode' decompression public static int DecompressBlock(byte[] inBuffer, int index, int count, byte[] outBuffer) { bool ascii; byte b; b = inBuffer[index++]; // Check the ASCII encoding flag if (b == 0) ascii = false; // Don't use ASCII encoding else if (b == 1) ascii = true; // Use ASCII encoding else throw new InvalidDataException(); b = inBuffer[index++]; if (b < 4 || b > 6) throw new InvalidDataException(); int dictSize = 0x40 << b; // Calculate dictionnary size int lowOffsetSize = b; var bitBuffer = new BitBuffer(inBuffer, index, count - 2); try { int i = 0; while (i < outBuffer.Length && !bitBuffer.Eof) { int t = bitBuffer.GetBit(); if (t == 0) // Litteral { // Depending on the compression mode, this can either be a raw byte or a coded ASCII character t = ascii ? DecodeValue(ref bitBuffer, asciiTree) : bitBuffer.GetByte(); outBuffer[i++] = (byte)t; } else // Length/Offset Pair { // Get the length int length = DecodeValue(ref bitBuffer, lengthTree); if (length == 519) break; // Length 519 means end of stream // Get the offset int offsetHigh = DecodeValue(ref bitBuffer, offsetTree); int offset = length == 2 ? i - ((offsetHigh << 2) | bitBuffer.GetBits(2)) - 1 : i - ((offsetHigh << lowOffsetSize) | bitBuffer.GetBits(lowOffsetSize)) - 1; if (offset < 0) throw new InvalidDataException(); // Copy while (length-- != 0) outBuffer[i++] = outBuffer[offset++]; } } return i; } finally { bitBuffer.Dispose(); } }
// 'explode' decompression public static int DecompressBlock(byte[] inBuffer, int index, int count, byte[] outBuffer) { bool ascii; byte b; b = inBuffer[index++]; // Check the ASCII encoding flag if (b == 0) { ascii = false; // Don't use ASCII encoding } else if (b == 1) { ascii = true; // Use ASCII encoding } else { throw new InvalidDataException(); } b = inBuffer[index++]; if (b < 4 || b > 6) { throw new InvalidDataException(); } int dictSize = 0x40 << b; // Calculate dictionnary size int lowOffsetSize = b; var bitBuffer = new BitBuffer(inBuffer, index, count - 2); try { int i = 0; while (i < outBuffer.Length && !bitBuffer.Eof) { int t = bitBuffer.GetBit(); if (t == 0) // Litteral { // Depending on the compression mode, this can either be a raw byte or a coded ASCII character t = ascii ? DecodeValue(ref bitBuffer, asciiTree) : bitBuffer.GetByte(); outBuffer[i++] = (byte)t; } else // Length/Offset Pair { // Get the length int length = DecodeValue(ref bitBuffer, lengthTree); if (length == 519) { break; // Length 519 means end of stream } // Get the offset int offsetHigh = DecodeValue(ref bitBuffer, offsetTree); int offset = length == 2 ? i - ((offsetHigh << 2) | bitBuffer.GetBits(2)) - 1 : i - ((offsetHigh << lowOffsetSize) | bitBuffer.GetBits(lowOffsetSize)) - 1; if (offset < 0) { throw new InvalidDataException(); } // Copy while (length-- != 0) { outBuffer[i++] = outBuffer[offset++]; } } } return(i); } finally { bitBuffer.Dispose(); } }