1
2
3
4
5 package joeq.ClassLib.Common.java.util.zip;
6
7 /***
8 * StreamManipulator
9 *
10 * @author John Whaley <jwhaley@alum.mit.edu>
11 * @version $Id: StreamManipulator.java 1451 2004-03-09 06:27:08Z jwhaley $
12 */
13 class StreamManipulator {
14
15 private byte[] window;
16 private int window_start = 0;
17 private int window_end = 0;
18
19 private int buffer = 0;
20 private int bits_in_buffer = 0;
21
22 /***
23 * Get the next n bits but don't increase input pointer. n must be
24 * less or equal 16 and if you if this call succeeds, you must drop
25 * at least n-8 bits in the next call.
26 *
27 * @return the value of the bits, or -1 if not enough bits available. */
28 public final int peekBits(int n)
29 {
30 if (bits_in_buffer < n)
31 {
32 if (window_start == window_end)
33 return -1;
34 buffer |= (window[window_start++] & 0xff
35 | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
36 bits_in_buffer += 16;
37 }
38 return buffer & ((1 << n) - 1);
39 }
40
41
42
43
44
45 public final void dropBits(int n)
46 {
47 buffer >>>= n;
48 bits_in_buffer -= n;
49 }
50
51 /***
52 * Gets the next n bits and increases input pointer. This is equivalent
53 * to peekBits followed by dropBits, except for correct error handling.
54 * @return the value of the bits, or -1 if not enough bits available.
55 */
56 public final int getBits(int n)
57 {
58 int bits = peekBits(n);
59 if (bits >= 0)
60 dropBits(n);
61 return bits;
62 }
63 /***
64 * Gets the number of bits available in the bit buffer. This must be
65 * only called when a previous peekBits() returned -1.
66 * @return the number of bits available.
67 */
68 public final int getAvailableBits()
69 {
70 return bits_in_buffer;
71 }
72
73 /***
74 * Gets the number of bytes available.
75 * @return the number of bytes available.
76 */
77 public final int getAvailableBytes()
78 {
79 return window_end - window_start + (bits_in_buffer >> 3);
80 }
81
82 /***
83 * Skips to the next byte boundary.
84 */
85 public void skipToByteBoundary()
86 {
87 buffer >>= (bits_in_buffer & 7);
88 bits_in_buffer &= ~7;
89 }
90
91 public final boolean needsInput() {
92 return window_start == window_end;
93 }
94
95
96
97
98
99
100
101
102
103 public int copyBytes(byte[] output, int offset, int length)
104 {
105 if (length < 0)
106 throw new java.lang.IllegalArgumentException("length negative");
107 if ((bits_in_buffer & 7) != 0)
108
109 throw new java.lang.IllegalStateException("Bit buffer is not aligned!");
110
111 int count = 0;
112 while (bits_in_buffer > 0 && length > 0)
113 {
114 output[offset++] = (byte) buffer;
115 buffer >>>= 8;
116 bits_in_buffer -= 8;
117 length--;
118 count++;
119 }
120 if (length == 0)
121 return count;
122
123 int avail = window_end - window_start;
124 if (length > avail)
125 length = avail;
126 java.lang.System.arraycopy(window, window_start, output, offset, length);
127 window_start += length;
128
129 if (((window_start - window_end) & 1) != 0)
130 {
131
132 buffer = (window[window_start++] & 0xff);
133 bits_in_buffer = 8;
134 }
135 return count + length;
136 }
137
138 public StreamManipulator()
139 {
140 }
141
142 public void reset()
143 {
144 window_start = window_end = buffer = bits_in_buffer = 0;
145 }
146
147 public void setInput(byte[] buf, int off, int len)
148 {
149 if (window_start < window_end)
150 throw new java.lang.IllegalStateException
151 ("Old input was not completely processed");
152
153 int end = off + len;
154
155
156
157
158 if (0 > off || off > end || end > buf.length)
159 throw new java.lang.ArrayIndexOutOfBoundsException();
160
161 if ((len & 1) != 0)
162 {
163
164 buffer |= (buf[off++] & 0xff) << bits_in_buffer;
165 bits_in_buffer += 8;
166 }
167
168 window = buf;
169 window_start = off;
170 window_end = end;
171 }
172
173 }