| // InflaterDynHeader.cs | 
| // Copyright (C) 2001 Mike Krueger | 
| // | 
| // This file was translated from java, it was part of the GNU Classpath | 
| // Copyright (C) 2001 Free Software Foundation, Inc. | 
| // | 
| // This program is free software; you can redistribute it and/or | 
| // modify it under the terms of the GNU General Public License | 
| // as published by the Free Software Foundation; either version 2 | 
| // of the License, or (at your option) any later version. | 
| // | 
| // This program is distributed in the hope that it will be useful, | 
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| // GNU General Public License for more details. | 
| // | 
| // You should have received a copy of the GNU General Public License | 
| // along with this program; if not, write to the Free Software | 
| // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
| // | 
| // Linking this library statically or dynamically with other modules is | 
| // making a combined work based on this library.  Thus, the terms and | 
| // conditions of the GNU General Public License cover the whole | 
| // combination. | 
| // | 
| // As a special exception, the copyright holders of this library give you | 
| // permission to link this library with independent modules to produce an | 
| // executable, regardless of the license terms of these independent | 
| // modules, and to copy and distribute the resulting executable under | 
| // terms of your choice, provided that you also meet, for each linked | 
| // independent module, the terms and conditions of the license of that | 
| // module.  An independent module is a module which is not derived from | 
| // or based on this library.  If you modify this library, you may extend | 
| // this exception to your version of the library, but you are not | 
| // obligated to do so.  If you do not wish to do so, delete this | 
| // exception statement from your version. | 
|   | 
| 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 | 
|   | 
|         #region Constructors | 
|         public InflaterDynHeader() | 
|         { | 
|         } | 
|         #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; | 
|   | 
|         /// <summary> | 
|         /// The current decode mode | 
|         /// </summary> | 
|         int mode; | 
|         int lnum, dnum, blnum, num; | 
|         int repSymbol; | 
|         byte lastLen; | 
|         int ptr; | 
|         #endregion | 
|   | 
|     } | 
| } |