00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 using System;
00039
00040 using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
00041
00042 namespace ICSharpCode.SharpZipLib.Zip.Compression
00043 {
00044
00045 class InflaterDynHeader
00046 {
00047 const int LNUM = 0;
00048 const int DNUM = 1;
00049 const int BLNUM = 2;
00050 const int BLLENS = 3;
00051 const int LENS = 4;
00052 const int REPS = 5;
00053
00054 static readonly int[] repMin = { 3, 3, 11 };
00055 static readonly int[] repBits = { 2, 3, 7 };
00056
00057 byte[] blLens;
00058 byte[] litdistLens;
00059
00060 InflaterHuffmanTree blTree;
00061
00062 int mode;
00063 int lnum, dnum, blnum, num;
00064 int repSymbol;
00065 byte lastLen;
00066 int ptr;
00067
00068 static readonly int[] BL_ORDER =
00069 { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
00070
00071 public InflaterDynHeader()
00072 {
00073 }
00074
00075 public bool Decode(StreamManipulator input)
00076 {
00077 decode_loop:
00078 for (;;) {
00079 switch (mode) {
00080 case LNUM:
00081 lnum = input.PeekBits(5);
00082 if (lnum < 0) {
00083 return false;
00084 }
00085 lnum += 257;
00086 input.DropBits(5);
00087
00088 mode = DNUM;
00089 goto case DNUM;
00090 case DNUM:
00091 dnum = input.PeekBits(5);
00092 if (dnum < 0) {
00093 return false;
00094 }
00095 dnum++;
00096 input.DropBits(5);
00097
00098 num = lnum+dnum;
00099 litdistLens = new byte[num];
00100 mode = BLNUM;
00101 goto case BLNUM;
00102 case BLNUM:
00103 blnum = input.PeekBits(4);
00104 if (blnum < 0) {
00105 return false;
00106 }
00107 blnum += 4;
00108 input.DropBits(4);
00109 blLens = new byte[19];
00110 ptr = 0;
00111
00112 mode = BLLENS;
00113 goto case BLLENS;
00114 case BLLENS:
00115 while (ptr < blnum) {
00116 int len = input.PeekBits(3);
00117 if (len < 0) {
00118 return false;
00119 }
00120 input.DropBits(3);
00121
00122 blLens[BL_ORDER[ptr]] = (byte) len;
00123 ptr++;
00124 }
00125 blTree = new InflaterHuffmanTree(blLens);
00126 blLens = null;
00127 ptr = 0;
00128 mode = LENS;
00129 goto case LENS;
00130 case LENS:
00131 {
00132 int symbol;
00133 while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) {
00134
00135
00136
00137 litdistLens[ptr++] = lastLen = (byte)symbol;
00138
00139 if (ptr == num) {
00140
00141 return true;
00142 }
00143 }
00144
00145
00146 if (symbol < 0) {
00147 return false;
00148 }
00149
00150
00151 if (symbol >= 17) {
00152
00153
00154 lastLen = 0;
00155 } else {
00156 if (ptr == 0) {
00157 throw new SharpZipBaseException();
00158 }
00159 }
00160 repSymbol = symbol-16;
00161 }
00162 mode = REPS;
00163 goto case REPS;
00164 case REPS:
00165 {
00166 int bits = repBits[repSymbol];
00167 int count = input.PeekBits(bits);
00168 if (count < 0) {
00169 return false;
00170 }
00171 input.DropBits(bits);
00172 count += repMin[repSymbol];
00173
00174
00175 if (ptr + count > num) {
00176 throw new SharpZipBaseException();
00177 }
00178 while (count-- > 0) {
00179 litdistLens[ptr++] = lastLen;
00180 }
00181
00182 if (ptr == num) {
00183
00184 return true;
00185 }
00186 }
00187 mode = LENS;
00188 goto decode_loop;
00189 }
00190 }
00191 }
00192
00193 public InflaterHuffmanTree BuildLitLenTree()
00194 {
00195 byte[] litlenLens = new byte[lnum];
00196 Array.Copy(litdistLens, 0, litlenLens, 0, lnum);
00197 return new InflaterHuffmanTree(litlenLens);
00198 }
00199
00200 public InflaterHuffmanTree BuildDistTree()
00201 {
00202 byte[] distLens = new byte[dnum];
00203 Array.Copy(litdistLens, lnum, distLens, 0, dnum);
00204 return new InflaterHuffmanTree(distLens);
00205 }
00206 }
00207 }