1 27 package org.htmlparser.lexer; 28 29 import java.io.ByteArrayInputStream ; 30 import java.io.IOException ; 31 import java.io.InputStream ; 32 import java.io.InputStreamReader ; 33 import java.io.ObjectInputStream ; 34 import java.io.ObjectOutputStream ; 35 import java.io.UnsupportedEncodingException ; 36 37 import org.htmlparser.util.EncodingChangeException; 38 import org.htmlparser.util.ParserException; 39 40 43 public class InputStreamSource 44 extends 45 Source 46 { 47 51 public static int BUFFER_SIZE = 16384; 52 53 57 protected transient InputStream mStream; 58 59 62 protected String mEncoding; 63 64 67 protected transient InputStreamReader mReader; 68 69 72 public char[] mBuffer; 73 74 77 public int mLevel; 78 79 82 public int mOffset; 83 84 87 protected int mMark; 88 89 94 public InputStreamSource (InputStream stream) 95 throws 96 UnsupportedEncodingException 97 { 98 this (stream, null, BUFFER_SIZE); 99 } 100 101 107 public InputStreamSource (InputStream stream, String charset) 108 throws 109 UnsupportedEncodingException 110 { 111 this (stream, charset, BUFFER_SIZE); 112 } 113 114 121 public InputStreamSource (InputStream stream, String charset, int buffer_size) 122 throws 123 UnsupportedEncodingException 124 { 125 if (null == stream) 126 stream = new Stream (null); 127 else 128 if (!stream.markSupported ()) 130 stream = new Stream (stream); 132 mStream = stream; 143 if (null == charset) 144 { 145 mReader = new InputStreamReader (stream); 146 mEncoding = mReader.getEncoding (); 147 } 148 else 149 { 150 mEncoding = charset; 151 mReader = new InputStreamReader (stream, charset); 152 } 153 mBuffer = new char[buffer_size]; 154 mLevel = 0; 155 mOffset = 0; 156 mMark = -1; 157 } 158 159 163 private void writeObject (ObjectOutputStream out) 164 throws 165 IOException 166 { 167 int offset; 168 char[] buffer; 169 170 if (null != mStream) 171 { 172 offset = mOffset; 174 buffer = new char[4096]; 175 while (EOF != read (buffer)) 176 ; 177 mOffset = offset; 178 } 179 180 out.defaultWriteObject (); 181 } 182 183 private void readObject (ObjectInputStream in) 184 throws 185 IOException , 186 ClassNotFoundException 187 { 188 in.defaultReadObject (); 189 if (null != mBuffer) mStream = new ByteArrayInputStream (new byte[0]); 192 } 193 194 198 public InputStream getStream () 199 { 200 return (mStream); 201 } 202 203 207 public String getEncoding () 208 { 209 return (mEncoding); 210 } 211 212 233 public void setEncoding (String character_set) 234 throws 235 ParserException 236 { 237 String encoding; 238 InputStream stream; 239 char[] buffer; 240 int offset; 241 char[] new_chars; 242 243 encoding = getEncoding (); 244 if (!encoding.equalsIgnoreCase (character_set)) 245 { 246 stream = getStream (); 247 try 248 { 249 buffer = mBuffer; 250 offset = mOffset; 251 stream.reset (); 252 try 253 { 254 mEncoding = character_set; 255 mReader = new InputStreamReader (stream, character_set); 256 mBuffer = new char[mBuffer.length]; 257 mLevel = 0; 258 mOffset = 0; 259 mMark = -1; 260 if (0 != offset) 261 { 262 new_chars = new char[offset]; 263 if (offset != read (new_chars)) 264 throw new ParserException ("reset stream failed"); 265 for (int i = 0; i < offset; i++) 266 if (new_chars[i] != buffer[i]) 267 throw new EncodingChangeException ("character mismatch (new: " 268 + new_chars[i] 269 + " [0x" 270 + Integer.toString (new_chars[i], 16) 271 + "] != old: " 272 + " [0x" 273 + Integer.toString (buffer[i], 16) 274 + buffer[i] 275 + "]) for encoding change from " 276 + encoding 277 + " to " 278 + character_set 279 + " at character offset " 280 + i); 281 } 282 } 283 catch (IOException ioe) 284 { 285 throw new ParserException (ioe.getMessage (), ioe); 286 } 287 } 288 catch (IOException ioe) 289 { throw new ParserException ("Stream reset failed (" 291 + ioe.getMessage () 292 + "), try wrapping it with a org.htmlparser.lexer.Stream", 293 ioe); 294 } 295 } 296 } 297 298 304 protected void fill (int min) 305 throws 306 IOException 307 { 308 char[] buffer; 309 int size; 310 int read; 311 312 if (null != mReader) { 314 size = mBuffer.length - mLevel; if (size < min) { 317 size = mBuffer.length * 2; 319 read = mLevel + min; 320 if (size < read) size = read; 322 else 323 min = size - mLevel; buffer = new char[size]; 325 } 326 else 327 { 328 buffer = mBuffer; 329 min = size; 330 } 331 332 read = mReader.read (buffer, mLevel, min); 334 if (EOF == read) 335 { 336 mReader.close (); 337 mReader = null; 338 } 339 else 340 { 341 if (mBuffer != buffer) 342 { System.arraycopy (mBuffer, 0, buffer, 0, mLevel); 344 mBuffer = buffer; 345 } 346 mLevel += read; 347 } 348 } 350 } 351 352 356 361 public void close () throws IOException 362 { 363 } 364 365 374 public int read () throws IOException 375 { 376 int ret; 377 378 if (mLevel - mOffset < 1) 379 { 380 if (null == mStream) 381 throw new IOException ("source is closed"); 382 fill (1); 383 if (mOffset >= mLevel) 384 ret = EOF; 385 else 386 ret = mBuffer[mOffset++]; 387 } 388 else 389 ret = mBuffer[mOffset++]; 390 391 return (ret); 392 } 393 394 405 public int read (char[] cbuf, int off, int len) throws IOException 406 { 407 int ret; 408 409 if (null == mStream) 410 throw new IOException ("source is closed"); 411 if ((null == cbuf) || (0 > off) || (0 > len)) 412 throw new IOException ("illegal argument read (" 413 + ((null == cbuf) ? "null" : "cbuf") 414 + ", " + off + ", " + len + ")"); 415 if (mLevel - mOffset < len) 416 fill (len - (mLevel - mOffset)); if (mOffset >= mLevel) 418 ret = EOF; 419 else 420 { 421 ret = Math.min (mLevel - mOffset, len); 422 System.arraycopy (mBuffer, mOffset, cbuf, off, ret); 423 mOffset += ret; 424 } 425 426 return (ret); 427 } 428 429 438 public int read (char[] cbuf) throws IOException 439 { 440 return (read (cbuf, 0, cbuf.length)); 441 } 442 443 448 public void reset () 449 { 450 if (null == mStream) 451 throw new IllegalStateException ("source is closed"); 452 if (-1 != mMark) 453 mOffset = mMark; 454 else 455 mOffset = 0; 456 } 457 458 462 public boolean markSupported () 463 { 464 return (true); 465 } 466 467 475 public void mark (int readAheadLimit) throws IOException 476 { 477 if (null == mStream) 478 throw new IOException ("source is closed"); 479 mMark = mOffset; 480 } 481 482 489 public boolean ready () throws IOException 490 { 491 if (null == mStream) 492 throw new IOException ("source is closed"); 493 return (mOffset < mLevel); 494 } 495 496 506 public long skip (long n) throws IOException 507 { 508 long ret; 509 510 if (null == mStream) 511 throw new IOException ("source is closed"); 512 if (mLevel - mOffset < n) 513 fill ((int)(n - (mLevel - mOffset))); if (mOffset >= mLevel) 515 ret = EOF; 516 else 517 { 518 ret = Math.min (mLevel - mOffset, n); 519 mOffset += ret; 520 } 521 522 return (ret); 523 } 524 525 529 534 public void unread () throws IOException 535 { 536 if (null == mStream) 537 throw new IOException ("source is closed"); 538 if (0 < mOffset) 539 mOffset--; 540 else 541 throw new IOException ("can't unread no characters"); 542 } 543 544 551 public char getCharacter (int offset) throws IOException 552 { 553 char ret; 554 555 if (null == mStream) 556 throw new IOException ("source is closed"); 557 if (offset >= mBuffer.length) 558 throw new IOException ("illegal read ahead"); 559 else 560 ret = mBuffer[offset]; 561 562 return (ret); 563 } 564 565 576 public void getCharacters (char[] array, int offset, int start, int end) throws IOException 577 { 578 if (null == mStream) 579 throw new IOException ("source is closed"); 580 System.arraycopy (mBuffer, start, array, offset, end - start); 581 } 582 583 591 public String getString (int offset, int length) throws IOException 592 { 593 String ret; 594 595 if (null == mStream) 596 throw new IOException ("source is closed"); 597 if (offset + length >= mBuffer.length) 598 throw new IOException ("illegal read ahead"); 599 else 600 ret = new String (mBuffer, offset, length); 601 602 return (ret); 603 } 604 605 613 public void getCharacters (StringBuffer buffer, int offset, int length) throws IOException 614 { 615 if (null == mStream) 616 throw new IOException ("source is closed"); 617 buffer.append (mBuffer, offset, length); 618 } 619 620 630 public void destroy () throws IOException 631 { 632 mStream = null; 633 if (null != mReader) 634 mReader.close (); 635 mReader = null; 636 mBuffer = null; 637 mLevel = 0; 638 mOffset = 0; 639 mMark = -1; 640 } 641 642 647 public int offset () 648 { 649 int ret; 650 651 if (null == mStream) 652 ret = EOF; 653 else 654 ret = mOffset; 655 656 return (ret); 657 } 658 659 664 public int available () 665 { 666 int ret; 667 668 if (null == mStream) 669 ret = 0; 670 else 671 ret = mLevel - mOffset; 672 673 return (ret); 674 } 675 } 676 | Popular Tags |