1 28 29 package HTTPClient; 30 31 import java.io.IOException ; 32 import java.io.EOFException ; 33 import java.io.InputStream ; 34 import java.io.FileInputStream ; 35 import java.io.FilterInputStream ; 36 37 38 47 class UncompressInputStream extends FilterInputStream 48 { 49 53 public UncompressInputStream(InputStream is) throws IOException 54 { 55 super(is); 56 parse_header(); 57 } 58 59 60 byte[] one = new byte[1]; 61 public synchronized int read() throws IOException 62 { 63 int b = in.read(one, 0, 1); 64 if (b == 1) 65 return (one[0] & 0xff); 66 else 67 return -1; 68 } 69 70 71 private static final int TBL_CLEAR = 0x100; 73 private static final int TBL_FIRST = TBL_CLEAR + 1; 74 75 private int[] tab_prefix; 76 private byte[] tab_suffix; 77 private int[] zeros = new int[256]; 78 private byte[] stack; 79 80 private boolean block_mode; 82 private int n_bits; 83 private int maxbits; 84 private int maxmaxcode; 85 private int maxcode; 86 private int bitmask; 87 private int oldcode; 88 private byte finchar; 89 private int stackp; 90 private int free_ent; 91 92 private byte[] data = new byte[10000]; 94 private int bit_pos = 0, end = 0, got = 0; 95 private boolean eof = false; 96 private static final int EXTRA = 64; 97 98 99 public synchronized int read(byte[] buf, int off, int len) 100 throws IOException 101 { 102 if (eof) return -1; 103 int start = off; 104 105 108 int[] l_tab_prefix = tab_prefix; 109 byte[] l_tab_suffix = tab_suffix; 110 byte[] l_stack = stack; 111 int l_n_bits = n_bits; 112 int l_maxcode = maxcode; 113 int l_maxmaxcode = maxmaxcode; 114 int l_bitmask = bitmask; 115 int l_oldcode = oldcode; 116 byte l_finchar = finchar; 117 int l_stackp = stackp; 118 int l_free_ent = free_ent; 119 byte[] l_data = data; 120 int l_bit_pos = bit_pos; 121 122 123 125 int s_size = l_stack.length - l_stackp; 126 if (s_size > 0) 127 { 128 int num = (s_size >= len) ? len : s_size ; 129 System.arraycopy(l_stack, l_stackp, buf, off, num); 130 off += num; 131 len -= num; 132 l_stackp += num; 133 } 134 135 if (len == 0) 136 { 137 stackp = l_stackp; 138 return off-start; 139 } 140 141 142 144 main_loop: do 145 { 146 if (end < EXTRA) fill(); 147 148 int bit_in = (got > 0) ? (end - end%l_n_bits)<<3 : 149 (end<<3)-(l_n_bits-1); 150 151 while (l_bit_pos < bit_in) 152 { 153 155 if (l_free_ent > l_maxcode) 156 { 157 int n_bytes = l_n_bits << 3; 158 l_bit_pos = (l_bit_pos-1) + 159 n_bytes - (l_bit_pos-1+n_bytes) % n_bytes; 160 161 l_n_bits++; 162 l_maxcode = (l_n_bits==maxbits) ? l_maxmaxcode : 163 (1<<l_n_bits) - 1; 164 165 if (debug) 166 System.err.println("Code-width expanded to " + l_n_bits); 167 168 l_bitmask = (1<<l_n_bits)-1; 169 l_bit_pos = resetbuf(l_bit_pos); 170 continue main_loop; 171 } 172 173 174 176 int pos = l_bit_pos>>3; 177 int code = (((l_data[pos]&0xFF) | ((l_data[pos+1]&0xFF)<<8) | 178 ((l_data[pos+2]&0xFF)<<16)) 179 >> (l_bit_pos & 0x7)) & l_bitmask; 180 l_bit_pos += l_n_bits; 181 182 183 185 if (l_oldcode == -1) 186 { 187 if (code >= 256) 188 throw new IOException ("corrupt input: " + code + 189 " > 255"); 190 l_finchar = (byte) (l_oldcode = code); 191 buf[off++] = l_finchar; 192 len--; 193 continue; 194 } 195 196 197 199 if (code == TBL_CLEAR && block_mode) 200 { 201 System.arraycopy(zeros, 0, l_tab_prefix, 0, zeros.length); 202 l_free_ent = TBL_FIRST - 1; 203 204 int n_bytes = l_n_bits << 3; 205 l_bit_pos = (l_bit_pos-1) + 206 n_bytes - (l_bit_pos-1+n_bytes) % n_bytes; 207 l_n_bits = INIT_BITS; 208 l_maxcode = (1 << l_n_bits) - 1; 209 l_bitmask = l_maxcode; 210 211 if (debug) System.err.println("Code tables reset"); 212 213 l_bit_pos = resetbuf(l_bit_pos); 214 continue main_loop; 215 } 216 217 218 220 int incode = code; 221 l_stackp = l_stack.length; 222 223 224 226 if (code >= l_free_ent) 227 { 228 if (code > l_free_ent) 229 throw new IOException ("corrupt input: code=" + code + 230 ", free_ent=" + l_free_ent); 231 232 l_stack[--l_stackp] = l_finchar; 233 code = l_oldcode; 234 } 235 236 237 239 while (code >= 256) 240 { 241 l_stack[--l_stackp] = l_tab_suffix[code]; 242 code = l_tab_prefix[code]; 243 } 244 l_finchar = l_tab_suffix[code]; 245 buf[off++] = l_finchar; 246 len--; 247 248 249 251 s_size = l_stack.length - l_stackp; 252 int num = (s_size >= len) ? len : s_size ; 253 System.arraycopy(l_stack, l_stackp, buf, off, num); 254 off += num; 255 len -= num; 256 l_stackp += num; 257 258 259 261 if (l_free_ent < l_maxmaxcode) 262 { 263 l_tab_prefix[l_free_ent] = l_oldcode; 264 l_tab_suffix[l_free_ent] = l_finchar; 265 l_free_ent++; 266 } 267 268 269 271 l_oldcode = incode; 272 273 274 276 if (len == 0) 277 { 278 n_bits = l_n_bits; 279 maxcode = l_maxcode; 280 bitmask = l_bitmask; 281 oldcode = l_oldcode; 282 finchar = l_finchar; 283 stackp = l_stackp; 284 free_ent = l_free_ent; 285 bit_pos = l_bit_pos; 286 287 return off-start; 288 } 289 } 290 291 l_bit_pos = resetbuf(l_bit_pos); 292 } while (got > 0); 293 294 n_bits = l_n_bits; 295 maxcode = l_maxcode; 296 bitmask = l_bitmask; 297 oldcode = l_oldcode; 298 finchar = l_finchar; 299 stackp = l_stackp; 300 free_ent = l_free_ent; 301 bit_pos = l_bit_pos; 302 303 eof = true; 304 return off-start; 305 } 306 307 308 312 private final int resetbuf(int bit_pos) 313 { 314 int pos = bit_pos >> 3; 315 System.arraycopy(data, pos, data, 0, end-pos); 316 end -= pos; 317 return 0; 318 } 319 320 321 private final void fill() throws IOException 322 { 323 got = in.read(data, end, data.length-1-end); 324 if (got > 0) end += got; 325 } 326 327 328 public synchronized long skip(long num) throws IOException 329 { 330 byte[] tmp = new byte[(int) num]; 331 int got = read(tmp, 0, (int) num); 332 333 if (got > 0) 334 return (long) got; 335 else 336 return 0L; 337 } 338 339 340 public synchronized int available() throws IOException 341 { 342 if (eof) return 0; 343 344 return in.available(); 345 } 346 347 348 private static final int LZW_MAGIC = 0x1f9d; 349 private static final int MAX_BITS = 16; 350 private static final int INIT_BITS = 9; 351 private static final int HDR_MAXBITS = 0x1f; 352 private static final int HDR_EXTENDED = 0x20; 353 private static final int HDR_FREE = 0x40; 354 private static final int HDR_BLOCK_MODE = 0x80; 355 356 private void parse_header() throws IOException 357 { 358 360 int t = in.read(); 361 if (t < 0) throw new EOFException ("Failed to read magic number"); 362 int magic = (t & 0xff) << 8; 363 t = in.read(); 364 if (t < 0) throw new EOFException ("Failed to read magic number"); 365 magic += t & 0xff; 366 if (magic != LZW_MAGIC) 367 throw new IOException ("Input not in compress format (read " + 368 "magic number 0x" + 369 Integer.toHexString(magic) + ")"); 370 371 372 374 int header = in.read(); 375 if (header < 0) throw new EOFException ("Failed to read header"); 376 377 block_mode = (header & HDR_BLOCK_MODE) > 0; 378 maxbits = header & HDR_MAXBITS; 379 380 if (maxbits > MAX_BITS) 381 throw new IOException ("Stream compressed with " + maxbits + 382 " bits, but can only handle " + MAX_BITS + 383 " bits"); 384 385 if ((header & HDR_EXTENDED) > 0) 386 throw new IOException ("Header extension bit set"); 387 388 if ((header & HDR_FREE) > 0) 389 throw new IOException ("Header bit 6 set"); 390 391 if (debug) 392 { 393 System.err.println("block mode: " + block_mode); 394 System.err.println("max bits: " + maxbits); 395 } 396 397 398 400 maxmaxcode = 1 << maxbits; 401 n_bits = INIT_BITS; 402 maxcode = (1 << n_bits) - 1; 403 bitmask = maxcode; 404 oldcode = -1; 405 finchar = 0; 406 free_ent = block_mode ? TBL_FIRST : 256; 407 408 tab_prefix = new int[1 << maxbits]; 409 tab_suffix = new byte[1 << maxbits]; 410 stack = new byte[1 << maxbits]; 411 stackp = stack.length; 412 413 for (int idx=255; idx>=0; idx--) 414 tab_suffix[idx] = (byte) idx; 415 } 416 417 418 private static final boolean debug = false; 419 420 public static void main (String args[]) throws Exception 421 { 422 if (args.length != 1) 423 { 424 System.err.println("Usage: UncompressInputStream <file>"); 425 System.exit(1); 426 } 427 428 InputStream in = 429 new UncompressInputStream(new FileInputStream (args[0])); 430 431 byte[] buf = new byte[100000]; 432 int tot = 0; 433 long beg = System.currentTimeMillis(); 434 435 while (true) 436 { 437 int got = in.read(buf); 438 if (got < 0) break; 439 System.out.write(buf, 0, got); 440 tot += got; 441 } 442 443 long end = System.currentTimeMillis(); 444 System.err.println("Decompressed " + tot + " bytes"); 445 System.err.println("Time: " + (end-beg)/1000. + " seconds"); 446 } 447 } 448 449 | Popular Tags |