1 /* java.util.Scanner -- Parses primitive types and strings using regexps 2 Copyright (C) 2007 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 package java.util; 39 40 import java.io.BufferedInputStream; 41 import java.io.File; 42 import java.io.FileInputStream; 43 import java.io.FileNotFoundException; 44 import java.io.IOException; 45 import java.io.InputStream; 46 47 import java.math.BigDecimal; 48 import java.math.BigInteger; 49 50 import java.nio.ByteBuffer; 51 import java.nio.CharBuffer; 52 import java.nio.channels.ReadableByteChannel; 53 54 import java.text.DecimalFormat; 55 import java.text.DecimalFormatSymbols; 56 import java.text.NumberFormat; 57 import java.text.ParseException; 58 59 import java.util.Iterator; 60 import java.util.Locale; 61 import java.util.regex.MatchResult; 62 import java.util.regex.Matcher; 63 import java.util.regex.Pattern; 64 65 /** 66 * @author E0327023 Hernadi Laszlo 67 */ 68 public class Scanner 69 implements Iterator <String> 70 { 71 private static final String NOT_LONG = "\" is not a long"; //$NON-NLS-1$ 72 73 private static final String ERR_PREFIX = "\""; //$NON-NLS-1$ 74 75 private static final String NOT_INT = "\" is not an integer"; //$NON-NLS-1$ 76 77 private static final String NOT_DOUBLE = "\" is not a double"; //$NON-NLS-1$ 78 79 private static final String NOT_BYTE = "\" is not a byte"; //$NON-NLS-1$ 80 81 private static final String NOT_BOOLEAN = "\" is not a boolean"; //$NON-NLS-1$ 82 83 private static final String IS_NOT = "\" is not "; //$NON-NLS-1$ 84 85 private static final String DEFAULT_PATTERN_S = "\\p{javaWhitespace}+"; //$NON-NLS-1$ 86 87 private static final Pattern DEFAULT_PATTERN = 88 Pattern.compile (DEFAULT_PATTERN_S); 89 90 private static final String BIG_INTEGER = "BigInteger"; //$NON-NLS-1$ 91 92 private final static String NEW_LINE = 93 System.getProperty ("line.separator"); 94 95 private IOException lastIOException = null; 96 97 /** 98 * An InputStream source if a Constructor with an InputStream source is called, otherwise it 99 * stays <source> null </source>. 100 */ 101 private InputStream bIS = null; 102 103 /** 104 * Length of the input Buffer, which is the maximum bytes to be read at once. 105 */ 106 private final int MaxBufferLen = 1000000; 107 108 /** 109 * Minimum buffer length. If there are less chars in the Buffer than this value reading from 110 * source is tried. 111 */ 112 private final int MIN_BUF_LEN = 100; 113 114 /** 115 * Maximum number of processed chars in the Buffer. If exeeded, all processed chars from the 116 * beginning of the Buffer will be discarded to save space. The bytes left are copyed into a new 117 * Buffer. 118 */ 119 private final int MAX_PREFIX = 10000; 120 121 /** 122 * The Buffer which is used by the Matcher to find given patterns. It is filled up when matcher 123 * hits end or <code> MIN_BUF_LEN </code> is reached. 124 */ 125 private String actBuffer = new String (); 126 127 /** 128 * The current radix to use by the methods getNextXXX and hasNextXXX. 129 */ 130 private int currentRadix = 10; 131 132 /** 133 * The current locale. 134 * 135 * @see #useLocale(Locale) 136 * @see #locale() 137 */ 138 private Locale actLocale = Locale.getDefault (); 139 140 /** 141 * The current pattern for the matcher. 142 */ 143 private Pattern p = DEFAULT_PATTERN; 144 145 /** 146 * The current position in the Buffer, at which the next match should start. 147 */ 148 private int actPos = 0; 149 150 /** 151 * A global buffer to save new allocations by reading from source. 152 */ 153 private final byte[] tmpBuffer = new byte[this.MaxBufferLen]; 154 155 /** 156 * The charsetName to use with the source. 157 */ 158 private String charsetName = null; 159 160 /** 161 * The Matcher which is used. 162 */ 163 private Matcher myMatcher = this.p.matcher (this.actBuffer); 164 165 /** 166 * The MatchResult is generated at each match, even if match() isn't called. 167 */ 168 private MatchResult actResult = null; 169 170 /** 171 * A Readable source if a Constructor with a Readable source is called, otherwise it stays 172 * <source> null </source>. 173 */ 174 private Readable readableSource = null; 175 176 /** 177 * A ReadableByteChannel source if a Constructor with a ReadableByteChannel source is called, 178 * otherwise it stays <source> null </source>. 179 */ 180 private ReadableByteChannel rbcSource = null; 181 182 /** 183 * Indicates if the close() method was called. 184 */ 185 private boolean isClosed = false; 186 187 /** 188 * For performance reasons the last Found is saved, if a hasNextXXX method was called. 189 */ 190 private String lastFound = null; 191 192 private boolean lastFoundPresent = false; 193 194 private int lastNextPos = 0; 195 196 private int lastPatternHash = 0; 197 198 private int last_RegionStart = 0; 199 200 private int last_RegionEnd = 0; 201 202 private boolean last_anchor = false; 203 204 private boolean last_transparent = false; 205 206 private MatchResult lastResult = null; 207 208 /** 209 * To keep track of the current position in the stream for the toString method, each time 210 * processed chars are removed the amount is added to processedChars. 211 */ 212 private int procesedChars = 0; 213 214 /** 215 * needInput is set <code> true </code> before a read method, and if there is no input it blocks 216 * and stays <code>true</code>. Right after a read it is set to <code>false</code>. 217 */ 218 private boolean needInput = false; 219 220 private boolean skipped = false; 221 222 /** 223 * <code> {@link #doSkipp} </code> indicates that the found pattern belongs to the result. If 224 * <code> {@link #doSkipp} </code> is false the match result ends at the beginning of the match. 225 * In both cases the current position is set after the pattern, if the found pattern has to be 226 * removed, a nextXXX method is called. 227 */ 228 private boolean doSkipp = false; 229 230 /** 231 * Indicates if the last match was valid or not. 232 */ 233 private boolean matchValid = false; 234 235 private NumberFormat actFormat = NumberFormat.getInstance (this.actLocale); 236 237 private DecimalFormat df = (DecimalFormat) this.actFormat; 238 239 /** 240 * Indicates if current Locale should be used at the input. 241 */ 242 private boolean useLocale = true; 243 244 private DecimalFormatSymbols dfs = 245 new DecimalFormatSymbols (this.actLocale); 246 247 /** 248 * Constructs a new Scanner with the given File as source. 249 * {@link #Scanner(InputStream, String)} is called with <code> null </code> as charsetName. 250 * 251 * @param source 252 * The File to use as source. 253 * @throws FileNotFoundException 254 * If the file is not found an Exception is thrown. 255 */ Scanner(final File source)256 public Scanner (final File source) throws FileNotFoundException // TESTED 257 { 258 this (source, null); 259 } 260 261 /** 262 * Constructs a new Scanner with the given File as source. <br> 263 * {@link #Scanner(InputStream, String)} is called with the given charsetName. 264 * 265 * @param source 266 * The File to use as source. 267 * @param charsetName 268 * Current charset name of the file. If charsetName is null it behaves if it was not 269 * set. 270 * @throws FileNotFoundException 271 * If the file is not found an Exception is thrown. 272 */ Scanner(final File source, final String charsetName)273 public Scanner (final File source, 274 final String charsetName) throws FileNotFoundException 275 { 276 this (new FileInputStream (source), charsetName); 277 } 278 279 /** 280 * Constructs a new Scanner with the given inputStream. <br> 281 * {@link #Scanner(InputStream, String)} is called with <code> null </code> as charsetName. 282 * 283 * @param source 284 * The InputStream to use as source. 285 */ Scanner(final InputStream source)286 public Scanner (final InputStream source) // TESTED 287 { 288 this (source, null); 289 } 290 291 /** 292 * Constructs a new Scanner with the InputSream and a charsetName. Afterwards the Buffer is 293 * filled. 294 * 295 * @param source 296 * The InputStream to use as source. 297 * @param charsetName 298 * The charsetName to apply on the source's data. 299 */ Scanner(final InputStream source, final String charsetName)300 public Scanner (final InputStream source, final String charsetName) 301 { 302 this.bIS = (new BufferedInputStream (source)); 303 this.charsetName = charsetName; 304 myFillBuffer (); 305 } 306 307 /** 308 * Constructs a new Scanner with a Readable input as source. 309 * 310 * @param source 311 * The Readable to use as source. 312 */ Scanner(final Readable source)313 public Scanner (final Readable source) 314 { 315 this.readableSource = source; 316 myFillBuffer (); 317 } 318 319 /** 320 * Constructs a new Scanner with a ReadableByteChannel as 321 * source. Therfore the {@link #Scanner(ReadableByteChannel, 322 * String)} is called with <code> null </code> as charsetName. 323 * 324 * @param source 325 * The ReadableByteChannel to use as source. 326 */ Scanner(final ReadableByteChannel source)327 public Scanner (final ReadableByteChannel source) 328 { 329 this (source, null); 330 } 331 332 /** 333 * Constructs a new Scanner with a ReadableByteChannel as source and 334 * a given charsetName, which is to be applied on it. <br> It also 335 * initiates the main Buffer. 336 * 337 * @param source 338 * The ReadableByteChannel to use as source. 339 * @param charsetName 340 * The charsetName to be applied on the source. 341 */ Scanner(final ReadableByteChannel source, final String charsetName)342 public Scanner (final ReadableByteChannel source, final String charsetName) 343 { 344 this.charsetName = charsetName; 345 this.rbcSource = source; 346 myFillBuffer (); 347 } 348 349 /** 350 * Constructs a new Scanner using the given String as input only. 351 * 352 * @param source 353 * The whole String to be used as source. 354 */ Scanner(final String source)355 public Scanner (final String source) // TESTED 356 { 357 this.actBuffer = new String (source); 358 this.myMatcher.reset (this.actBuffer); 359 } 360 361 /** 362 * Closes this Scanner. If an {@link IOException} occurs it is 363 * catched and is available under {@link #ioException()}.<br> After 364 * the Scanner is closed, all searches will lead to a {@link 365 * IllegalStateException}. 366 */ close()367 public void close () 368 { 369 try 370 { 371 if (this.bIS != null) 372 this.bIS.close (); 373 if (this.rbcSource != null) 374 this.rbcSource.close (); 375 this.isClosed = true; 376 } 377 catch (IOException ioe) 378 { 379 this.lastIOException = ioe; 380 } 381 } 382 383 /** 384 * Returns the current delimiter. 385 * 386 * @return the current delimiter. 387 */ delimiter()388 public Pattern delimiter () // TESTED 389 { 390 return this.p; 391 } 392 393 /** 394 * Tries to find the pattern in the current line. 395 * 396 * @param pattern The pattern which should be searched in the 397 * current line of the input. 398 * @throws NoSuchElementException 399 * If the pattern was not found. 400 * @return If the search was successful, the result or otherwise a 401 * {@link NoSuchElementException} is thrown. 402 */ findInLine(final Pattern pattern)403 public String findInLine (final Pattern pattern) throws NoSuchElementException // TESTED 404 { 405 String tmpStr = myNextLine (false); 406 return myFindPInStr (pattern, tmpStr, 0); 407 } 408 409 /** 410 * Compiles the given pattern into a {@link Pattern} and calls 411 * {@link #findInLine(Pattern)} with the compiled pattern and 412 * returns whatever it returns. 413 * 414 * @param pattern 415 * The pattern which should be matched in the input. 416 * @throws NoSuchElementException 417 * If the pattern was not found. 418 * @return The match in the current line. 419 */ findInLine(final String pattern)420 public String findInLine (final String pattern) // TESTED 421 { 422 return findInLine (Pattern.compile (pattern)); 423 } 424 425 /** 426 * Trys to match the pattern within the given horizon. 427 * 428 * @param pattern 429 * Pattern to search. 430 * @param horizon 431 * @return The result of the match. 432 * @throws IllegalArgumentException 433 * if the horizon is negative. 434 * @throws IllegalStateException 435 * if the Scanner is closed. 436 */ findWithinHorizon(final Pattern pattern, final int horizon)437 public String findWithinHorizon (final Pattern pattern, final int horizon) 438 throws IllegalArgumentException, IllegalStateException 439 { 440 if (horizon < 0) 441 { 442 throw new IllegalArgumentException (horizon + " is negative"); 443 } 444 445 if (this.isClosed) 446 { 447 throw new IllegalStateException ("Scanner is closed"); 448 } 449 450 // doSkipp is set true to get the matching patern together with the found String 451 this.doSkipp = true; 452 String rc = myFindPInStr (pattern, this.actBuffer, horizon); 453 454 if (rc != null) 455 { 456 this.actPos += rc.length (); 457 } 458 459 return rc; 460 } 461 462 /** 463 * Compile the pattern and call {@link #findWithinHorizon(Pattern, 464 * int)}. 465 * 466 * @param pattern 467 * Pattern to search. 468 * @param horizon 469 * @return The result of the match. 470 * @throws IllegalArgumentException 471 * if the horizon is negative. 472 * @throws IllegalStateException 473 * if the Scanner is closed. 474 */ findWithinHorizon(final String pattern, final int horizon)475 public String findWithinHorizon (final String pattern, final int horizon) 476 throws IllegalArgumentException, IllegalStateException 477 { 478 return findWithinHorizon (Pattern.compile (pattern), horizon); 479 } 480 481 /** 482 * Checks if there is any next String using the current 483 * delimiter. Therefore the string must not be <code> null </code> 484 * and the length must be greater then 0. If a {@link 485 * NoSuchElementException} is thrown by the search method, it is 486 * catched and false is returned. 487 * 488 * @return <code> true </code> if there is any result using the current delimiter. This wouldn't 489 * lead to a {@link NoSuchElementException}. 490 * @throws IllegalStateException 491 * if the Scanner is closed. 492 */ hasNext()493 public boolean hasNext () throws IllegalStateException // TESTED 494 { 495 String tmpStr = null; 496 497 try 498 { 499 tmpStr = myCoreNext (false, this.p); 500 } 501 catch (NoSuchElementException nf) 502 { 503 } 504 505 if (tmpStr == null || tmpStr.length () <= 0) 506 { 507 return false; 508 } 509 return true; 510 } 511 512 /** 513 * Searches the pattern in the next subString before the next 514 * current delimiter. 515 * 516 * @param pattern 517 * The pattern to search for. 518 * @return <code> true </code> if the pattern is found before the current delimiter. 519 * @throws IllegalStateException 520 * if the Scanner is closed. 521 */ hasNext(final Pattern pattern)522 public boolean hasNext (final Pattern pattern) throws IllegalStateException // TESTED 523 { 524 String tmpStr; 525 526 tmpStr = myNext (pattern, false); 527 528 if (tmpStr == null || tmpStr.length () <= 0) 529 { 530 return false; 531 } 532 return true; 533 } 534 535 /** 536 * Compiles the pattern to a {@link Pattern} and calls {@link 537 * #hasNext(Pattern)}. 538 * 539 * @see #hasNext(Pattern) 540 * @param pattern 541 * The pattern as string to search for. 542 * @return <code> true </code> if the pattern is found before the current delimiter. 543 * @throws IllegalStateException 544 * if the Scanner is closed. 545 */ hasNext(final String pattern)546 public boolean hasNext (final String pattern) throws IllegalStateException // TESTED 547 { 548 return hasNext (Pattern.compile (pattern)); 549 } 550 551 /** 552 * Checks if the string to the next delimiter can be interpreted as 553 * a BigDecimal number. <br> BigDecimal numbers are always tryed 554 * with radix 10. 555 * 556 * @see #nextBigDecimal() 557 * @return <code> true </code> if the next string is a BigDecimal number. 558 * @throws IllegalStateException 559 * if the Scanner is closed. 560 */ hasNextBigDecimal()561 public boolean hasNextBigDecimal () throws IllegalStateException // TESTED 562 { 563 try 564 { 565 myBigDecimal (false); 566 return true; 567 } 568 catch (InputMismatchException nfe) 569 { 570 return false; 571 } 572 } 573 574 /** 575 * Checks if the string to the next delimiter can be interpreted as 576 * a BigInteger number. <br> Call {@link #hasNextBigInteger(int)} 577 * with the current radix. 578 * 579 * @see #nextBigInteger() 580 * @return <code> true </code> if the next string is a BigInteger number. 581 * @throws IllegalStateException 582 * if the Scanner is closed. 583 */ hasNextBigInteger()584 public boolean hasNextBigInteger () throws IllegalStateException // TESTED 585 { 586 return hasNextBigInteger (this.currentRadix); 587 } 588 589 /** 590 * Checks if the string to the next delimiter can be interpreted as 591 * a BigInteger number. <br> 592 * 593 * @param radix 594 * The radix to use for this check. The global radix of the Scanner will not be 595 * changed. 596 * @return <code> true </code> if the next string is a BigInteger number. 597 * @throws IllegalStateException 598 * if the Scanner is closed. 599 */ hasNextBigInteger(final int radix)600 public boolean hasNextBigInteger (final int radix) throws 601 IllegalStateException 602 { 603 try 604 { 605 myNextBigInteger (radix, false, BIG_INTEGER); 606 return true; 607 } 608 catch (InputMismatchException ime) 609 { 610 return false; 611 } 612 } 613 614 /** 615 * Checks if the next string could be a boolean. The method handles 616 * the input not case sensitiv, so "true" and "TRUE" and even "tRuE" 617 * are <code> true </code>. 618 * 619 * @see #nextBoolean() 620 * @return Return <code> true </code> if the next string is a boolean. 621 * @throws IllegalStateException 622 * if the Scanner is closed. 623 */ hasNextBoolean()624 public boolean hasNextBoolean () throws IllegalStateException // TESTED 625 { 626 try 627 { 628 myNextBoolean (false); 629 return true; 630 } 631 catch (InputMismatchException ime) 632 { 633 return false; 634 } 635 } 636 637 /** 638 * Checks if the string to the next delimiter can be interpreted as 639 * a byte number. <br> Calls {@link #hasNextByte(int)} with the 640 * current radix. 641 * 642 * @see #nextByte() 643 * @return <code> true </code> if the next string is a byte number. 644 * @throws IllegalStateException 645 * if the Scanner is closed. 646 */ hasNextByte()647 public boolean hasNextByte () throws IllegalStateException // TESTED 648 { 649 return hasNextByte (this.currentRadix); 650 } 651 652 /** 653 * Checks if the string to the next delimiter can be interpreted as 654 * a byte number with the given radix. <br> To check, the private 655 * method {@link #myNextByte(int, boolean)} is called, and if no 656 * error occurs the next string could be a byte. 657 * 658 * @see #nextByte(int) 659 * @param radix The radix to use for this check. The global radix of 660 * the Scanner will not be changed. 661 * @return <code> true </code> if the next string is a byte number. 662 * @throws IllegalStateException 663 * if the Scanner is closed. 664 */ hasNextByte(final int radix)665 public boolean hasNextByte (final int radix) throws IllegalStateException 666 { 667 try 668 { 669 myNextByte (radix, false); 670 return true; 671 } 672 catch (InputMismatchException ime) 673 { 674 return false; 675 } 676 } 677 678 /** 679 * Checks if the string to the next delimiter can be interpreted as 680 * a double number. <br> To check, the private method {@link 681 * #myNextDouble(boolean)} is called, and if no error occurs the 682 * next string could be a double. 683 * 684 * @see #nextDouble() 685 * @return <code> true </code> if the next string is a double number. 686 * @throws IllegalStateException 687 * if the Scanner is closed. 688 */ hasNextDouble()689 public boolean hasNextDouble () throws IllegalStateException // TESTED 690 { 691 try 692 { 693 myNextDouble (false); 694 return true; 695 } 696 catch (InputMismatchException ime) 697 { 698 return false; 699 } 700 } 701 702 /** 703 * Checks if the string to the next delimiter can be interpreted as 704 * a double number. Because every float is a double this is 705 * checked.<br> To check, the private method {@link 706 * #myNextDouble(boolean)} is called, and if no error occurs the 707 * next string could be a double. 708 * 709 * @see #nextFloat() 710 * @return <code> true </code> if the next string is a double number. 711 * @throws IllegalStateException 712 * if the Scanner is closed. 713 */ hasNextFloat()714 public boolean hasNextFloat () throws IllegalStateException // TESTED 715 { 716 try 717 { 718 myNextDouble (false); 719 // myNextFloat(false); 720 return true; 721 } 722 catch (InputMismatchException ime) 723 { 724 return false; 725 } 726 } 727 728 /** 729 * Checks if the string to the next delimiter can be interpreted as 730 * an int number. <br> To check, the private method {@link 731 * #myNextInt(int, boolean)} is called, and if no error occurs the 732 * next string could be an int. 733 * 734 * @see #nextInt(int) 735 * @return <code> true </code> if the next string is an int number. 736 * @throws IllegalStateException 737 * if the Scanner is closed. 738 */ hasNextInt()739 public boolean hasNextInt () throws IllegalStateException // TESTED 740 { 741 return hasNextInt (this.currentRadix); 742 } 743 744 /** 745 * Checks if the string to the next delimiter can be interpreted as 746 * an int number with the given radix. <br> To check, the private 747 * method {@link #myNextInt(int, boolean)} is called, and if no 748 * error occurs the next string could be an int. 749 * 750 * @see #nextInt(int) 751 * @param radix 752 * The radix to use for this check. The global radix of the Scanner will not be 753 * changed. 754 * @return <code> true </code> if the next string is an int number. 755 * @throws IllegalStateException 756 * if the Scanner is closed. 757 */ hasNextInt(final int radix)758 public boolean hasNextInt (final int radix) throws IllegalStateException 759 { 760 try 761 { 762 myNextInt (radix, false); 763 return true; 764 } 765 catch (InputMismatchException ime) 766 { 767 return false; 768 } 769 } 770 771 /** 772 * Checks if there is a current line, which ends at the next line 773 * break or the end of the input. 774 * 775 * @return <code> true </code> if there is a current line. 776 * @throws IllegalStateException 777 * if the Scanner is closed. 778 */ hasNextLine()779 public boolean hasNextLine () throws IllegalStateException // TESTED 780 { 781 return (myNextLine (false) != null); 782 } 783 784 /** 785 * Checks if the string to the next delimiter can be interpreted as 786 * a long number. <br> To check, the private method {@link 787 * #myNextLong(int, boolean)} is called, and if no error occurs the 788 * next string could be a long. 789 * 790 * @see #nextLong() 791 * @return <code> true </code> if the next string is a long number. 792 * @throws IllegalStateException 793 * if the Scanner is closed. 794 */ hasNextLong()795 public boolean hasNextLong () throws IllegalStateException // TESTED 796 { 797 return hasNextLong (this.currentRadix); 798 } 799 800 /** 801 * Checks if the string to the next delimiter can be interpreted as 802 * a long number with the given radix. <br> To check, the private 803 * method {@link #myNextLong(int, boolean)} is called, and if no 804 * error occurs the next string could be a long. 805 * 806 * @see #nextLong(int) 807 * @param radix 808 * The radix to use for this check. The global radix of the Scanner will not be 809 * changed. 810 * @return <code> true </code> if the next string is a long number. 811 * @throws IllegalStateException 812 * if the Scanner is closed. 813 */ hasNextLong(final int radix)814 public boolean hasNextLong (final int radix) throws IllegalStateException 815 { 816 try 817 { 818 myNextLong (radix, false); 819 return true; 820 } 821 catch (InputMismatchException ime) 822 { 823 return false; 824 } 825 } 826 827 /** 828 * Checks if the string to the next delimiter can be interpreted as 829 * a short number with the given radix. <br> To check, the private 830 * method {@link #myNextShort(int, boolean)} is called, and if no 831 * error occurs the next string could be a short. 832 * 833 * @see #nextShort(int) 834 * @return <code> true </code> if the next string is a short number. 835 * @throws IllegalStateException 836 * if the Scanner is closed. 837 */ hasNextShort()838 public boolean hasNextShort () throws IllegalStateException // TESTED 839 { 840 return hasNextShort (this.currentRadix); 841 } 842 843 /** 844 * Checks if the string to the next delimiter can be interpreted as 845 * a short number. <br> To check, the private method {@link 846 * #myNextShort(int, boolean)} is called, and if no error occurs the 847 * next string could be a short. 848 * 849 * @see #nextShort(int) 850 * @param radix 851 * The radix to use for this check. The global radix of the Scanner will not be 852 * changed. 853 * @return <code> true </code> if the next string is a short number. 854 * @throws IllegalStateException 855 * if the Scanner is closed. 856 */ hasNextShort(final int radix)857 public boolean hasNextShort (final int radix) throws IllegalStateException 858 { 859 try 860 { 861 myNextShort (radix, false); 862 return true; 863 } 864 catch (InputMismatchException ime) 865 { 866 return false; 867 } 868 } 869 870 /** 871 * Returns the last {@link IOException} occured. 872 * 873 * @return Returns the last {@link IOException}. 874 */ ioException()875 public IOException ioException () 876 { 877 return this.lastIOException; 878 } 879 880 /** 881 * Returns the current value of {@link #useLocale}. This is used to 882 * tell the Scanner if it should use the Locale format or just 883 * handle numbers of the default format. 884 * 885 * @see #setUseLocale(boolean) 886 * @return the useLoclae. 887 */ isUseLocale()888 public boolean isUseLocale () // TESTED 889 { 890 return this.useLocale; 891 } 892 893 /** 894 * Returns the current Locale. It is initialized with {@link 895 * Locale#getDefault()}. 896 * 897 * @see #useLocale(Locale) 898 * @return Returns the current Locale. 899 */ locale()900 public Locale locale () // TESTED 901 { 902 return this.actLocale; 903 } 904 905 /** 906 * Returns the last MatchResult found. This is updated after every 907 * successfully search. 908 * 909 * @return Returns the last {@link MatchResult} found. 910 */ match()911 public MatchResult match () // TESTED 912 { 913 return this.actResult; 914 } 915 916 /** 917 * Uses the current delimiter to find the next string in the 918 * buffer. If a string is found the current position is set after 919 * the delimiter, otherwise a {@link NoSuchElementException} is 920 * thrown. A successful match sets the matchResult. 921 * 922 * @see #match() 923 * @return Returns the next string of the buffer. 924 * @throws NoSuchElementException 925 * If no element was found an exception is thrown. 926 * @throws IllegalStateException 927 * If the Scanner is closed. 928 */ next()929 public String next () throws NoSuchElementException, IllegalStateException // TESTED 930 { 931 return myCoreNext (true, this.p); 932 } 933 934 /** 935 * Tries to match the buffer with the given pattern. The current 936 * delimiter will not be changed. 937 * 938 * @param pattern 939 * The pattern to match. 940 * @return Returns the next string matching the pattern. 941 * @throws NoSuchElementException 942 * If no element was found an exception is thrown. 943 * @throws IllegalStateException 944 * If the Scanner is closed. 945 */ next(final Pattern pattern)946 public String next (final Pattern pattern) throws NoSuchElementException, IllegalStateException // TESTED 947 { 948 return myNext (pattern, true); 949 } 950 951 /** 952 * Tries to match the buffer with the given pattern. The current 953 * delimiter will not be changed. Calls the {@link #next(Pattern)} 954 * with the compiled pattern. 955 * 956 * @see #next(Pattern) 957 * @param pattern 958 * The pattern to match. 959 * @return Returns the next string matching the pattern. 960 * @throws NoSuchElementException 961 * If no element was found an exception is thrown. 962 * @throws IllegalStateException 963 * If the Scanner is closed. 964 */ next(final String pattern)965 public String next (final String pattern) throws NoSuchElementException, IllegalStateException // TESTED 966 { 967 return next (Pattern.compile (pattern)); 968 } 969 970 /** 971 * Tries to interpret the next string as a BigDecimal value. 972 * 973 * @return Returns the BigDecimal value of the next string. 974 * @throws NoSuchElementException 975 * If no string is found or the string is not a BigDecimal. 976 * @throws IllegalStateException 977 * If the Scanner is closed. 978 */ nextBigDecimal()979 public BigDecimal nextBigDecimal () throws NoSuchElementException, IllegalStateException // TESTED 980 { 981 return myBigDecimal (true); 982 } 983 984 /** 985 * Tries to interpret the next string as a BigInteger value. Call 986 * {@link #nextBigInteger(int)} with the current radix as parameter, 987 * and return the value. 988 * 989 * @see #nextBigInteger(int) 990 * @return Returns the BigInteger value of the next string. 991 * @throws NoSuchElementException 992 * If no string is found or the string is not a BigInteger. 993 * @throws IllegalStateException 994 * If the Scanner is closed. 995 */ nextBigInteger()996 public BigInteger nextBigInteger () throws NoSuchElementException, IllegalStateException // TESTED 997 { 998 return nextBigInteger (this.currentRadix); 999 } 1000 1001 /** 1002 * Tries to interpret the next string as a BigInteger value with the 1003 * given radix. 1004 * 1005 * @param radix 1006 * The radix to be used for this BigInteger. The current radix of the Scanner is not 1007 * changed. 1008 * @return Returns the BigInteger value of the next string. 1009 * @throws NoSuchElementException 1010 * If no string is found or the string is not a BigInteger. 1011 * @throws IllegalStateException 1012 * If the Scanner is closed. 1013 */ nextBigInteger(final int radix)1014 public BigInteger nextBigInteger (final int radix) throws 1015 NoSuchElementException, IllegalStateException 1016 { 1017 return myNextBigInteger (radix, true, BIG_INTEGER); 1018 } 1019 1020 /** 1021 * Tries to interpret the next string to the delimiter as a boolean 1022 * value, ignoring case. 1023 * 1024 * @return Returns the boolean value of the next matching string or throws an exception. 1025 * @throws NoSuchElementException 1026 * If no string is found or the string is not a boolean. 1027 * @throws IllegalStateException 1028 * If the Scanner is closed. 1029 */ nextBoolean()1030 public boolean nextBoolean () throws NoSuchElementException, IllegalStateException // TESTED 1031 { 1032 return myNextBoolean (true); 1033 } 1034 1035 /** 1036 * Tries to interpret the next string as a byte value. Call {@link 1037 * #nextByte(int)} with the current radix as parameter, and return 1038 * the value. 1039 * 1040 * @see #nextByte(int) 1041 * @return Returns the byte value of the next string. 1042 * @throws NoSuchElementException 1043 * If no string is found or the string is not a byte 1044 * @throws IllegalStateException 1045 * If the Scanner is closed. 1046 */ nextByte()1047 public byte nextByte () throws NoSuchElementException, IllegalStateException // TESTED 1048 { 1049 return nextByte (this.currentRadix); 1050 } 1051 1052 /** 1053 * Tries to interpret the next string as a byte value with the given 1054 * radix. 1055 * 1056 * @param radix 1057 * The radix to be used for this byte. The current radix of the Scanner is not 1058 * changed. 1059 * @return Returns the byte value of the next string. 1060 * @throws NoSuchElementException 1061 * If no string is found or the string is not a byte. 1062 * @throws IllegalStateException 1063 * If the Scanner is closed. 1064 */ nextByte(final int radix)1065 public byte nextByte (final int radix) throws NoSuchElementException, 1066 IllegalStateException 1067 { 1068 return myNextByte (radix, true); 1069 } 1070 1071 /** 1072 * Tries to interpret the next string as a double value. 1073 * 1074 * @return Returns the int value of the next string. 1075 * @throws NoSuchElementException 1076 * If no string is found or the string is not a double. 1077 * @throws IllegalStateException 1078 * If the Scanner is closed. 1079 */ nextDouble()1080 public double nextDouble () throws NoSuchElementException, IllegalStateException // TESTED 1081 { 1082 return myNextDouble (true); 1083 } 1084 1085 /** 1086 * Tries to interpret the next string as a double value, and then 1087 * casts down to float. 1088 * 1089 * @return Returns the int value of the next string. 1090 * @throws NoSuchElementException 1091 * If no string is found or the string is not a double. 1092 * @throws IllegalStateException 1093 * If the Scanner is closed. 1094 */ nextFloat()1095 public float nextFloat () throws NoSuchElementException, IllegalStateException // TESTED 1096 { 1097 return (float) myNextDouble (true); 1098 // return myNextFloat(true); 1099 } 1100 1101 /** 1102 * Tries to interpret the next string as an int value. Calls {@link 1103 * #nextInt(int)} with the current radix as parameter, and return 1104 * the value. 1105 * 1106 * @see #nextInt(int) 1107 * @return Returns the int value of the next string. 1108 * @throws NoSuchElementException 1109 * If no string is found or the string is not an int. 1110 * @throws IllegalStateException 1111 * If the Scanner is closed. 1112 */ nextInt()1113 public int nextInt () throws NoSuchElementException, IllegalStateException // TESTED 1114 { 1115 return nextInt (this.currentRadix); 1116 } 1117 1118 /** 1119 * Tries to interpret the next string as an int value with the given 1120 * radix. 1121 * 1122 * @param radix 1123 * The radix to be used for this int. The current radix of the Scanner is not changed 1124 * @return Returns the int value of the next string. 1125 * @throws NoSuchElementException 1126 * If no string is found or the string is not an int. 1127 * @throws IllegalStateException 1128 * If the Scanner is closed. 1129 */ nextInt(final int radix)1130 public int nextInt (final int radix) throws NoSuchElementException, 1131 IllegalStateException 1132 { 1133 return myNextInt (radix, true); 1134 } 1135 1136 /** 1137 * Tries to match the system line seperator, and returns the current 1138 * line. 1139 * 1140 * @return Returns the current line. 1141 * @throws NoSuchElementException 1142 * If the current delimiter is not found. 1143 * @throws IllegalStateException 1144 * If the Scanner is closed. 1145 */ nextLine()1146 public String nextLine () throws NoSuchElementException, IllegalStateException // TESTED 1147 { 1148 return myNextLine (true); 1149 } 1150 1151 /** 1152 * Tries to interpret the next string as a long value. Calls {@link 1153 * #nextLong(int)} with the current radix as parameter, and return 1154 * the value. 1155 * 1156 * @see #nextLong(int) 1157 * @return Returns the long value of the next string. 1158 * @throws NoSuchElementException 1159 * If no string is found or the string is not a long. 1160 * @throws IllegalStateException 1161 * If the Scanner is closed. 1162 */ nextLong()1163 public long nextLong () throws NoSuchElementException, IllegalStateException // TESTED 1164 { 1165 return nextLong (this.currentRadix); 1166 } 1167 1168 /** 1169 * Tries to interpret the next string as a long value with the given 1170 * radix. 1171 * 1172 * @param radix 1173 * The radix to be used for this long. The current radix of the Scanner is not 1174 * changed 1175 * @return Returns the long value of the next string. 1176 * @throws NoSuchElementException 1177 * If no string is found or the string is not a long. 1178 * @throws IllegalStateException 1179 * If the Scanner is closed. 1180 */ nextLong(final int radix)1181 public long nextLong (final int radix) throws NoSuchElementException, 1182 IllegalStateException 1183 { 1184 return myNextLong (radix, true); 1185 } 1186 1187 /** 1188 * Tries to interpret the next string as a short value. Calls {@link 1189 * #nextShort(int)} with the current radix as parameter, and return 1190 * the value. 1191 * 1192 * @see #nextShort(int) 1193 * @return Returns the short value of the next string. 1194 * @throws NoSuchElementException 1195 * If no string is found or the string is not a short. 1196 */ nextShort()1197 public short nextShort () throws NoSuchElementException // TESTED 1198 { 1199 return nextShort (this.currentRadix); 1200 } 1201 1202 /** 1203 * Tries to interpret the next string as a short value with the 1204 * given radix. 1205 * 1206 * @param radix 1207 * The radix to be used for this short. The current radix of the Scanner is not 1208 * changed. 1209 * @return Returns the short value of the next string. 1210 * @throws NoSuchElementException 1211 * If no string is found or the string is not a short. 1212 */ nextShort(final int radix)1213 public short nextShort (final int radix) throws NoSuchElementException 1214 { 1215 return myNextShort (radix, true); 1216 } 1217 1218 /** 1219 * @return Returns the current radix. 1220 */ radix()1221 public int radix () 1222 { 1223 return this.currentRadix; 1224 } 1225 1226 /** 1227 * The remove operation is not supported by this implementation of 1228 * Iterator. 1229 */ remove()1230 public void remove () 1231 { 1232 } 1233 1234 /** 1235 * @param useLocale the useLocale to set. 1236 */ setUseLocale(final boolean useLocale)1237 public void setUseLocale (final boolean useLocale) // TESTED 1238 { 1239 this.useLocale = useLocale; 1240 } 1241 1242 /** 1243 * Skips the given pattern. Sets skipped <code>true</code>. 1244 * 1245 * @param pattern 1246 * Pattern which should be skipped. 1247 * @return <code>this</code> with the skipped buffer. 1248 * @throws NoSuchElementException 1249 * If the Pattern is not found. 1250 */ skip(final Pattern pattern)1251 public Scanner skip (final Pattern pattern) throws NoSuchElementException 1252 { 1253 this.doSkipp = true; 1254 int end; 1255 boolean found; 1256 Matcher matcher = pattern.matcher (this.actBuffer); 1257 matcher.region (this.actPos - 1, this.actBuffer.length ()); 1258 1259 found = matcher.find (); 1260 found = myFillBuffer_loop (matcher, this.actPos - 1, found); 1261 end = matcher.end (); 1262 1263 this.actPos = end + 1; 1264 1265 this.doSkipp = false; 1266 this.skipped = true; 1267 1268 actResult = null; 1269 1270 if (!found) 1271 { 1272 throw new NoSuchElementException (); 1273 } 1274 return this; 1275 } 1276 1277 /** 1278 * Skips a given pattern. Calls {@link #skip(Pattern)} with the 1279 * compiled pattern. 1280 * 1281 * @see #skip(Pattern) 1282 * @param pattern 1283 * Pattern which should be skipped. 1284 * @return <code>this</code> with the skipped buffer. 1285 */ skip(final String pattern)1286 public Scanner skip (final String pattern) 1287 { 1288 return skip (Pattern.compile (pattern)); 1289 } 1290 1291 /** 1292 * Returns the string representation of this Scanner. 1293 */ 1294 @Override toString()1295 public String toString () 1296 { 1297 String tmpStr2; 1298 String rc = this.getClass ().getName (); 1299 tmpStr2 = rc; 1300 tmpStr2 = "[delimiters=" + this.p.pattern () + "]"; 1301 rc += tmpStr2; 1302 tmpStr2 = "[position=" + (this.procesedChars + this.actPos) + "]"; 1303 rc += tmpStr2; 1304 tmpStr2 = "[match valid=" + this.matchValid + "]"; 1305 rc += tmpStr2; 1306 tmpStr2 = "[need input=" + this.needInput + "]"; 1307 rc += tmpStr2; 1308 tmpStr2 = "[source closed=" + this.isClosed + "]"; 1309 rc += tmpStr2; 1310 tmpStr2 = "[skipped=" + this.skipped + "]"; 1311 rc += tmpStr2; 1312 tmpStr2 = "[group separator=\\" + this.dfs.getGroupingSeparator () + "]"; 1313 rc += tmpStr2; 1314 tmpStr2 = "[decimal separator=\\" + this.dfs.getDecimalSeparator () + "]"; 1315 rc += tmpStr2; 1316 tmpStr2 = 1317 "[positive prefix=" + myConvert (this.df.getPositivePrefix ()) + "]"; 1318 rc += tmpStr2; 1319 tmpStr2 = 1320 "[negative prefix=" + myConvert (this.df.getNegativePrefix ()) + "]"; 1321 rc += tmpStr2; 1322 tmpStr2 = 1323 "[positive suffix=" + myConvert (this.df.getPositiveSuffix ()) + "]"; 1324 rc += tmpStr2; 1325 tmpStr2 = 1326 "[negative suffix=" + myConvert (this.df.getNegativeSuffix ()) + "]"; 1327 rc += tmpStr2; 1328 tmpStr2 = "[NaN string=" + myConvert (this.dfs.getNaN ()) + "]"; 1329 rc += tmpStr2; 1330 tmpStr2 = "[infinity string=" + myConvert (this.dfs.getInfinity ()) + "]"; 1331 rc += tmpStr2; 1332 return rc; 1333 } 1334 1335 /** 1336 * Sets the current pattern to the given parameter, and updates the 1337 * {@link Matcher} with the new pattern. 1338 * 1339 * @param pattern 1340 * The new pattern to use. 1341 * @return Returns the Scanner (<code>this</code>) with the new pattern. 1342 */ useDelimiter(final Pattern pattern)1343 public Scanner useDelimiter (final Pattern pattern) // TESTED 1344 { 1345 if (pattern != null) 1346 { 1347 this.p = pattern; 1348 this.myMatcher = this.p.matcher (this.actBuffer); 1349 } 1350 return this; 1351 } 1352 1353 /** 1354 * Sets the current pattern to the given parameter. Compiles the 1355 * pattern and calls {@link #useDelimiter(Pattern)} 1356 * 1357 * @see #useDelimiter(Pattern) 1358 * @param pattern 1359 * The new pattern to use. 1360 * @return Returns the Scanner (<code>this</code>) with the new pattern. 1361 */ useDelimiter(final String pattern)1362 public Scanner useDelimiter (final String pattern) // TESTED 1363 { 1364 return useDelimiter (Pattern.compile (pattern)); 1365 } 1366 1367 /** 1368 * Sets the current Locale to the given parameter. Formats and 1369 * Symbols are also set using the new Locale. 1370 * 1371 * @param locale The new Locale to use. If it is <code>null</code> 1372 * nothing happens. 1373 * @return Returns the Scanner (<code>this</code>) with the new Locale. 1374 */ useLocale(final Locale locale)1375 public Scanner useLocale (final Locale locale) // TESTED 1376 { 1377 if (locale != null) 1378 { 1379 this.actLocale = locale; 1380 this.actFormat = NumberFormat.getInstance (this.actLocale); 1381 this.dfs = new DecimalFormatSymbols (this.actLocale); 1382 this.df = (DecimalFormat) this.actFormat; 1383 } 1384 return this; 1385 } 1386 1387 /** 1388 * Sets the current radix to the current value if the given radix is 1389 * >= 2 and <= 36 otherwise an {@link IllegalArgumentException} is 1390 * thrown. 1391 * 1392 * @param radix 1393 * the new radix to use as default. 1394 * @return <code> this </code> with the new radix value. 1395 * @throws IllegalArgumentException 1396 * When the given radix is out of bounds. 1397 */ useRadix(final int radix)1398 public Scanner useRadix (final int radix) throws IllegalArgumentException 1399 { 1400 if (radix < 2 || radix > 36) 1401 { 1402 throw new IllegalArgumentException (); 1403 } 1404 this.currentRadix = radix; 1405 return this; 1406 } 1407 1408 /** 1409 * Checks if it is necessary to apply the current Locale on the 1410 * String. If so the String is converted using the {@link 1411 * NumberFormat#parse(String)} into a Number and then back to a 1412 * default stringrepresentation of that Number. 1413 * 1414 * @see #setUseLocale(boolean) 1415 * @param str 1416 * String to convert into another string. 1417 * @param radix Radix of the Number in the original string. It has 1418 * to be 10 for anything to happen. 1419 * @return Eighter the Stringrepresention of the number without the 1420 * Locale or an unchanged string. 1421 * @throws ParseException 1422 * if {@link NumberFormat#parse(String)} fails to parse. 1423 */ myApplyLocale(final String str, final int radix)1424 private String myApplyLocale (final String str, 1425 final int radix) throws ParseException 1426 { 1427 String rc; 1428 1429 if (this.useLocale && radix == 10) 1430 { 1431 rc = this.actFormat.parse (str).toString (); 1432 return rc; 1433 } 1434 1435 return str; 1436 } 1437 1438 /** 1439 * If {@link #useLocale} is set and radix is 10 the string is tryed 1440 * to be converted to string without Locale settings, because the 1441 * "normal" convert from Local has only double precision and it is 1442 * not enough for the about 50 digits of precision of the 1443 * BigDecimal. So in the first step the string is seperated into the 1444 * integer part which is converted to a long, and the fraction part 1445 * is appended afterwards. Between the integer and the fraction part 1446 * comes a ".". Finally the resulting string is returned. 1447 * 1448 * @see #setUseLocale(boolean) 1449 * @param str String representation of a BigDecimal number. 1450 * @return The default String representation (without Locale) of the 1451 * BigInteger. 1452 * @throws ParseException 1453 * If the String has more than one decimal seperators a parse exception is thrown. 1454 */ myApplyLocaleBD(final String str)1455 private String myApplyLocaleBD (final String str) throws ParseException 1456 { 1457 if (!this.useLocale || this.currentRadix != 10) 1458 { 1459 return str; 1460 } 1461 1462 String negPrefix = this.df.getNegativePrefix (); 1463 String negSuffix = this.df.getNegativeSuffix (); 1464 String posPrefix = this.df.getPositivePrefix (); 1465 String posSuffix = this.df.getPositiveSuffix (); 1466 1467 char d = this.dfs.getDecimalSeparator (); 1468 int begin1, begin2; 1469 boolean isNegativ = false; 1470 String parts = null; 1471 1472 String tmpStr1 = ""; 1473 1474 begin1 = str.indexOf (d); 1475 begin2 = str.indexOf (d, begin1 + 1); 1476 1477 if (begin2 > 0) 1478 { 1479 throw new ParseException ("more than one Decimal seperators", begin2); 1480 } 1481 1482 parts = str.substring (0, begin1); 1483 1484 if ((negPrefix.length () > 0 1485 && str.substring (0, negPrefix.length ()).equals (negPrefix)) 1486 || (negSuffix.length () > 0 1487 && str.substring (str.length () - 1488 negSuffix.length ()).equals (negSuffix))) 1489 { 1490 parts += negSuffix; 1491 isNegativ = true; 1492 } 1493 else 1494 if ((posPrefix.length () > 0 1495 && str.substring (0, posPrefix.length ()).equals (posPrefix)) 1496 || (posSuffix.length () > 0 1497 && str.substring (str.length () - 1498 posSuffix.length ()).equals (posSuffix))) 1499 { 1500 parts += posSuffix; 1501 } 1502 1503 tmpStr1 = this.actFormat.parse (parts).toString (); 1504 1505 if (isNegativ) 1506 { 1507 tmpStr1 += 1508 "." + str.substring (str.indexOf (d) + 1, 1509 str.length () - negSuffix.length ()); 1510 } 1511 else 1512 { 1513 tmpStr1 += 1514 "." + str.substring (str.indexOf (d) + 1, 1515 str.length () - posSuffix.length ()); 1516 } 1517 1518 return tmpStr1; 1519 } 1520 1521 /** 1522 * Tries to interpret the next String as a BigDecimal. Therfore the 1523 * next String is get with {@link #myCoreNext(boolean, Pattern)} and 1524 * then {@link #myApplyLocaleBD(String)} is called to convert the 1525 * String into a BigDecimal. 1526 * 1527 * @param delete 1528 * Should the found string be deleted or not. 1529 * @return Returns the BigDecimal value of the next string. 1530 * @throws InputMismatchException 1531 * If the string is not a BigDecimal 1532 */ myBigDecimal(final boolean delete)1533 private BigDecimal myBigDecimal (final boolean delete) throws 1534 InputMismatchException 1535 { 1536 BigDecimal rc; 1537 String tmp = myCoreNext (delete, this.p); 1538 try 1539 { 1540 tmp = myApplyLocaleBD (tmp); 1541 } 1542 catch (ParseException e) 1543 { 1544 throw new InputMismatchException (ERR_PREFIX + tmp + IS_NOT + 1545 "BigDecimal!!"); 1546 } 1547 rc = new BigDecimal (tmp); 1548 1549 return rc; 1550 } 1551 1552 /** 1553 * Applies suffix ("\E") and prefix ("\Q") if str.length != 0 Used 1554 * by the toString method. 1555 * 1556 * @param str 1557 * the string on which the suffix and prefix should be applied. 1558 * @return The new new string with the suffix and prefix. 1559 */ myConvert(final String str)1560 private String myConvert (final String str) 1561 { 1562 if (str != null && str.length () > 0) 1563 { 1564 return "\\Q" + str + "\\E"; 1565 } 1566 return str; 1567 } 1568 1569 /** 1570 * Searches the current Matcher for the current Pattern. If the end 1571 * is reached during the search it tried to read again from the 1572 * source. The search results are always saved in {@link #actResult} 1573 * which is returned when match() is called. If doSkip is true the 1574 * pattern is also taken. 1575 * 1576 * @param delete 1577 * if true the aktPos is set. 1578 * @param pattern 1579 * pattern to search for. 1580 * @return Returns the String which matches the pattern. 1581 * @throws NoSuchElementException 1582 * If the search has no result. 1583 */ myCoreNext(final boolean delete, final Pattern pattern)1584 private String myCoreNext (final boolean delete, final Pattern pattern) 1585 throws NoSuchElementException 1586 { 1587 if (this.isClosed) 1588 { 1589 throw new IllegalStateException ("Scanner closed"); 1590 } 1591 if (shallUseLastFound (pattern != null ? pattern : this.p)) 1592 { 1593 if (this.last_RegionEnd != this.myMatcher.regionEnd ()) 1594 { 1595 System.out.println (this.last_RegionEnd + " != " + 1596 this.myMatcher.regionEnd () + " (" + 1597 (this.last_RegionEnd - 1598 this.myMatcher.regionEnd ()) + ")"); 1599 } 1600 if (delete) 1601 { 1602 this.actPos = this.lastNextPos; 1603 this.lastFoundPresent = false; 1604 this.actResult = this.lastResult; 1605 } 1606 return this.lastFound; 1607 } 1608 1609 boolean found = false; 1610 int left; 1611 int endIndex; 1612 1613 String tmp2 = null; 1614 1615 if (this.actPos > this.MAX_PREFIX) 1616 { 1617 // skipp the processed chars so that the size of the buffer don't grow to much even with 1618 // huge files 1619 this.procesedChars += this.actPos; 1620 this.actBuffer = this.actBuffer.substring (this.actPos); 1621 this.actPos = 0; 1622 this.myMatcher = pattern.matcher (this.actBuffer); 1623 } 1624 1625 left = this.actBuffer.length () - this.actPos; 1626 if (left < this.MIN_BUF_LEN) 1627 { 1628 myFillBuffer (); 1629 } 1630 found = this.myMatcher.find (this.actPos); 1631 1632 found = myFillBuffer_loop (this.myMatcher, this.actPos, found); 1633 1634 this.needInput = false; 1635 1636 if (found) 1637 { 1638 if (this.doSkipp) 1639 { 1640 endIndex = this.myMatcher.end (); 1641 } 1642 else 1643 { 1644 endIndex = this.myMatcher.start (); 1645 } 1646 tmp2 = this.actBuffer.substring (this.actPos, endIndex); 1647 this.lastNextPos = this.myMatcher.end (); 1648 /* 1649 * if the delete flag is set, just set the current position after the end of the matched 1650 * pattern. 1651 */ 1652 if (delete) 1653 { 1654 this.actPos = this.lastNextPos; 1655 } 1656 else 1657 { 1658 this.lastFound = tmp2; 1659 this.lastFoundPresent = true; 1660 this.lastPatternHash = pattern.hashCode (); 1661 } 1662 this.last_RegionStart = this.myMatcher.regionStart (); 1663 this.last_RegionEnd = this.myMatcher.regionEnd (); 1664 this.last_anchor = this.myMatcher.hasAnchoringBounds (); 1665 this.last_transparent = this.myMatcher.hasTransparentBounds (); 1666 } 1667 else if (this.myMatcher.hitEnd ()) 1668 // the end of input is matched 1669 { 1670 tmp2 = this.actBuffer.substring (this.actPos); 1671 if (tmp2.length() == 0) 1672 tmp2 = null; 1673 this.lastNextPos = this.actBuffer.length (); 1674 if (delete) 1675 { 1676 this.actPos = this.lastNextPos; 1677 } 1678 else 1679 { 1680 this.lastFound = tmp2; 1681 this.lastFoundPresent = true; 1682 this.lastPatternHash = pattern.hashCode (); 1683 } 1684 this.last_RegionStart = this.myMatcher.regionStart (); 1685 this.last_RegionEnd = this.myMatcher.regionEnd (); 1686 this.last_anchor = this.myMatcher.hasAnchoringBounds (); 1687 this.last_transparent = this.myMatcher.hasTransparentBounds (); 1688 } 1689 else 1690 { 1691 /* 1692 * if no match found an Exception is throwed 1693 */ 1694 throw new NoSuchElementException (); 1695 } 1696 /* 1697 * change the Result only when a nextXXX() method was called, not if a hasNextXXX() method 1698 * is called 1699 */ 1700 if (delete) 1701 { 1702 this.actResult = this.myMatcher.toMatchResult (); 1703 1704 this.matchValid = this.actResult != null; 1705 } 1706 else 1707 { 1708 this.lastResult = this.myMatcher.toMatchResult (); 1709 } 1710 1711 this.skipped = this.doSkipp; 1712 this.doSkipp = false; 1713 1714 return tmp2; 1715 } 1716 1717 /** 1718 * Used to fill the String buffer from a source. Therfore the 3 1719 * possible sources are checked if they are not <code>null</code> 1720 * and this not used, otherwise the read method is called on the 1721 * source. If a charsetName is set and not <code>null</code> it is 1722 * applied to convert to String. 1723 */ myFillBuffer()1724 private void myFillBuffer () 1725 { 1726 int len; 1727 String tmpStr; 1728 CharBuffer cb = null; 1729 ByteBuffer bb = null; 1730 1731 if (this.bIS != null) 1732 { 1733 try 1734 { 1735 len = this.bIS.read (this.tmpBuffer); 1736 if (len < 0) 1737 { 1738 return; 1739 } 1740 if (this.charsetName != null) 1741 { 1742 tmpStr = new String (this.tmpBuffer, 0, len, this.charsetName); 1743 } 1744 else 1745 { 1746 tmpStr = new String (this.tmpBuffer, 0, len); 1747 } 1748 this.actBuffer += tmpStr; 1749 } 1750 catch (IOException e) 1751 { 1752 this.lastIOException = e; 1753 } 1754 } 1755 else if (this.readableSource != null) 1756 { 1757 try 1758 { 1759 cb = CharBuffer.allocate (1000); 1760 this.needInput = true; 1761 len = this.readableSource.read (cb); 1762 if (len < 0) 1763 { 1764 return; 1765 } 1766 this.needInput = false; 1767 tmpStr = new String (cb.array ()); 1768 this.actBuffer += tmpStr; 1769 } 1770 catch (IOException e) 1771 { 1772 this.lastIOException = e; 1773 } 1774 } 1775 else if (this.rbcSource != null) 1776 { 1777 try 1778 { 1779 bb = ByteBuffer.allocate (1000); 1780 this.needInput = true; 1781 len = this.rbcSource.read (bb); 1782 this.needInput = false; 1783 if (len < 0) 1784 { 1785 return; 1786 } 1787 if (this.charsetName != null) 1788 { 1789 tmpStr = new String (bb.array (), 0, len, this.charsetName); 1790 } 1791 else 1792 { 1793 tmpStr = new String (bb.array (), 0, len); 1794 } 1795 this.actBuffer += tmpStr; 1796 } 1797 catch (IOException e) 1798 { 1799 this.lastIOException = e; 1800 } 1801 } 1802 1803 this.myMatcher.reset (this.actBuffer); 1804 } 1805 1806 /** 1807 * A loop in which the {@link #myFillBuffer()} is called and checked 1808 * if the pattern is found in the matcher and if the buffersize 1809 * changes after the read. 1810 * 1811 * @param aktM 1812 * The current Matcher. 1813 * @param pos 1814 * Position from which the matcher should start matching. 1815 * @param found 1816 * if already found. 1817 * @return <code> true </code> if the matcher has found a match. 1818 */ myFillBuffer_loop(final Matcher aktM, final int pos, boolean found)1819 private boolean myFillBuffer_loop (final Matcher aktM, final int pos, 1820 boolean found) 1821 { 1822 int tmp; 1823 1824 tmp = this.actBuffer.length (); 1825 while (aktM.hitEnd () 1826 && ((this.bIS != null) || (this.readableSource != null) 1827 || (this.rbcSource != null))) 1828 { 1829 myFillBuffer (); 1830 if (tmp == this.actBuffer.length ()) 1831 { 1832 break; 1833 } 1834 found = aktM.find (pos); 1835 this.needInput = true; 1836 } 1837 return found; 1838 } 1839 1840 /** 1841 * Used to find the given pattern in the given string before the 1842 * given horizon. Therfore the current matcher is copied, and 1843 * overwritten using the given pattern and the given Sting. <br> 1844 * After the search the original values are restored, and skipped is 1845 * set <code> true </code>. 1846 * 1847 * @param pattern 1848 * Pattern which should be matched. 1849 * @param str 1850 * The String in which the pattern should be matched. 1851 * @param horizon 1852 * the horizon whithin the match should be, if 0 then it is ignored. 1853 * @return Returns the String in the given String that matches the pattern. 1854 */ myFindPInStr(final Pattern pattern, final String str, final int horizon)1855 private String myFindPInStr (final Pattern pattern, final String str, 1856 final int horizon) 1857 { 1858 String rc = null; 1859 int curPos = this.actPos; 1860 Matcher aktMatcher = this.myMatcher; 1861 1862 this.myMatcher = pattern.matcher (str); 1863 if (horizon > 0) 1864 { 1865 this.myMatcher.useAnchoringBounds (true); 1866 this.myMatcher.useTransparentBounds (true); 1867 this.myMatcher.region (this.actPos, this.actPos + horizon); 1868 } 1869 rc = myCoreNext (true, pattern); 1870 this.myMatcher = aktMatcher; 1871 1872 this.actPos = curPos; 1873 this.skipped = true; 1874 1875 return rc; 1876 } 1877 1878 /** 1879 * Used by the {@link #hasNext(Pattern)} and {@link #next(Pattern)} 1880 * methods. Therfore a substring is taken first to the current 1881 * delimiter, afterwards the given pattern is searched in this 1882 * subsring.<br> Finally the current Buffer and matcher (which have 1883 * been temporarily changed) are set back.<br> <br> The {@link 1884 * #skipped} is set <code> true </code>. 1885 * 1886 * @param pattern 1887 * Pattern to find until the current delimiter. 1888 * @param delete 1889 * Is <code> true </code> if a next method is called.<br> 1890 * Is <code> false </code> if a hasNext method is called. 1891 * @return Returns the String which is returned by the public methods. 1892 */ myNext(final Pattern pattern, final boolean delete)1893 private String myNext (final Pattern pattern, final boolean delete) 1894 { 1895 String tmpStr; 1896 Matcher aktMatcher = this.myMatcher; 1897 String result; 1898 String currBuffer = this.actBuffer; 1899 int currAktPos; 1900 1901 tmpStr = myCoreNext (delete, this.p); 1902 this.myMatcher = pattern.matcher (tmpStr); 1903 this.actBuffer = tmpStr; 1904 currAktPos = this.actPos; 1905 this.actPos = 0; 1906 result = myCoreNext (delete, pattern); 1907 this.actPos = currAktPos; 1908 1909 this.actBuffer = currBuffer; 1910 this.myMatcher = aktMatcher; 1911 this.skipped = true; 1912 1913 return result; 1914 } 1915 1916 /** 1917 * Calls the next() method internally to get the next String, and 1918 * trys to apply a locale which is only applied if the radix is 10 1919 * and useLocale is <code> true </code>. Afterwards it is tried to 1920 * call the Constructor of a {@link BigInteger} with the given 1921 * radix. 1922 * 1923 * @param radix The radix to use. 1924 * @param delete If the found String should be removed from input or 1925 * not. 1926 * @param name name of "BigInteger" in case of an Error. 1927 * @return Returns the new BigInteger created if there is no Error. 1928 * @throws InputMismatchException 1929 * If there is a {@link ParseException} or a {@link NumberFormatException}. 1930 */ myNextBigInteger(final int radix, final boolean delete, final String name)1931 private BigInteger myNextBigInteger (final int radix, final boolean delete, 1932 final String name) 1933 { 1934 BigInteger rc; 1935 String tmp = myPrepareForNext (this.p, delete); 1936 1937 try 1938 { 1939 tmp = myApplyLocale (tmp, radix); 1940 rc = new BigInteger (tmp, radix); 1941 return rc; 1942 } 1943 catch (NumberFormatException nfe) 1944 { 1945 } 1946 catch (ParseException e) 1947 { 1948 } 1949 throw new InputMismatchException (ERR_PREFIX + tmp + IS_NOT + name); 1950 } 1951 1952 /** 1953 * Checks if the next String is either "true" or "false", otherwise 1954 * an {@link InputMismatchException} is thrown. It ignores the case 1955 * of the string so that "true" and "TRUE" and even "TrUe" are 1956 * accepted. 1957 * 1958 * @param delete Should the found value be removed from the input or 1959 * not. 1960 * @return Returns the boolean value (if it is a boolean). 1961 * @throws InputMismatchException 1962 * If the next String is not a boolean. 1963 */ myNextBoolean(final boolean delete)1964 private boolean myNextBoolean (final boolean delete) throws 1965 InputMismatchException 1966 { 1967 String tmp = myPrepareForNext (this.p, delete); 1968 if (tmp.equalsIgnoreCase ("true")) 1969 { 1970 return true; 1971 } 1972 else if (tmp.equalsIgnoreCase ("false")) 1973 { 1974 return false; 1975 } 1976 else 1977 { 1978 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_BOOLEAN); 1979 } 1980 } 1981 1982 /** 1983 * Calls the {@link #myPrepareForNext(Pattern, boolean)} which calls 1984 * the {@link #myCoreNext(boolean, Pattern)} to return the next 1985 * String matching the current delimier. Afterwards it is tryed to 1986 * convert the String into a byte. Any Error will lead into a {@link 1987 * InputMismatchException}. 1988 * 1989 * @param radix The radix to use. 1990 * @param delete Should the found String be removed from the input. 1991 * @return Returns the byte value of the String. 1992 * @throws InputMismatchException if the next String is not a byte. 1993 */ myNextByte(final int radix, final boolean delete)1994 private byte myNextByte (final int radix, 1995 final boolean delete) throws InputMismatchException 1996 { 1997 byte rc; 1998 String tmp = myPrepareForNext (this.p, delete); 1999 2000 try 2001 { 2002 tmp = myApplyLocale (tmp, radix); 2003 rc = Byte.parseByte (tmp, radix); 2004 return rc; 2005 } 2006 catch (NumberFormatException nfe) 2007 { 2008 } 2009 catch (ParseException e) 2010 { 2011 } 2012 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_BYTE); 2013 } 2014 2015 /** 2016 * Tries to interpret the next String as a double value. To verify 2017 * if the double value is correct, it is converted back to a String 2018 * using the default Locale and this String is compared with the 2019 * String from which the double was converted. If the two Strings 2020 * don't match, an {@link InputMismatchException} is thrown.<br> 2021 * <br> The radix used is always 10 even if the global radix is 2022 * changed. 2023 * 2024 * @param delete Should the String be removed, if true it will be 2025 * also removed if the String is not a double value. 2026 * @return Returns the double value of the next String. 2027 * @throws InputMismatchException if the next String is not a 2028 * double. 2029 */ myNextDouble(final boolean delete)2030 private double myNextDouble (final boolean delete) throws 2031 InputMismatchException 2032 { 2033 double rc; 2034 String tmp = myPrepareForNext (this.p, delete); 2035 2036 try 2037 { 2038 tmp = myApplyLocale (tmp, 10); 2039 rc = Double.parseDouble (tmp); 2040 if (("" + rc).equals (tmp)) 2041 { 2042 return rc; 2043 } 2044 } 2045 catch (ParseException e) 2046 { 2047 } 2048 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_DOUBLE); 2049 } 2050 2051 /** 2052 * Tries to interpret the next String as an int value. Therfore 2053 * {@link #myApplyLocale(String, int)} decides if the current Locale 2054 * should be applied or not and then the result is parsed using 2055 * {@link Integer#parseInt(String, int)}. Any Error will lead to an 2056 * {@link InputMismatchException}. 2057 * 2058 * @param radix The radix to use. 2059 * @param delete <code> true </code> if the String should be deleted 2060 * from the input. 2061 * @return Returns the int value of the String. 2062 * @throws InputMismatchException if the next String is not an int. 2063 */ myNextInt(final int radix, final boolean delete)2064 private int myNextInt (final int radix, 2065 final boolean delete) throws InputMismatchException 2066 { 2067 int rc; 2068 String tmp = myPrepareForNext (this.p, delete); 2069 try 2070 { 2071 tmp = myApplyLocale (tmp, radix); 2072 rc = Integer.parseInt (tmp, radix); 2073 return rc; 2074 } 2075 catch (NumberFormatException nfe) 2076 { 2077 } 2078 catch (ParseException e) 2079 { 2080 } 2081 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_INT); 2082 } 2083 2084 /** 2085 * Finds the next line using the {@link #NEW_LINE} constant which is 2086 * set to the system specific line seperator. 2087 * 2088 * @param delete should the found line be deleted from the input. 2089 * @return the current line. 2090 */ myNextLine(final boolean delete)2091 private String myNextLine (final boolean delete) 2092 { 2093 return myPrepareForNext (Pattern.compile (NEW_LINE), delete); 2094 } 2095 2096 /** 2097 * Tries to interpret the next String as a long value with the given 2098 * radix. Therfore the {@link Long#parseLong(String, int)} is called 2099 * and every Error will lead into a {@link InputMismatchException}. 2100 * 2101 * @param radix The radix to be used. 2102 * @param delete Should the found String be deleted from the input. 2103 * @return the long value of the next String. 2104 * @throws InputMismatchException if the next String is not a long. 2105 */ myNextLong(final int radix, final boolean delete)2106 private long myNextLong (final int radix, 2107 final boolean delete) throws InputMismatchException 2108 { 2109 long rc; 2110 String tmp = myPrepareForNext (this.p, delete); 2111 2112 try 2113 { 2114 tmp = myApplyLocale (tmp, radix); 2115 rc = Long.parseLong (tmp, radix); 2116 return rc; 2117 } 2118 catch (NumberFormatException nfe) 2119 { 2120 } 2121 catch (ParseException e) 2122 { 2123 } 2124 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_LONG); 2125 } 2126 2127 /** 2128 * Tries to interpret the next String as a short value with the 2129 * given radix. Therfore the {@link Short#parseShort(String, int)} 2130 * is called and every Error will lead into a {@link 2131 * InputMismatchException} . 2132 * 2133 * @param radix 2134 * The radix to be used. 2135 * @param delete 2136 * Should the found String be deleted from the input. 2137 * @return the long value of the next String. 2138 * @throws InputMismatchException 2139 * if the next String is not a short. 2140 */ myNextShort(final int radix, final boolean delete)2141 private short myNextShort (final int radix, 2142 final boolean delete) throws 2143 InputMismatchException 2144 { 2145 short rc; 2146 String tmp = myPrepareForNext (this.p, delete); 2147 2148 try 2149 { 2150 tmp = myApplyLocale (tmp, radix); 2151 rc = Short.parseShort (tmp, radix); 2152 return rc; 2153 } 2154 catch (NumberFormatException nfe) 2155 { 2156 } 2157 catch (ParseException e) 2158 { 2159 } 2160 throw new InputMismatchException (ERR_PREFIX + tmp + 2161 "\" is not a short"); 2162 } 2163 2164 /** 2165 * Sets the current pattern to the given pattern and calls the 2166 * {@link #myCoreNext(boolean, Pattern)}. Finally sets the pattern 2167 * back to its old value. 2168 * 2169 * @param aktPattern Pattern to be used for the next match. 2170 * @param delete Should the found String be deleted or not. 2171 * @return Return the String returned from {@link 2172 * #myCoreNext(boolean, Pattern)}. 2173 */ myPrepareForNext(final Pattern aktPattern, final boolean delete)2174 private String myPrepareForNext (final Pattern aktPattern, 2175 final boolean delete) 2176 { 2177 2178 String rc; 2179 Pattern oldPattern = this.p; 2180 useDelimiter (aktPattern); 2181 2182 rc = myCoreNext (delete, aktPattern); 2183 2184 useDelimiter (oldPattern); 2185 2186 return rc; 2187 } 2188 2189 /** 2190 * Determinates if the last found can be used, so that after a 2191 * hasNextXXX the nextXXX has not to search if nothing has 2192 * changed.<br /> Used in {@link #myCoreNext(boolean, Pattern)}. 2193 * 2194 * @param aktP The pattern which should be checked. 2195 * @return <code> true </code> if the searchresult is already ready. 2196 */ shallUseLastFound(final Pattern aktP)2197 private boolean shallUseLastFound (final Pattern aktP) 2198 { 2199 if (this.lastFoundPresent && 2200 this.lastPatternHash == aktP.hashCode () && 2201 this.last_RegionStart == this.myMatcher.regionStart () && 2202 this.last_anchor == this.myMatcher.hasAnchoringBounds () && 2203 this.last_transparent == this.myMatcher.hasTransparentBounds ()) 2204 { 2205 if (this.last_RegionEnd != this.myMatcher.regionEnd ()) 2206 { 2207 int tmpVal = 2208 this.myMatcher.regionEnd () - 2209 this.last_RegionEnd - this.MAX_PREFIX; 2210 if (tmpVal > 0 && tmpVal < 20) 2211 { 2212 this.last_RegionEnd = 2213 this.myMatcher.regionEnd (); 2214 return true; 2215 } 2216 } 2217 else 2218 return true; 2219 } 2220 return false; 2221 } 2222 2223 } 2224