Frames | No Frames |
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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 1230: public void remove () 1231: { 1232: } 1233: 1234: /** 1235: * @param useLocale the useLocale to set. 1236: */ 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: */ 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: */ 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 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: }