using System; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; namespace ICSharpCode.SharpZipLib.Zip.Compression { class InflaterDynHeader { #region Constants const int LNUM = 0; const int DNUM = 1; const int BLNUM = 2; const int BLLENS = 3; const int LENS = 4; const int REPS = 5; static readonly int[] repMin = { 3, 3, 11 }; static readonly int[] repBits = { 2, 3, 7 }; static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; #endregion public bool Decode(StreamManipulator input) { decode_loop: for (;;) { switch (mode) { case LNUM: lnum = input.PeekBits(5); if (lnum < 0) { return false; } lnum += 257; input.DropBits(5); // System.err.println("LNUM: "+lnum); mode = DNUM; goto case DNUM; // fall through case DNUM: dnum = input.PeekBits(5); if (dnum < 0) { return false; } dnum++; input.DropBits(5); // System.err.println("DNUM: "+dnum); num = lnum + dnum; litdistLens = new byte[num]; mode = BLNUM; goto case BLNUM; // fall through case BLNUM: blnum = input.PeekBits(4); if (blnum < 0) { return false; } blnum += 4; input.DropBits(4); blLens = new byte[19]; ptr = 0; // System.err.println("BLNUM: "+blnum); mode = BLLENS; goto case BLLENS; // fall through case BLLENS: while (ptr < blnum) { int len = input.PeekBits(3); if (len < 0) { return false; } input.DropBits(3); // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); blLens[BL_ORDER[ptr]] = (byte)len; ptr++; } blTree = new InflaterHuffmanTree(blLens); blLens = null; ptr = 0; mode = LENS; goto case LENS; // fall through case LENS: { int symbol; while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) { /* Normal case: symbol in [0..15] */ // System.err.println("litdistLens["+ptr+"]: "+symbol); litdistLens[ptr++] = lastLen = (byte)symbol; if (ptr == num) { /* Finished */ return true; } } /* need more input ? */ if (symbol < 0) { return false; } /* otherwise repeat code */ if (symbol >= 17) { /* repeat zero */ // System.err.println("repeating zero"); lastLen = 0; } else { if (ptr == 0) { throw new SharpZipBaseException(); } } repSymbol = symbol - 16; } mode = REPS; goto case REPS; // fall through case REPS: { int bits = repBits[repSymbol]; int count = input.PeekBits(bits); if (count < 0) { return false; } input.DropBits(bits); count += repMin[repSymbol]; // System.err.println("litdistLens repeated: "+count); if (ptr + count > num) { throw new SharpZipBaseException(); } while (count-- > 0) { litdistLens[ptr++] = lastLen; } if (ptr == num) { /* Finished */ return true; } } mode = LENS; goto decode_loop; } } } public InflaterHuffmanTree BuildLitLenTree() { byte[] litlenLens = new byte[lnum]; Array.Copy(litdistLens, 0, litlenLens, 0, lnum); return new InflaterHuffmanTree(litlenLens); } public InflaterHuffmanTree BuildDistTree() { byte[] distLens = new byte[dnum]; Array.Copy(litdistLens, lnum, distLens, 0, dnum); return new InflaterHuffmanTree(distLens); } #region Instance Fields byte[] blLens; byte[] litdistLens; InflaterHuffmanTree blTree; /// /// The current decode mode /// int mode; int lnum, dnum, blnum, num; int repSymbol; byte lastLen; int ptr; #endregion } }