Source code: ClassLib/Common/java/util/zip/InflaterDynHeader.java
1 // InflaterDynHeader.java, created Mon Jul 8 4:06:18 2002 by joewhaley
2 // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3 // Licensed under the terms of the GNU LGPL; see COPYING for details.
4 package ClassLib.Common.java.util.zip;
5
6 import java.util.zip.DataFormatException;
7
8 /**
9 * InflaterDynHeader
10 *
11 * @author John Whaley <jwhaley@alum.mit.edu>
12 * @version $Id: InflaterDynHeader.java,v 1.5 2003/05/12 10:04:53 joewhaley Exp $
13 */
14 class InflaterDynHeader {
15
16 private static final int LNUM = 0;
17 private static final int DNUM = 1;
18 private static final int BLNUM = 2;
19 private static final int BLLENS = 3;
20 private static final int LENS = 4;
21 private static final int REPS = 5;
22
23 private static final int repMin[] = { 3, 3, 11 };
24 private static final int repBits[] = { 2, 3, 7 };
25
26
27 private byte[] blLens;
28 private byte[] litdistLens;
29
30 private InflaterHuffmanTree blTree;
31
32 private int mode;
33 private int lnum, dnum, blnum, num;
34 private int repSymbol;
35 private byte lastLen;
36 private int ptr;
37
38 private static final int[] BL_ORDER =
39 { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
40
41 public InflaterDynHeader()
42 {
43 }
44
45 public boolean decode(StreamManipulator input) throws DataFormatException
46 {
47 decode_loop:
48 for (;;)
49 {
50 switch (mode)
51 {
52 case LNUM:
53 lnum = input.peekBits(5);
54 if (lnum < 0)
55 return false;
56 lnum += 257;
57 input.dropBits(5);
58 // System.err.println("LNUM: "+lnum);
59 mode = DNUM;
60 /* fall through */
61 case DNUM:
62 dnum = input.peekBits(5);
63 if (dnum < 0)
64 return false;
65 dnum++;
66 input.dropBits(5);
67 // System.err.println("DNUM: "+dnum);
68 num = lnum+dnum;
69 litdistLens = new byte[num];
70 mode = BLNUM;
71 /* fall through */
72 case BLNUM:
73 blnum = input.peekBits(4);
74 if (blnum < 0)
75 return false;
76 blnum += 4;
77 input.dropBits(4);
78 blLens = new byte[19];
79 ptr = 0;
80 // System.err.println("BLNUM: "+blnum);
81 mode = BLLENS;
82 /* fall through */
83 case BLLENS:
84 while (ptr < blnum)
85 {
86 int len = input.peekBits(3);
87 if (len < 0)
88 return false;
89 input.dropBits(3);
90 // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
91 blLens[BL_ORDER[ptr]] = (byte) len;
92 ptr++;
93 }
94 blTree = new InflaterHuffmanTree(blLens);
95 blLens = null;
96 ptr = 0;
97 mode = LENS;
98 /* fall through */
99 case LENS:
100 {
101 int symbol;
102 while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
103 {
104 /* Normal case: symbol in [0..15] */
105
106 // System.err.println("litdistLens["+ptr+"]: "+symbol);
107 litdistLens[ptr++] = lastLen = (byte) symbol;
108
109 if (ptr == num)
110 {
111 /* Finished */
112 return true;
113 }
114 }
115
116 /* need more input ? */
117 if (symbol < 0)
118 return false;
119
120 /* otherwise repeat code */
121 if (symbol >= 17)
122 {
123 /* repeat zero */
124 // System.err.println("repeating zero");
125 lastLen = 0;
126 }
127 else
128 {
129 if (ptr == 0)
130 throw new DataFormatException();
131 }
132 repSymbol = symbol-16;
133 mode = REPS;
134 }
135 /* fall through */
136
137 case REPS:
138 {
139 int bits = repBits[repSymbol];
140 int count = input.peekBits(bits);
141 if (count < 0)
142 return false;
143 input.dropBits(bits);
144 count += repMin[repSymbol];
145 // System.err.println("litdistLens repeated: "+count);
146
147 if (ptr + count > num)
148 throw new DataFormatException();
149 while (count-- > 0)
150 litdistLens[ptr++] = lastLen;
151
152 if (ptr == num)
153 {
154 /* Finished */
155 return true;
156 }
157 }
158 mode = LENS;
159 continue decode_loop;
160 }
161 }
162 }
163
164 public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
165 {
166 byte[] litlenLens = new byte[lnum];
167 System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
168 return new InflaterHuffmanTree(litlenLens);
169 }
170
171 public InflaterHuffmanTree buildDistTree() throws DataFormatException
172 {
173 byte[] distLens = new byte[dnum];
174 System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
175 return new InflaterHuffmanTree(distLens);
176 }
177 }