1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.util; 28 29 import java.util.regex.*; 30 import java.io.*; 31 import java.math.*; 32 import java.nio.*; 33 import java.nio.channels.*; 34 import java.nio.charset.*; 35 import java.text.*; 36 import java.util.Locale; 37 38 import sun.misc.LRUCache; 39 40 /** 41 * A simple text scanner which can parse primitive types and strings using 42 * regular expressions. 43 * 44 * <p>A <code>Scanner</code> breaks its input into tokens using a 45 * delimiter pattern, which by default matches whitespace. The resulting 46 * tokens may then be converted into values of different types using the 47 * various <tt>next</tt> methods. 48 * 49 * <p>For example, this code allows a user to read a number from 50 * <tt>System.in</tt>: 51 * <blockquote><pre> 52 * Scanner sc = new Scanner(System.in); 53 * int i = sc.nextInt(); 54 * </pre></blockquote> 55 * 56 * <p>As another example, this code allows <code>long</code> types to be 57 * assigned from entries in a file <code>myNumbers</code>: 58 * <blockquote><pre> 59 * Scanner sc = new Scanner(new File("myNumbers")); 60 * while (sc.hasNextLong()) { 61 * long aLong = sc.nextLong(); 62 * }</pre></blockquote> 63 * 64 * <p>The scanner can also use delimiters other than whitespace. This 65 * example reads several items in from a string: 66 *<blockquote><pre> 67 * String input = "1 fish 2 fish red fish blue fish"; 68 * Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); 69 * System.out.println(s.nextInt()); 70 * System.out.println(s.nextInt()); 71 * System.out.println(s.next()); 72 * System.out.println(s.next()); 73 * s.close(); </pre></blockquote> 74 * <p> 75 * prints the following output: 76 * <blockquote><pre> 77 * 1 78 * 2 79 * red 80 * blue </pre></blockquote> 81 * 82 * <p>The same output can be generated with this code, which uses a regular 83 * expression to parse all four tokens at once: 84 *<blockquote><pre> 85 * String input = "1 fish 2 fish red fish blue fish"; 86 * Scanner s = new Scanner(input); 87 * s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"); 88 * MatchResult result = s.match(); 89 * for (int i=1; i<=result.groupCount(); i++) 90 * System.out.println(result.group(i)); 91 * s.close(); </pre></blockquote> 92 * 93 * <p>The <a name="default-delimiter">default whitespace delimiter</a> used 94 * by a scanner is as recognized by {@link java.lang.Character}.{@link 95 * java.lang.Character#isWhitespace(char) isWhitespace}. The {@link #reset} 96 * method will reset the value of the scanner's delimiter to the default 97 * whitespace delimiter regardless of whether it was previously changed. 98 * 99 * <p>A scanning operation may block waiting for input. 100 * 101 * <p>The {@link #next} and {@link #hasNext} methods and their 102 * primitive-type companion methods (such as {@link #nextInt} and 103 * {@link #hasNextInt}) first skip any input that matches the delimiter 104 * pattern, and then attempt to return the next token. Both <tt>hasNext</tt> 105 * and <tt>next</tt> methods may block waiting for further input. Whether a 106 * <tt>hasNext</tt> method blocks has no connection to whether or not its 107 * associated <tt>next</tt> method will block. 108 * 109 * <p> The {@link #findInLine}, {@link #findWithinHorizon}, and {@link #skip} 110 * methods operate independently of the delimiter pattern. These methods will 111 * attempt to match the specified pattern with no regard to delimiters in the 112 * input and thus can be used in special circumstances where delimiters are 113 * not relevant. These methods may block waiting for more input. 114 * 115 * <p>When a scanner throws an {@link InputMismatchException}, the scanner 116 * will not pass the token that caused the exception, so that it may be 117 * retrieved or skipped via some other method. 118 * 119 * <p>Depending upon the type of delimiting pattern, empty tokens may be 120 * returned. For example, the pattern <tt>"\\s+"</tt> will return no empty 121 * tokens since it matches multiple instances of the delimiter. The delimiting 122 * pattern <tt>"\\s"</tt> could return empty tokens since it only passes one 123 * space at a time. 124 * 125 * <p> A scanner can read text from any object which implements the {@link 126 * java.lang.Readable} interface. If an invocation of the underlying 127 * readable's {@link java.lang.Readable#read} method throws an {@link 128 * java.io.IOException} then the scanner assumes that the end of the input 129 * has been reached. The most recent <tt>IOException</tt> thrown by the 130 * underlying readable can be retrieved via the {@link #ioException} method. 131 * 132 * <p>When a <code>Scanner</code> is closed, it will close its input source 133 * if the source implements the {@link java.io.Closeable} interface. 134 * 135 * <p>A <code>Scanner</code> is not safe for multithreaded use without 136 * external synchronization. 137 * 138 * <p>Unless otherwise mentioned, passing a <code>null</code> parameter into 139 * any method of a <code>Scanner</code> will cause a 140 * <code>NullPointerException</code> to be thrown. 141 * 142 * <p>A scanner will default to interpreting numbers as decimal unless a 143 * different radix has been set by using the {@link #useRadix} method. The 144 * {@link #reset} method will reset the value of the scanner's radix to 145 * <code>10</code> regardless of whether it was previously changed. 146 * 147 * <a name="localized-numbers"> 148 * <h4> Localized numbers </h4> 149 * 150 * <p> An instance of this class is capable of scanning numbers in the standard 151 * formats as well as in the formats of the scanner's locale. A scanner's 152 * <a name="initial-locale">initial locale </a>is the value returned by the {@link 153 * java.util.Locale#getDefault} method; it may be changed via the {@link 154 * #useLocale} method. The {@link #reset} method will reset the value of the 155 * scanner's locale to the initial locale regardless of whether it was 156 * previously changed. 157 * 158 * <p>The localized formats are defined in terms of the following parameters, 159 * which for a particular locale are taken from that locale's {@link 160 * java.text.DecimalFormat DecimalFormat} object, <tt>df</tt>, and its and 161 * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object, 162 * <tt>dfs</tt>. 163 * 164 * <blockquote><table> 165 * <tr><td valign="top"><i>LocalGroupSeparator </i></td> 166 * <td valign="top">The character used to separate thousands groups, 167 * <i>i.e.,</i> <tt>dfs.</tt>{@link 168 * java.text.DecimalFormatSymbols#getGroupingSeparator 169 * getGroupingSeparator()}</td></tr> 170 * <tr><td valign="top"><i>LocalDecimalSeparator </i></td> 171 * <td valign="top">The character used for the decimal point, 172 * <i>i.e.,</i> <tt>dfs.</tt>{@link 173 * java.text.DecimalFormatSymbols#getDecimalSeparator 174 * getDecimalSeparator()}</td></tr> 175 * <tr><td valign="top"><i>LocalPositivePrefix </i></td> 176 * <td valign="top">The string that appears before a positive number (may 177 * be empty), <i>i.e.,</i> <tt>df.</tt>{@link 178 * java.text.DecimalFormat#getPositivePrefix 179 * getPositivePrefix()}</td></tr> 180 * <tr><td valign="top"><i>LocalPositiveSuffix </i></td> 181 * <td valign="top">The string that appears after a positive number (may be 182 * empty), <i>i.e.,</i> <tt>df.</tt>{@link 183 * java.text.DecimalFormat#getPositiveSuffix 184 * getPositiveSuffix()}</td></tr> 185 * <tr><td valign="top"><i>LocalNegativePrefix </i></td> 186 * <td valign="top">The string that appears before a negative number (may 187 * be empty), <i>i.e.,</i> <tt>df.</tt>{@link 188 * java.text.DecimalFormat#getNegativePrefix 189 * getNegativePrefix()}</td></tr> 190 * <tr><td valign="top"><i>LocalNegativeSuffix </i></td> 191 * <td valign="top">The string that appears after a negative number (may be 192 * empty), <i>i.e.,</i> <tt>df.</tt>{@link 193 * java.text.DecimalFormat#getNegativeSuffix 194 * getNegativeSuffix()}</td></tr> 195 * <tr><td valign="top"><i>LocalNaN </i></td> 196 * <td valign="top">The string that represents not-a-number for 197 * floating-point values, 198 * <i>i.e.,</i> <tt>dfs.</tt>{@link 199 * java.text.DecimalFormatSymbols#getNaN 200 * getNaN()}</td></tr> 201 * <tr><td valign="top"><i>LocalInfinity </i></td> 202 * <td valign="top">The string that represents infinity for floating-point 203 * values, <i>i.e.,</i> <tt>dfs.</tt>{@link 204 * java.text.DecimalFormatSymbols#getInfinity 205 * getInfinity()}</td></tr> 206 * </table></blockquote> 207 * 208 * <a name="number-syntax"> 209 * <h4> Number syntax </h4> 210 * 211 * <p> The strings that can be parsed as numbers by an instance of this class 212 * are specified in terms of the following regular-expression grammar, where 213 * Rmax is the highest digit in the radix being used (for example, Rmax is 9 214 * in base 10). 215 * 216 * <p> 217 * <table cellspacing=0 cellpadding=0 align=center> 218 * 219 * <tr><td valign=top align=right><i>NonASCIIDigit</i> ::</td> 220 * <td valign=top>= A non-ASCII character c for which 221 * {@link java.lang.Character#isDigit Character.isDigit}<tt>(c)</tt> 222 * returns true</td></tr> 223 * 224 * <tr><td> </td></tr> 225 * 226 * <tr><td align=right><i>Non0Digit</i> ::</td> 227 * <td><tt>= [1-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr> 228 * 229 * <tr><td> </td></tr> 230 * 231 * <tr><td align=right><i>Digit</i> ::</td> 232 * <td><tt>= [0-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr> 233 * 234 * <tr><td> </td></tr> 235 * 236 * <tr><td valign=top align=right><i>GroupedNumeral</i> ::</td> 237 * <td valign=top> 238 * <table cellpadding=0 cellspacing=0> 239 * <tr><td><tt>= ( </tt></td> 240 * <td><i>Non0Digit</i><tt> 241 * </tt><i>Digit</i><tt>? 242 * </tt><i>Digit</i><tt>?</tt></td></tr> 243 * <tr><td></td> 244 * <td><tt>( </tt><i>LocalGroupSeparator</i><tt> 245 * </tt><i>Digit</i><tt> 246 * </tt><i>Digit</i><tt> 247 * </tt><i>Digit</i><tt> )+ )</tt></td></tr> 248 * </table></td></tr> 249 * 250 * <tr><td> </td></tr> 251 * 252 * <tr><td align=right><i>Numeral</i> ::</td> 253 * <td><tt>= ( ( </tt><i>Digit</i><tt>+ ) 254 * | </tt><i>GroupedNumeral</i><tt> )</tt></td></tr> 255 * 256 * <tr><td> </td></tr> 257 * 258 * <tr><td valign=top align=right> 259 * <a name="Integer-regex"><i>Integer</i> ::</td> 260 * <td valign=top><tt>= ( [-+]? ( </tt><i>Numeral</i><tt> 261 * ) )</tt></td></tr> 262 * <tr><td></td> 263 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> </tt><i>Numeral</i><tt> 264 * </tt><i>LocalPositiveSuffix</i></td></tr> 265 * <tr><td></td> 266 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> </tt><i>Numeral</i><tt> 267 * </tt><i>LocalNegativeSuffix</i></td></tr> 268 * 269 * <tr><td> </td></tr> 270 * 271 * <tr><td align=right><i>DecimalNumeral</i> ::</td> 272 * <td><tt>= </tt><i>Numeral</i></td></tr> 273 * <tr><td></td> 274 * <td><tt>| </tt><i>Numeral</i><tt> 275 * </tt><i>LocalDecimalSeparator</i><tt> 276 * </tt><i>Digit</i><tt>*</tt></td></tr> 277 * <tr><td></td> 278 * <td><tt>| </tt><i>LocalDecimalSeparator</i><tt> 279 * </tt><i>Digit</i><tt>+</tt></td></tr> 280 * 281 * <tr><td> </td></tr> 282 * 283 * <tr><td align=right><i>Exponent</i> ::</td> 284 * <td><tt>= ( [eE] [+-]? </tt><i>Digit</i><tt>+ )</tt></td></tr> 285 * 286 * <tr><td> </td></tr> 287 * 288 * <tr><td align=right> 289 * <a name="Decimal-regex"><i>Decimal</i> ::</td> 290 * <td><tt>= ( [-+]? </tt><i>DecimalNumeral</i><tt> 291 * </tt><i>Exponent</i><tt>? )</tt></td></tr> 292 * <tr><td></td> 293 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> 294 * </tt><i>DecimalNumeral</i><tt> 295 * </tt><i>LocalPositiveSuffix</i> 296 * </tt><i>Exponent</i><tt>?</td></tr> 297 * <tr><td></td> 298 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> 299 * </tt><i>DecimalNumeral</i><tt> 300 * </tt><i>LocalNegativeSuffix</i> 301 * </tt><i>Exponent</i><tt>?</td></tr> 302 * 303 * <tr><td> </td></tr> 304 * 305 * <tr><td align=right><i>HexFloat</i> ::</td> 306 * <td><tt>= [-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+ 307 * ([pP][-+]?[0-9]+)?</tt></td></tr> 308 * 309 * <tr><td> </td></tr> 310 * 311 * <tr><td align=right><i>NonNumber</i> ::</td> 312 * <td valign=top><tt>= NaN 313 * | </tt><i>LocalNan</i><tt> 314 * | Infinity 315 * | </tt><i>LocalInfinity</i></td></tr> 316 * 317 * <tr><td> </td></tr> 318 * 319 * <tr><td align=right><i>SignedNonNumber</i> ::</td> 320 * <td><tt>= ( [-+]? </tt><i>NonNumber</i><tt> )</tt></td></tr> 321 * <tr><td></td> 322 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> 323 * </tt><i>NonNumber</i><tt> 324 * </tt><i>LocalPositiveSuffix</i></td></tr> 325 * <tr><td></td> 326 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> 327 * </tt><i>NonNumber</i><tt> 328 * </tt><i>LocalNegativeSuffix</i></td></tr> 329 * 330 * <tr><td> </td></tr> 331 * 332 * <tr><td valign=top align=right> 333 * <a name="Float-regex"><i>Float</i> ::</td> 334 * <td valign=top><tt>= </tt><i>Decimal</i><tt></td></tr> 335 * <tr><td></td> 336 * <td><tt>| </tt><i>HexFloat</i><tt></td></tr> 337 * <tr><td></td> 338 * <td><tt>| </tt><i>SignedNonNumber</i><tt></td></tr> 339 * 340 * </table> 341 * </center> 342 * 343 * <p> Whitespace is not significant in the above regular expressions. 344 * 345 * @since 1.5 346 */ 347 public final class Scanner implements Iterator<String>, Closeable { 348 349 // Internal buffer used to hold input 350 private CharBuffer buf; 351 352 // Size of internal character buffer 353 private static final int BUFFER_SIZE = 1024; // change to 1024; 354 355 // The index into the buffer currently held by the Scanner 356 private int position; 357 358 // Internal matcher used for finding delimiters 359 private Matcher matcher; 360 361 // Pattern used to delimit tokens 362 private Pattern delimPattern; 363 364 // Pattern found in last hasNext operation 365 private Pattern hasNextPattern; 366 367 // Position after last hasNext operation 368 private int hasNextPosition; 369 370 // Result after last hasNext operation 371 private String hasNextResult; 372 373 // The input source 374 private Readable source; 375 376 // Boolean is true if source is done 377 private boolean sourceClosed = false; 378 379 // Boolean indicating more input is required 380 private boolean needInput = false; 381 382 // Boolean indicating if a delim has been skipped this operation 383 private boolean skipped = false; 384 385 // A store of a position that the scanner may fall back to 386 private int savedScannerPosition = -1; 387 388 // A cache of the last primitive type scanned 389 private Object typeCache = null; 390 391 // Boolean indicating if a match result is available 392 private boolean matchValid = false; 393 394 // Boolean indicating if this scanner has been closed 395 private boolean closed = false; 396 397 // The current radix used by this scanner 398 private int radix = 10; 399 400 // The default radix for this scanner 401 private int defaultRadix = 10; 402 403 // The locale used by this scanner 404 private Locale locale = null; 405 406 // A cache of the last few recently used Patterns 407 private LRUCache<String,Pattern> patternCache = 408 new LRUCache<String,Pattern>(7) { 409 protected Pattern create(String s) { 410 return Pattern.compile(s); 411 } 412 protected boolean hasName(Pattern p, String s) { 413 return p.pattern().equals(s); 414 } 415 }; 416 417 // A holder of the last IOException encountered 418 private IOException lastException; 419 420 // A pattern for java whitespace 421 private static Pattern WHITESPACE_PATTERN = Pattern.compile( 422 "\\p{javaWhitespace}+"); 423 424 // A pattern for any token 425 private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*"); 426 427 // A pattern for non-ASCII digits 428 private static Pattern NON_ASCII_DIGIT = Pattern.compile( 429 "[\\p{javaDigit}&&[^0-9]]"); 430 431 // Fields and methods to support scanning primitive types 432 433 /** 434 * Locale dependent values used to scan numbers 435 */ 436 private String groupSeparator = "\\,"; 437 private String decimalSeparator = "\\."; 438 private String nanString = "NaN"; 439 private String infinityString = "Infinity"; 440 private String positivePrefix = ""; 441 private String negativePrefix = "\\-"; 442 private String positiveSuffix = ""; 443 private String negativeSuffix = ""; 444 445 /** 446 * Fields and an accessor method to match booleans 447 */ 448 private static volatile Pattern boolPattern; 449 private static final String BOOLEAN_PATTERN = "true|false"; boolPattern()450 private static Pattern boolPattern() { 451 Pattern bp = boolPattern; 452 if (bp == null) 453 boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN, 454 Pattern.CASE_INSENSITIVE); 455 return bp; 456 } 457 458 /** 459 * Fields and methods to match bytes, shorts, ints, and longs 460 */ 461 private Pattern integerPattern; 462 private String digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 463 private String non0Digit = "[\\p{javaDigit}&&[^0]]"; 464 private int SIMPLE_GROUP_INDEX = 5; buildIntegerPatternString()465 private String buildIntegerPatternString() { 466 String radixDigits = digits.substring(0, radix); 467 // Android changed : Support non-decimal starting digits. (i.e, a-z are valid radix digits). 468 String nonZeroRadixDigits = "((?i)[" + digits.substring(1, radix) + "]|(" + non0Digit + "))"; 469 470 // \\p{javaDigit} is not guaranteed to be appropriate 471 // here but what can we do? The final authority will be 472 // whatever parse method is invoked, so ultimately the 473 // Scanner will do the right thing 474 String digit = "((?i)["+radixDigits+"]|\\p{javaDigit})"; 475 // Android changed : Support non-decimal starting digits. 476 String groupedNumeral = "("+nonZeroRadixDigits+digit+"?"+digit+"?("+ 477 groupSeparator+digit+digit+digit+")+)"; 478 // digit++ is the possessive form which is necessary for reducing 479 // backtracking that would otherwise cause unacceptable performance 480 String numeral = "(("+ digit+"++)|"+groupedNumeral+")"; 481 String javaStyleInteger = "([-+]?(" + numeral + "))"; 482 String negativeInteger = negativePrefix + numeral + negativeSuffix; 483 String positiveInteger = positivePrefix + numeral + positiveSuffix; 484 return "("+ javaStyleInteger + ")|(" + 485 positiveInteger + ")|(" + 486 negativeInteger + ")"; 487 } integerPattern()488 private Pattern integerPattern() { 489 if (integerPattern == null) { 490 integerPattern = patternCache.forName(buildIntegerPatternString()); 491 } 492 return integerPattern; 493 } 494 495 /** 496 * Fields and an accessor method to match line separators 497 */ 498 private static volatile Pattern separatorPattern; 499 private static volatile Pattern linePattern; 500 private static final String LINE_SEPARATOR_PATTERN = 501 "\r\n|[\n\r\u2028\u2029\u0085]"; 502 private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$"; 503 separatorPattern()504 private static Pattern separatorPattern() { 505 Pattern sp = separatorPattern; 506 if (sp == null) 507 separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN); 508 return sp; 509 } 510 linePattern()511 private static Pattern linePattern() { 512 Pattern lp = linePattern; 513 if (lp == null) 514 linePattern = lp = Pattern.compile(LINE_PATTERN); 515 return lp; 516 } 517 518 /** 519 * Fields and methods to match floats and doubles 520 */ 521 private Pattern floatPattern; 522 private Pattern decimalPattern; buildFloatAndDecimalPattern()523 private void buildFloatAndDecimalPattern() { 524 // \\p{javaDigit} may not be perfect, see above 525 String digit = "([0-9]|(\\p{javaDigit}))"; 526 String exponent = "([eE][+-]?"+digit+"+)?"; 527 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+ 528 groupSeparator+digit+digit+digit+")+)"; 529 // Once again digit++ is used for performance, as above 530 String numeral = "(("+digit+"++)|"+groupedNumeral+")"; 531 String decimalNumeral = "("+numeral+"|"+numeral + 532 decimalSeparator + digit + "*+|"+ decimalSeparator + 533 digit + "++)"; 534 String nonNumber = "(NaN|"+nanString+"|Infinity|"+ 535 infinityString+")"; 536 String positiveFloat = "(" + positivePrefix + decimalNumeral + 537 positiveSuffix + exponent + ")"; 538 String negativeFloat = "(" + negativePrefix + decimalNumeral + 539 negativeSuffix + exponent + ")"; 540 String decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+ 541 positiveFloat + "|" + negativeFloat + ")"; 542 String hexFloat = 543 "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?"; 544 String positiveNonNumber = "(" + positivePrefix + nonNumber + 545 positiveSuffix + ")"; 546 String negativeNonNumber = "(" + negativePrefix + nonNumber + 547 negativeSuffix + ")"; 548 String signedNonNumber = "(([-+]?"+nonNumber+")|" + 549 positiveNonNumber + "|" + 550 negativeNonNumber + ")"; 551 floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" + 552 signedNonNumber); 553 decimalPattern = Pattern.compile(decimal); 554 } floatPattern()555 private Pattern floatPattern() { 556 if (floatPattern == null) { 557 buildFloatAndDecimalPattern(); 558 } 559 return floatPattern; 560 } decimalPattern()561 private Pattern decimalPattern() { 562 if (decimalPattern == null) { 563 buildFloatAndDecimalPattern(); 564 } 565 return decimalPattern; 566 } 567 568 // Constructors 569 570 /** 571 * Constructs a <code>Scanner</code> that returns values scanned 572 * from the specified source delimited by the specified pattern. 573 * 574 * @param source A character source implementing the Readable interface 575 * @param pattern A delimiting pattern 576 * @return A scanner with the specified source and pattern 577 */ Scanner(Readable source, Pattern pattern)578 private Scanner(Readable source, Pattern pattern) { 579 assert source != null : "source should not be null"; 580 assert pattern != null : "pattern should not be null"; 581 this.source = source; 582 delimPattern = pattern; 583 buf = CharBuffer.allocate(BUFFER_SIZE); 584 buf.limit(0); 585 matcher = delimPattern.matcher(buf); 586 matcher.useTransparentBounds(true); 587 matcher.useAnchoringBounds(false); 588 useLocale(Locale.getDefault(Locale.Category.FORMAT)); 589 } 590 591 /** 592 * Constructs a new <code>Scanner</code> that produces values scanned 593 * from the specified source. 594 * 595 * @param source A character source implementing the {@link Readable} 596 * interface 597 */ Scanner(Readable source)598 public Scanner(Readable source) { 599 this(Objects.requireNonNull(source, "source"), WHITESPACE_PATTERN); 600 } 601 602 /** 603 * Constructs a new <code>Scanner</code> that produces values scanned 604 * from the specified input stream. Bytes from the stream are converted 605 * into characters using the underlying platform's 606 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 607 * 608 * @param source An input stream to be scanned 609 */ Scanner(InputStream source)610 public Scanner(InputStream source) { 611 this(new InputStreamReader(source), WHITESPACE_PATTERN); 612 } 613 614 /** 615 * Constructs a new <code>Scanner</code> that produces values scanned 616 * from the specified input stream. Bytes from the stream are converted 617 * into characters using the specified charset. 618 * 619 * @param source An input stream to be scanned 620 * @param charsetName The encoding type used to convert bytes from the 621 * stream into characters to be scanned 622 * @throws IllegalArgumentException if the specified character set 623 * does not exist 624 */ Scanner(InputStream source, String charsetName)625 public Scanner(InputStream source, String charsetName) { 626 this(makeReadable(Objects.requireNonNull(source, "source"), toCharset(charsetName)), 627 WHITESPACE_PATTERN); 628 } 629 630 /** 631 * Returns a charset object for the given charset name. 632 * @throws NullPointerException is csn is null 633 * @throws IllegalArgumentException if the charset is not supported 634 */ toCharset(String csn)635 private static Charset toCharset(String csn) { 636 Objects.requireNonNull(csn, "charsetName"); 637 try { 638 return Charset.forName(csn); 639 } catch (IllegalCharsetNameException|UnsupportedCharsetException e) { 640 // IllegalArgumentException should be thrown 641 throw new IllegalArgumentException(e); 642 } 643 } 644 makeReadable(InputStream source, Charset charset)645 private static Readable makeReadable(InputStream source, Charset charset) { 646 return new InputStreamReader(source, charset); 647 } 648 649 /** 650 * Constructs a new <code>Scanner</code> that produces values scanned 651 * from the specified file. Bytes from the file are converted into 652 * characters using the underlying platform's 653 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 654 * 655 * @param source A file to be scanned 656 * @throws FileNotFoundException if source is not found 657 */ Scanner(File source)658 public Scanner(File source) throws FileNotFoundException { 659 this((ReadableByteChannel)(new FileInputStream(source).getChannel())); 660 } 661 662 /** 663 * Constructs a new <code>Scanner</code> that produces values scanned 664 * from the specified file. Bytes from the file are converted into 665 * characters using the specified charset. 666 * 667 * @param source A file to be scanned 668 * @param charsetName The encoding type used to convert bytes from the file 669 * into characters to be scanned 670 * @throws FileNotFoundException if source is not found 671 * @throws IllegalArgumentException if the specified encoding is 672 * not found 673 */ Scanner(File source, String charsetName)674 public Scanner(File source, String charsetName) 675 throws FileNotFoundException 676 { 677 this(Objects.requireNonNull(source), toDecoder(charsetName)); 678 } 679 Scanner(File source, CharsetDecoder dec)680 private Scanner(File source, CharsetDecoder dec) 681 throws FileNotFoundException 682 { 683 this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec)); 684 } 685 toDecoder(String charsetName)686 private static CharsetDecoder toDecoder(String charsetName) { 687 // Android-changed: Throw an IAE instead of an NPE. 688 // Objects.requireNonNull(charsetName, "charsetName"); 689 if (charsetName == null) { 690 throw new IllegalArgumentException("charsetName == null"); 691 } 692 try { 693 return Charset.forName(charsetName).newDecoder(); 694 } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { 695 throw new IllegalArgumentException(charsetName); 696 } 697 } 698 makeReadable(ReadableByteChannel source, CharsetDecoder dec)699 private static Readable makeReadable(ReadableByteChannel source, 700 CharsetDecoder dec) { 701 return Channels.newReader(source, dec, -1); 702 } 703 704 /** 705 * Constructs a new <code>Scanner</code> that produces values scanned 706 * from the specified string. 707 * 708 * @param source A string to scan 709 */ Scanner(String source)710 public Scanner(String source) { 711 this(new StringReader(source), WHITESPACE_PATTERN); 712 } 713 714 /** 715 * Constructs a new <code>Scanner</code> that produces values scanned 716 * from the specified channel. Bytes from the source are converted into 717 * characters using the underlying platform's 718 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 719 * 720 * @param source A channel to scan 721 */ Scanner(ReadableByteChannel source)722 public Scanner(ReadableByteChannel source) { 723 this(makeReadable(Objects.requireNonNull(source, "source")), 724 WHITESPACE_PATTERN); 725 } 726 makeReadable(ReadableByteChannel source)727 private static Readable makeReadable(ReadableByteChannel source) { 728 return makeReadable(source, Charset.defaultCharset().newDecoder()); 729 } 730 731 /** 732 * Constructs a new <code>Scanner</code> that produces values scanned 733 * from the specified channel. Bytes from the source are converted into 734 * characters using the specified charset. 735 * 736 * @param source A channel to scan 737 * @param charsetName The encoding type used to convert bytes from the 738 * channel into characters to be scanned 739 * @throws IllegalArgumentException if the specified character set 740 * does not exist 741 */ Scanner(ReadableByteChannel source, String charsetName)742 public Scanner(ReadableByteChannel source, String charsetName) { 743 this(makeReadable(Objects.requireNonNull(source, "source"), toDecoder(charsetName)), 744 WHITESPACE_PATTERN); 745 } 746 747 // Private primitives used to support scanning 748 saveState()749 private void saveState() { 750 savedScannerPosition = position; 751 } 752 revertState()753 private void revertState() { 754 this.position = savedScannerPosition; 755 savedScannerPosition = -1; 756 skipped = false; 757 } 758 revertState(boolean b)759 private boolean revertState(boolean b) { 760 this.position = savedScannerPosition; 761 savedScannerPosition = -1; 762 skipped = false; 763 return b; 764 } 765 cacheResult()766 private void cacheResult() { 767 hasNextResult = matcher.group(); 768 hasNextPosition = matcher.end(); 769 hasNextPattern = matcher.pattern(); 770 } 771 cacheResult(String result)772 private void cacheResult(String result) { 773 hasNextResult = result; 774 hasNextPosition = matcher.end(); 775 hasNextPattern = matcher.pattern(); 776 } 777 778 // Clears both regular cache and type cache clearCaches()779 private void clearCaches() { 780 hasNextPattern = null; 781 typeCache = null; 782 } 783 784 // Also clears both the regular cache and the type cache getCachedResult()785 private String getCachedResult() { 786 position = hasNextPosition; 787 hasNextPattern = null; 788 typeCache = null; 789 return hasNextResult; 790 } 791 792 // Also clears both the regular cache and the type cache useTypeCache()793 private void useTypeCache() { 794 if (closed) 795 throw new IllegalStateException("Scanner closed"); 796 position = hasNextPosition; 797 hasNextPattern = null; 798 typeCache = null; 799 } 800 801 // Tries to read more input. May block. readInput()802 private void readInput() { 803 if (buf.limit() == buf.capacity()) 804 makeSpace(); 805 806 // Prepare to receive data 807 int p = buf.position(); 808 buf.position(buf.limit()); 809 buf.limit(buf.capacity()); 810 811 int n = 0; 812 try { 813 n = source.read(buf); 814 } catch (IOException ioe) { 815 lastException = ioe; 816 n = -1; 817 } 818 819 if (n == -1) { 820 sourceClosed = true; 821 needInput = false; 822 } 823 824 if (n > 0) 825 needInput = false; 826 827 // Restore current position and limit for reading 828 buf.limit(buf.position()); 829 buf.position(p); 830 // Android changed : The matcher implementation eagerly calls toString() so we'll have 831 // to update its input whenever the buffer limit, position etc. changes. 832 matcher.reset(buf); 833 } 834 835 // After this method is called there will either be an exception 836 // or else there will be space in the buffer makeSpace()837 private boolean makeSpace() { 838 clearCaches(); 839 int offset = savedScannerPosition == -1 ? 840 position : savedScannerPosition; 841 buf.position(offset); 842 // Gain space by compacting buffer 843 if (offset > 0) { 844 buf.compact(); 845 translateSavedIndexes(offset); 846 position -= offset; 847 buf.flip(); 848 return true; 849 } 850 // Gain space by growing buffer 851 int newSize = buf.capacity() * 2; 852 CharBuffer newBuf = CharBuffer.allocate(newSize); 853 newBuf.put(buf); 854 newBuf.flip(); 855 translateSavedIndexes(offset); 856 position -= offset; 857 buf = newBuf; 858 matcher.reset(buf); 859 return true; 860 } 861 862 // When a buffer compaction/reallocation occurs the saved indexes must 863 // be modified appropriately translateSavedIndexes(int offset)864 private void translateSavedIndexes(int offset) { 865 if (savedScannerPosition != -1) 866 savedScannerPosition -= offset; 867 } 868 869 // If we are at the end of input then NoSuchElement; 870 // If there is still input left then InputMismatch throwFor()871 private void throwFor() { 872 skipped = false; 873 if ((sourceClosed) && (position == buf.limit())) 874 throw new NoSuchElementException(); 875 else 876 throw new InputMismatchException(); 877 } 878 879 // Returns true if a complete token or partial token is in the buffer. 880 // It is not necessary to find a complete token since a partial token 881 // means that there will be another token with or without more input. hasTokenInBuffer()882 private boolean hasTokenInBuffer() { 883 matchValid = false; 884 matcher.usePattern(delimPattern); 885 matcher.region(position, buf.limit()); 886 887 // Skip delims first 888 if (matcher.lookingAt()) 889 position = matcher.end(); 890 891 // If we are sitting at the end, no more tokens in buffer 892 if (position == buf.limit()) 893 return false; 894 895 return true; 896 } 897 898 /* 899 * Returns a "complete token" that matches the specified pattern 900 * 901 * A token is complete if surrounded by delims; a partial token 902 * is prefixed by delims but not postfixed by them 903 * 904 * The position is advanced to the end of that complete token 905 * 906 * Pattern == null means accept any token at all 907 * 908 * Triple return: 909 * 1. valid string means it was found 910 * 2. null with needInput=false means we won't ever find it 911 * 3. null with needInput=true means try again after readInput 912 */ getCompleteTokenInBuffer(Pattern pattern)913 private String getCompleteTokenInBuffer(Pattern pattern) { 914 matchValid = false; 915 916 // Skip delims first 917 matcher.usePattern(delimPattern); 918 if (!skipped) { // Enforcing only one skip of leading delims 919 matcher.region(position, buf.limit()); 920 if (matcher.lookingAt()) { 921 // If more input could extend the delimiters then we must wait 922 // for more input 923 if (matcher.hitEnd() && !sourceClosed) { 924 needInput = true; 925 return null; 926 } 927 // The delims were whole and the matcher should skip them 928 skipped = true; 929 position = matcher.end(); 930 } 931 } 932 933 // If we are sitting at the end, no more tokens in buffer 934 if (position == buf.limit()) { 935 if (sourceClosed) 936 return null; 937 needInput = true; 938 return null; 939 } 940 941 // Must look for next delims. Simply attempting to match the 942 // pattern at this point may find a match but it might not be 943 // the first longest match because of missing input, or it might 944 // match a partial token instead of the whole thing. 945 946 // Then look for next delims 947 matcher.region(position, buf.limit()); 948 boolean foundNextDelim = matcher.find(); 949 if (foundNextDelim && (matcher.end() == position)) { 950 // Zero length delimiter match; we should find the next one 951 // using the automatic advance past a zero length match; 952 // Otherwise we have just found the same one we just skipped 953 foundNextDelim = matcher.find(); 954 } 955 if (foundNextDelim) { 956 // In the rare case that more input could cause the match 957 // to be lost and there is more input coming we must wait 958 // for more input. Note that hitting the end is okay as long 959 // as the match cannot go away. It is the beginning of the 960 // next delims we want to be sure about, we don't care if 961 // they potentially extend further. 962 if (matcher.requireEnd() && !sourceClosed) { 963 needInput = true; 964 return null; 965 } 966 int tokenEnd = matcher.start(); 967 // There is a complete token. 968 if (pattern == null) { 969 // Must continue with match to provide valid MatchResult 970 pattern = FIND_ANY_PATTERN; 971 } 972 // Attempt to match against the desired pattern 973 matcher.usePattern(pattern); 974 matcher.region(position, tokenEnd); 975 if (matcher.matches()) { 976 String s = matcher.group(); 977 position = matcher.end(); 978 return s; 979 } else { // Complete token but it does not match 980 return null; 981 } 982 } 983 984 // If we can't find the next delims but no more input is coming, 985 // then we can treat the remainder as a whole token 986 if (sourceClosed) { 987 if (pattern == null) { 988 // Must continue with match to provide valid MatchResult 989 pattern = FIND_ANY_PATTERN; 990 } 991 // Last token; Match the pattern here or throw 992 matcher.usePattern(pattern); 993 matcher.region(position, buf.limit()); 994 if (matcher.matches()) { 995 String s = matcher.group(); 996 position = matcher.end(); 997 return s; 998 } 999 // Last piece does not match 1000 return null; 1001 } 1002 1003 // There is a partial token in the buffer; must read more 1004 // to complete it 1005 needInput = true; 1006 return null; 1007 } 1008 1009 // Finds the specified pattern in the buffer up to horizon. 1010 // Returns a match for the specified input pattern. findPatternInBuffer(Pattern pattern, int horizon)1011 private String findPatternInBuffer(Pattern pattern, int horizon) { 1012 matchValid = false; 1013 matcher.usePattern(pattern); 1014 int bufferLimit = buf.limit(); 1015 int horizonLimit = -1; 1016 int searchLimit = bufferLimit; 1017 if (horizon > 0) { 1018 horizonLimit = position + horizon; 1019 if (horizonLimit < bufferLimit) 1020 searchLimit = horizonLimit; 1021 } 1022 matcher.region(position, searchLimit); 1023 if (matcher.find()) { 1024 if (matcher.hitEnd() && (!sourceClosed)) { 1025 // The match may be longer if didn't hit horizon or real end 1026 if (searchLimit != horizonLimit) { 1027 // Hit an artificial end; try to extend the match 1028 needInput = true; 1029 return null; 1030 } 1031 // The match could go away depending on what is next 1032 if ((searchLimit == horizonLimit) && matcher.requireEnd()) { 1033 // Rare case: we hit the end of input and it happens 1034 // that it is at the horizon and the end of input is 1035 // required for the match. 1036 needInput = true; 1037 return null; 1038 } 1039 } 1040 // Did not hit end, or hit real end, or hit horizon 1041 position = matcher.end(); 1042 return matcher.group(); 1043 } 1044 1045 if (sourceClosed) 1046 return null; 1047 1048 // If there is no specified horizon, or if we have not searched 1049 // to the specified horizon yet, get more input 1050 if ((horizon == 0) || (searchLimit != horizonLimit)) 1051 needInput = true; 1052 return null; 1053 } 1054 1055 // Returns a match for the specified input pattern anchored at 1056 // the current position matchPatternInBuffer(Pattern pattern)1057 private String matchPatternInBuffer(Pattern pattern) { 1058 matchValid = false; 1059 matcher.usePattern(pattern); 1060 matcher.region(position, buf.limit()); 1061 if (matcher.lookingAt()) { 1062 if (matcher.hitEnd() && (!sourceClosed)) { 1063 // Get more input and try again 1064 needInput = true; 1065 return null; 1066 } 1067 position = matcher.end(); 1068 return matcher.group(); 1069 } 1070 1071 if (sourceClosed) 1072 return null; 1073 1074 // Read more to find pattern 1075 needInput = true; 1076 return null; 1077 } 1078 1079 // Throws if the scanner is closed ensureOpen()1080 private void ensureOpen() { 1081 if (closed) 1082 throw new IllegalStateException("Scanner closed"); 1083 } 1084 1085 // Public methods 1086 1087 /** 1088 * Closes this scanner. 1089 * 1090 * <p> If this scanner has not yet been closed then if its underlying 1091 * {@linkplain java.lang.Readable readable} also implements the {@link 1092 * java.io.Closeable} interface then the readable's <tt>close</tt> method 1093 * will be invoked. If this scanner is already closed then invoking this 1094 * method will have no effect. 1095 * 1096 * <p>Attempting to perform search operations after a scanner has 1097 * been closed will result in an {@link IllegalStateException}. 1098 * 1099 */ close()1100 public void close() { 1101 if (closed) 1102 return; 1103 if (source instanceof Closeable) { 1104 try { 1105 ((Closeable)source).close(); 1106 } catch (IOException ioe) { 1107 lastException = ioe; 1108 } 1109 } 1110 sourceClosed = true; 1111 source = null; 1112 closed = true; 1113 } 1114 1115 /** 1116 * Returns the <code>IOException</code> last thrown by this 1117 * <code>Scanner</code>'s underlying <code>Readable</code>. This method 1118 * returns <code>null</code> if no such exception exists. 1119 * 1120 * @return the last exception thrown by this scanner's readable 1121 */ ioException()1122 public IOException ioException() { 1123 return lastException; 1124 } 1125 1126 /** 1127 * Returns the <code>Pattern</code> this <code>Scanner</code> is currently 1128 * using to match delimiters. 1129 * 1130 * @return this scanner's delimiting pattern. 1131 */ delimiter()1132 public Pattern delimiter() { 1133 return delimPattern; 1134 } 1135 1136 /** 1137 * Sets this scanner's delimiting pattern to the specified pattern. 1138 * 1139 * @param pattern A delimiting pattern 1140 * @return this scanner 1141 */ useDelimiter(Pattern pattern)1142 public Scanner useDelimiter(Pattern pattern) { 1143 delimPattern = pattern; 1144 return this; 1145 } 1146 1147 /** 1148 * Sets this scanner's delimiting pattern to a pattern constructed from 1149 * the specified <code>String</code>. 1150 * 1151 * <p> An invocation of this method of the form 1152 * <tt>useDelimiter(pattern)</tt> behaves in exactly the same way as the 1153 * invocation <tt>useDelimiter(Pattern.compile(pattern))</tt>. 1154 * 1155 * <p> Invoking the {@link #reset} method will set the scanner's delimiter 1156 * to the <a href= "#default-delimiter">default</a>. 1157 * 1158 * @param pattern A string specifying a delimiting pattern 1159 * @return this scanner 1160 */ useDelimiter(String pattern)1161 public Scanner useDelimiter(String pattern) { 1162 delimPattern = patternCache.forName(pattern); 1163 return this; 1164 } 1165 1166 /** 1167 * Returns this scanner's locale. 1168 * 1169 * <p>A scanner's locale affects many elements of its default 1170 * primitive matching regular expressions; see 1171 * <a href= "#localized-numbers">localized numbers</a> above. 1172 * 1173 * @return this scanner's locale 1174 */ locale()1175 public Locale locale() { 1176 return this.locale; 1177 } 1178 1179 /** 1180 * Sets this scanner's locale to the specified locale. 1181 * 1182 * <p>A scanner's locale affects many elements of its default 1183 * primitive matching regular expressions; see 1184 * <a href= "#localized-numbers">localized numbers</a> above. 1185 * 1186 * <p>Invoking the {@link #reset} method will set the scanner's locale to 1187 * the <a href= "#initial-locale">initial locale</a>. 1188 * 1189 * @param locale A string specifying the locale to use 1190 * @return this scanner 1191 */ useLocale(Locale locale)1192 public Scanner useLocale(Locale locale) { 1193 if (locale.equals(this.locale)) 1194 return this; 1195 1196 this.locale = locale; 1197 DecimalFormat df = 1198 (DecimalFormat)NumberFormat.getNumberInstance(locale); 1199 DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale); 1200 1201 // These must be literalized to avoid collision with regex 1202 // metacharacters such as dot or parenthesis 1203 groupSeparator = "\\" + dfs.getGroupingSeparator(); 1204 decimalSeparator = "\\" + dfs.getDecimalSeparator(); 1205 1206 // Quoting the nonzero length locale-specific things 1207 // to avoid potential conflict with metacharacters 1208 nanString = "\\Q" + dfs.getNaN() + "\\E"; 1209 infinityString = "\\Q" + dfs.getInfinity() + "\\E"; 1210 positivePrefix = df.getPositivePrefix(); 1211 if (positivePrefix.length() > 0) 1212 positivePrefix = "\\Q" + positivePrefix + "\\E"; 1213 negativePrefix = df.getNegativePrefix(); 1214 if (negativePrefix.length() > 0) 1215 negativePrefix = "\\Q" + negativePrefix + "\\E"; 1216 positiveSuffix = df.getPositiveSuffix(); 1217 if (positiveSuffix.length() > 0) 1218 positiveSuffix = "\\Q" + positiveSuffix + "\\E"; 1219 negativeSuffix = df.getNegativeSuffix(); 1220 if (negativeSuffix.length() > 0) 1221 negativeSuffix = "\\Q" + negativeSuffix + "\\E"; 1222 1223 // Force rebuilding and recompilation of locale dependent 1224 // primitive patterns 1225 integerPattern = null; 1226 floatPattern = null; 1227 1228 return this; 1229 } 1230 1231 /** 1232 * Returns this scanner's default radix. 1233 * 1234 * <p>A scanner's radix affects elements of its default 1235 * number matching regular expressions; see 1236 * <a href= "#localized-numbers">localized numbers</a> above. 1237 * 1238 * @return the default radix of this scanner 1239 */ radix()1240 public int radix() { 1241 return this.defaultRadix; 1242 } 1243 1244 /** 1245 * Sets this scanner's default radix to the specified radix. 1246 * 1247 * <p>A scanner's radix affects elements of its default 1248 * number matching regular expressions; see 1249 * <a href= "#localized-numbers">localized numbers</a> above. 1250 * 1251 * <p>If the radix is less than <code>Character.MIN_RADIX</code> 1252 * or greater than <code>Character.MAX_RADIX</code>, then an 1253 * <code>IllegalArgumentException</code> is thrown. 1254 * 1255 * <p>Invoking the {@link #reset} method will set the scanner's radix to 1256 * <code>10</code>. 1257 * 1258 * @param radix The radix to use when scanning numbers 1259 * @return this scanner 1260 * @throws IllegalArgumentException if radix is out of range 1261 */ useRadix(int radix)1262 public Scanner useRadix(int radix) { 1263 if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX)) 1264 throw new IllegalArgumentException("radix:"+radix); 1265 1266 if (this.defaultRadix == radix) 1267 return this; 1268 this.defaultRadix = radix; 1269 // Force rebuilding and recompilation of radix dependent patterns 1270 integerPattern = null; 1271 return this; 1272 } 1273 1274 // The next operation should occur in the specified radix but 1275 // the default is left untouched. setRadix(int radix)1276 private void setRadix(int radix) { 1277 // Android-changed : Complain loudly if a bogus radix is being set. 1278 if (radix > Character.MAX_RADIX) { 1279 throw new IllegalArgumentException("radix == " + radix); 1280 } 1281 1282 if (this.radix != radix) { 1283 // Force rebuilding and recompilation of radix dependent patterns 1284 integerPattern = null; 1285 this.radix = radix; 1286 } 1287 } 1288 1289 /** 1290 * Returns the match result of the last scanning operation performed 1291 * by this scanner. This method throws <code>IllegalStateException</code> 1292 * if no match has been performed, or if the last match was 1293 * not successful. 1294 * 1295 * <p>The various <code>next</code>methods of <code>Scanner</code> 1296 * make a match result available if they complete without throwing an 1297 * exception. For instance, after an invocation of the {@link #nextInt} 1298 * method that returned an int, this method returns a 1299 * <code>MatchResult</code> for the search of the 1300 * <a href="#Integer-regex"><i>Integer</i></a> regular expression 1301 * defined above. Similarly the {@link #findInLine}, 1302 * {@link #findWithinHorizon}, and {@link #skip} methods will make a 1303 * match available if they succeed. 1304 * 1305 * @return a match result for the last match operation 1306 * @throws IllegalStateException If no match result is available 1307 */ match()1308 public MatchResult match() { 1309 if (!matchValid) 1310 throw new IllegalStateException("No match result available"); 1311 return matcher.toMatchResult(); 1312 } 1313 1314 /** 1315 * <p>Returns the string representation of this <code>Scanner</code>. The 1316 * string representation of a <code>Scanner</code> contains information 1317 * that may be useful for debugging. The exact format is unspecified. 1318 * 1319 * @return The string representation of this scanner 1320 */ toString()1321 public String toString() { 1322 StringBuilder sb = new StringBuilder(); 1323 sb.append("java.util.Scanner"); 1324 sb.append("[delimiters=" + delimPattern + "]"); 1325 sb.append("[position=" + position + "]"); 1326 sb.append("[match valid=" + matchValid + "]"); 1327 sb.append("[need input=" + needInput + "]"); 1328 sb.append("[source closed=" + sourceClosed + "]"); 1329 sb.append("[skipped=" + skipped + "]"); 1330 sb.append("[group separator=" + groupSeparator + "]"); 1331 sb.append("[decimal separator=" + decimalSeparator + "]"); 1332 sb.append("[positive prefix=" + positivePrefix + "]"); 1333 sb.append("[negative prefix=" + negativePrefix + "]"); 1334 sb.append("[positive suffix=" + positiveSuffix + "]"); 1335 sb.append("[negative suffix=" + negativeSuffix + "]"); 1336 sb.append("[NaN string=" + nanString + "]"); 1337 sb.append("[infinity string=" + infinityString + "]"); 1338 return sb.toString(); 1339 } 1340 1341 /** 1342 * Returns true if this scanner has another token in its input. 1343 * This method may block while waiting for input to scan. 1344 * The scanner does not advance past any input. 1345 * 1346 * @return true if and only if this scanner has another token 1347 * @throws IllegalStateException if this scanner is closed 1348 * @see java.util.Iterator 1349 */ hasNext()1350 public boolean hasNext() { 1351 ensureOpen(); 1352 saveState(); 1353 while (!sourceClosed) { 1354 if (hasTokenInBuffer()) 1355 return revertState(true); 1356 readInput(); 1357 } 1358 boolean result = hasTokenInBuffer(); 1359 return revertState(result); 1360 } 1361 1362 /** 1363 * Finds and returns the next complete token from this scanner. 1364 * A complete token is preceded and followed by input that matches 1365 * the delimiter pattern. This method may block while waiting for input 1366 * to scan, even if a previous invocation of {@link #hasNext} returned 1367 * <code>true</code>. 1368 * 1369 * @return the next token 1370 * @throws NoSuchElementException if no more tokens are available 1371 * @throws IllegalStateException if this scanner is closed 1372 * @see java.util.Iterator 1373 */ next()1374 public String next() { 1375 ensureOpen(); 1376 clearCaches(); 1377 1378 while (true) { 1379 String token = getCompleteTokenInBuffer(null); 1380 if (token != null) { 1381 matchValid = true; 1382 skipped = false; 1383 return token; 1384 } 1385 if (needInput) 1386 readInput(); 1387 else 1388 throwFor(); 1389 } 1390 } 1391 1392 /** 1393 * The remove operation is not supported by this implementation of 1394 * <code>Iterator</code>. 1395 * 1396 * @throws UnsupportedOperationException if this method is invoked. 1397 * @see java.util.Iterator 1398 */ remove()1399 public void remove() { 1400 throw new UnsupportedOperationException(); 1401 } 1402 1403 /** 1404 * Returns true if the next token matches the pattern constructed from the 1405 * specified string. The scanner does not advance past any input. 1406 * 1407 * <p> An invocation of this method of the form <tt>hasNext(pattern)</tt> 1408 * behaves in exactly the same way as the invocation 1409 * <tt>hasNext(Pattern.compile(pattern))</tt>. 1410 * 1411 * @param pattern a string specifying the pattern to scan 1412 * @return true if and only if this scanner has another token matching 1413 * the specified pattern 1414 * @throws IllegalStateException if this scanner is closed 1415 */ hasNext(String pattern)1416 public boolean hasNext(String pattern) { 1417 return hasNext(patternCache.forName(pattern)); 1418 } 1419 1420 /** 1421 * Returns the next token if it matches the pattern constructed from the 1422 * specified string. If the match is successful, the scanner advances 1423 * past the input that matched the pattern. 1424 * 1425 * <p> An invocation of this method of the form <tt>next(pattern)</tt> 1426 * behaves in exactly the same way as the invocation 1427 * <tt>next(Pattern.compile(pattern))</tt>. 1428 * 1429 * @param pattern a string specifying the pattern to scan 1430 * @return the next token 1431 * @throws NoSuchElementException if no such tokens are available 1432 * @throws IllegalStateException if this scanner is closed 1433 */ next(String pattern)1434 public String next(String pattern) { 1435 return next(patternCache.forName(pattern)); 1436 } 1437 1438 /** 1439 * Returns true if the next complete token matches the specified pattern. 1440 * A complete token is prefixed and postfixed by input that matches 1441 * the delimiter pattern. This method may block while waiting for input. 1442 * The scanner does not advance past any input. 1443 * 1444 * @param pattern the pattern to scan for 1445 * @return true if and only if this scanner has another token matching 1446 * the specified pattern 1447 * @throws IllegalStateException if this scanner is closed 1448 */ hasNext(Pattern pattern)1449 public boolean hasNext(Pattern pattern) { 1450 ensureOpen(); 1451 if (pattern == null) 1452 throw new NullPointerException(); 1453 hasNextPattern = null; 1454 saveState(); 1455 1456 while (true) { 1457 if (getCompleteTokenInBuffer(pattern) != null) { 1458 matchValid = true; 1459 cacheResult(); 1460 return revertState(true); 1461 } 1462 if (needInput) 1463 readInput(); 1464 else 1465 return revertState(false); 1466 } 1467 } 1468 1469 /** 1470 * Returns the next token if it matches the specified pattern. This 1471 * method may block while waiting for input to scan, even if a previous 1472 * invocation of {@link #hasNext(Pattern)} returned <code>true</code>. 1473 * If the match is successful, the scanner advances past the input that 1474 * matched the pattern. 1475 * 1476 * @param pattern the pattern to scan for 1477 * @return the next token 1478 * @throws NoSuchElementException if no more tokens are available 1479 * @throws IllegalStateException if this scanner is closed 1480 */ next(Pattern pattern)1481 public String next(Pattern pattern) { 1482 ensureOpen(); 1483 if (pattern == null) 1484 throw new NullPointerException(); 1485 1486 // Did we already find this pattern? 1487 if (hasNextPattern == pattern) 1488 return getCachedResult(); 1489 clearCaches(); 1490 1491 // Search for the pattern 1492 while (true) { 1493 String token = getCompleteTokenInBuffer(pattern); 1494 if (token != null) { 1495 matchValid = true; 1496 skipped = false; 1497 return token; 1498 } 1499 if (needInput) 1500 readInput(); 1501 else 1502 throwFor(); 1503 } 1504 } 1505 1506 /** 1507 * Returns true if there is another line in the input of this scanner. 1508 * This method may block while waiting for input. The scanner does not 1509 * advance past any input. 1510 * 1511 * @return true if and only if this scanner has another line of input 1512 * @throws IllegalStateException if this scanner is closed 1513 */ hasNextLine()1514 public boolean hasNextLine() { 1515 saveState(); 1516 1517 String result = findWithinHorizon(linePattern(), 0); 1518 if (result != null) { 1519 MatchResult mr = this.match(); 1520 String lineSep = mr.group(1); 1521 if (lineSep != null) { 1522 result = result.substring(0, result.length() - 1523 lineSep.length()); 1524 cacheResult(result); 1525 1526 } else { 1527 cacheResult(); 1528 } 1529 } 1530 revertState(); 1531 return (result != null); 1532 } 1533 1534 /** 1535 * Advances this scanner past the current line and returns the input 1536 * that was skipped. 1537 * 1538 * This method returns the rest of the current line, excluding any line 1539 * separator at the end. The position is set to the beginning of the next 1540 * line. 1541 * 1542 * <p>Since this method continues to search through the input looking 1543 * for a line separator, it may buffer all of the input searching for 1544 * the line to skip if no line separators are present. 1545 * 1546 * @return the line that was skipped 1547 * @throws NoSuchElementException if no line was found 1548 * @throws IllegalStateException if this scanner is closed 1549 */ nextLine()1550 public String nextLine() { 1551 if (hasNextPattern == linePattern()) 1552 return getCachedResult(); 1553 clearCaches(); 1554 1555 String result = findWithinHorizon(linePattern, 0); 1556 if (result == null) 1557 throw new NoSuchElementException("No line found"); 1558 MatchResult mr = this.match(); 1559 String lineSep = mr.group(1); 1560 if (lineSep != null) 1561 result = result.substring(0, result.length() - lineSep.length()); 1562 if (result == null) 1563 throw new NoSuchElementException(); 1564 else 1565 return result; 1566 } 1567 1568 // Public methods that ignore delimiters 1569 1570 /** 1571 * Attempts to find the next occurrence of a pattern constructed from the 1572 * specified string, ignoring delimiters. 1573 * 1574 * <p>An invocation of this method of the form <tt>findInLine(pattern)</tt> 1575 * behaves in exactly the same way as the invocation 1576 * <tt>findInLine(Pattern.compile(pattern))</tt>. 1577 * 1578 * @param pattern a string specifying the pattern to search for 1579 * @return the text that matched the specified pattern 1580 * @throws IllegalStateException if this scanner is closed 1581 */ findInLine(String pattern)1582 public String findInLine(String pattern) { 1583 return findInLine(patternCache.forName(pattern)); 1584 } 1585 1586 /** 1587 * Attempts to find the next occurrence of the specified pattern ignoring 1588 * delimiters. If the pattern is found before the next line separator, the 1589 * scanner advances past the input that matched and returns the string that 1590 * matched the pattern. 1591 * If no such pattern is detected in the input up to the next line 1592 * separator, then <code>null</code> is returned and the scanner's 1593 * position is unchanged. This method may block waiting for input that 1594 * matches the pattern. 1595 * 1596 * <p>Since this method continues to search through the input looking 1597 * for the specified pattern, it may buffer all of the input searching for 1598 * the desired token if no line separators are present. 1599 * 1600 * @param pattern the pattern to scan for 1601 * @return the text that matched the specified pattern 1602 * @throws IllegalStateException if this scanner is closed 1603 */ findInLine(Pattern pattern)1604 public String findInLine(Pattern pattern) { 1605 ensureOpen(); 1606 if (pattern == null) 1607 throw new NullPointerException(); 1608 clearCaches(); 1609 // Expand buffer to include the next newline or end of input 1610 int endPosition = 0; 1611 saveState(); 1612 while (true) { 1613 String token = findPatternInBuffer(separatorPattern(), 0); 1614 if (token != null) { 1615 endPosition = matcher.start(); 1616 break; // up to next newline 1617 } 1618 if (needInput) { 1619 readInput(); 1620 } else { 1621 endPosition = buf.limit(); 1622 break; // up to end of input 1623 } 1624 } 1625 revertState(); 1626 int horizonForLine = endPosition - position; 1627 // If there is nothing between the current pos and the next 1628 // newline simply return null, invoking findWithinHorizon 1629 // with "horizon=0" will scan beyond the line bound. 1630 if (horizonForLine == 0) 1631 return null; 1632 // Search for the pattern 1633 return findWithinHorizon(pattern, horizonForLine); 1634 } 1635 1636 /** 1637 * Attempts to find the next occurrence of a pattern constructed from the 1638 * specified string, ignoring delimiters. 1639 * 1640 * <p>An invocation of this method of the form 1641 * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as 1642 * the invocation 1643 * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>. 1644 * 1645 * @param pattern a string specifying the pattern to search for 1646 * @return the text that matched the specified pattern 1647 * @throws IllegalStateException if this scanner is closed 1648 * @throws IllegalArgumentException if horizon is negative 1649 */ findWithinHorizon(String pattern, int horizon)1650 public String findWithinHorizon(String pattern, int horizon) { 1651 return findWithinHorizon(patternCache.forName(pattern), horizon); 1652 } 1653 1654 /** 1655 * Attempts to find the next occurrence of the specified pattern. 1656 * 1657 * <p>This method searches through the input up to the specified 1658 * search horizon, ignoring delimiters. If the pattern is found the 1659 * scanner advances past the input that matched and returns the string 1660 * that matched the pattern. If no such pattern is detected then the 1661 * null is returned and the scanner's position remains unchanged. This 1662 * method may block waiting for input that matches the pattern. 1663 * 1664 * <p>A scanner will never search more than <code>horizon</code> code 1665 * points beyond its current position. Note that a match may be clipped 1666 * by the horizon; that is, an arbitrary match result may have been 1667 * different if the horizon had been larger. The scanner treats the 1668 * horizon as a transparent, non-anchoring bound (see {@link 1669 * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}). 1670 * 1671 * <p>If horizon is <code>0</code>, then the horizon is ignored and 1672 * this method continues to search through the input looking for the 1673 * specified pattern without bound. In this case it may buffer all of 1674 * the input searching for the pattern. 1675 * 1676 * <p>If horizon is negative, then an IllegalArgumentException is 1677 * thrown. 1678 * 1679 * @param pattern the pattern to scan for 1680 * @return the text that matched the specified pattern 1681 * @throws IllegalStateException if this scanner is closed 1682 * @throws IllegalArgumentException if horizon is negative 1683 */ findWithinHorizon(Pattern pattern, int horizon)1684 public String findWithinHorizon(Pattern pattern, int horizon) { 1685 ensureOpen(); 1686 if (pattern == null) 1687 throw new NullPointerException(); 1688 if (horizon < 0) 1689 throw new IllegalArgumentException("horizon < 0"); 1690 clearCaches(); 1691 1692 // Search for the pattern 1693 while (true) { 1694 String token = findPatternInBuffer(pattern, horizon); 1695 if (token != null) { 1696 matchValid = true; 1697 return token; 1698 } 1699 if (needInput) 1700 readInput(); 1701 else 1702 break; // up to end of input 1703 } 1704 return null; 1705 } 1706 1707 /** 1708 * Skips input that matches the specified pattern, ignoring delimiters. 1709 * This method will skip input if an anchored match of the specified 1710 * pattern succeeds. 1711 * 1712 * <p>If a match to the specified pattern is not found at the 1713 * current position, then no input is skipped and a 1714 * <tt>NoSuchElementException</tt> is thrown. 1715 * 1716 * <p>Since this method seeks to match the specified pattern starting at 1717 * the scanner's current position, patterns that can match a lot of 1718 * input (".*", for example) may cause the scanner to buffer a large 1719 * amount of input. 1720 * 1721 * <p>Note that it is possible to skip something without risking a 1722 * <code>NoSuchElementException</code> by using a pattern that can 1723 * match nothing, e.g., <code>sc.skip("[ \t]*")</code>. 1724 * 1725 * @param pattern a string specifying the pattern to skip over 1726 * @return this scanner 1727 * @throws NoSuchElementException if the specified pattern is not found 1728 * @throws IllegalStateException if this scanner is closed 1729 */ skip(Pattern pattern)1730 public Scanner skip(Pattern pattern) { 1731 ensureOpen(); 1732 if (pattern == null) 1733 throw new NullPointerException(); 1734 clearCaches(); 1735 1736 // Search for the pattern 1737 while (true) { 1738 String token = matchPatternInBuffer(pattern); 1739 if (token != null) { 1740 matchValid = true; 1741 position = matcher.end(); 1742 return this; 1743 } 1744 if (needInput) 1745 readInput(); 1746 else 1747 throw new NoSuchElementException(); 1748 } 1749 } 1750 1751 /** 1752 * Skips input that matches a pattern constructed from the specified 1753 * string. 1754 * 1755 * <p> An invocation of this method of the form <tt>skip(pattern)</tt> 1756 * behaves in exactly the same way as the invocation 1757 * <tt>skip(Pattern.compile(pattern))</tt>. 1758 * 1759 * @param pattern a string specifying the pattern to skip over 1760 * @return this scanner 1761 * @throws IllegalStateException if this scanner is closed 1762 */ skip(String pattern)1763 public Scanner skip(String pattern) { 1764 return skip(patternCache.forName(pattern)); 1765 } 1766 1767 // Convenience methods for scanning primitives 1768 1769 /** 1770 * Returns true if the next token in this scanner's input can be 1771 * interpreted as a boolean value using a case insensitive pattern 1772 * created from the string "true|false". The scanner does not 1773 * advance past the input that matched. 1774 * 1775 * @return true if and only if this scanner's next token is a valid 1776 * boolean value 1777 * @throws IllegalStateException if this scanner is closed 1778 */ hasNextBoolean()1779 public boolean hasNextBoolean() { 1780 return hasNext(boolPattern()); 1781 } 1782 1783 /** 1784 * Scans the next token of the input into a boolean value and returns 1785 * that value. This method will throw <code>InputMismatchException</code> 1786 * if the next token cannot be translated into a valid boolean value. 1787 * If the match is successful, the scanner advances past the input that 1788 * matched. 1789 * 1790 * @return the boolean scanned from the input 1791 * @throws InputMismatchException if the next token is not a valid boolean 1792 * @throws NoSuchElementException if input is exhausted 1793 * @throws IllegalStateException if this scanner is closed 1794 */ nextBoolean()1795 public boolean nextBoolean() { 1796 clearCaches(); 1797 return Boolean.parseBoolean(next(boolPattern())); 1798 } 1799 1800 /** 1801 * Returns true if the next token in this scanner's input can be 1802 * interpreted as a byte value in the default radix using the 1803 * {@link #nextByte} method. The scanner does not advance past any input. 1804 * 1805 * @return true if and only if this scanner's next token is a valid 1806 * byte value 1807 * @throws IllegalStateException if this scanner is closed 1808 */ hasNextByte()1809 public boolean hasNextByte() { 1810 return hasNextByte(defaultRadix); 1811 } 1812 1813 /** 1814 * Returns true if the next token in this scanner's input can be 1815 * interpreted as a byte value in the specified radix using the 1816 * {@link #nextByte} method. The scanner does not advance past any input. 1817 * 1818 * @param radix the radix used to interpret the token as a byte value 1819 * @return true if and only if this scanner's next token is a valid 1820 * byte value 1821 * @throws IllegalStateException if this scanner is closed 1822 */ hasNextByte(int radix)1823 public boolean hasNextByte(int radix) { 1824 setRadix(radix); 1825 boolean result = hasNext(integerPattern()); 1826 if (result) { // Cache it 1827 try { 1828 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 1829 processIntegerToken(hasNextResult) : 1830 hasNextResult; 1831 typeCache = Byte.parseByte(s, radix); 1832 } catch (NumberFormatException nfe) { 1833 result = false; 1834 } 1835 } 1836 return result; 1837 } 1838 1839 /** 1840 * Scans the next token of the input as a <tt>byte</tt>. 1841 * 1842 * <p> An invocation of this method of the form 1843 * <tt>nextByte()</tt> behaves in exactly the same way as the 1844 * invocation <tt>nextByte(radix)</tt>, where <code>radix</code> 1845 * is the default radix of this scanner. 1846 * 1847 * @return the <tt>byte</tt> scanned from the input 1848 * @throws InputMismatchException 1849 * if the next token does not match the <i>Integer</i> 1850 * regular expression, or is out of range 1851 * @throws NoSuchElementException if input is exhausted 1852 * @throws IllegalStateException if this scanner is closed 1853 */ nextByte()1854 public byte nextByte() { 1855 return nextByte(defaultRadix); 1856 } 1857 1858 /** 1859 * Scans the next token of the input as a <tt>byte</tt>. 1860 * This method will throw <code>InputMismatchException</code> 1861 * if the next token cannot be translated into a valid byte value as 1862 * described below. If the translation is successful, the scanner advances 1863 * past the input that matched. 1864 * 1865 * <p> If the next token matches the <a 1866 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 1867 * above then the token is converted into a <tt>byte</tt> value as if by 1868 * removing all locale specific prefixes, group separators, and locale 1869 * specific suffixes, then mapping non-ASCII digits into ASCII 1870 * digits via {@link Character#digit Character.digit}, prepending a 1871 * negative sign (-) if the locale specific negative prefixes and suffixes 1872 * were present, and passing the resulting string to 1873 * {@link Byte#parseByte(String, int) Byte.parseByte} with the 1874 * specified radix. 1875 * 1876 * @param radix the radix used to interpret the token as a byte value 1877 * @return the <tt>byte</tt> scanned from the input 1878 * @throws InputMismatchException 1879 * if the next token does not match the <i>Integer</i> 1880 * regular expression, or is out of range 1881 * @throws NoSuchElementException if input is exhausted 1882 * @throws IllegalStateException if this scanner is closed 1883 */ nextByte(int radix)1884 public byte nextByte(int radix) { 1885 // Check cached result 1886 if ((typeCache != null) && (typeCache instanceof Byte) 1887 && this.radix == radix) { 1888 byte val = ((Byte)typeCache).byteValue(); 1889 useTypeCache(); 1890 return val; 1891 } 1892 setRadix(radix); 1893 clearCaches(); 1894 // Search for next byte 1895 try { 1896 String s = next(integerPattern()); 1897 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 1898 s = processIntegerToken(s); 1899 return Byte.parseByte(s, radix); 1900 } catch (NumberFormatException nfe) { 1901 position = matcher.start(); // don't skip bad token 1902 throw new InputMismatchException(nfe.getMessage()); 1903 } 1904 } 1905 1906 /** 1907 * Returns true if the next token in this scanner's input can be 1908 * interpreted as a short value in the default radix using the 1909 * {@link #nextShort} method. The scanner does not advance past any input. 1910 * 1911 * @return true if and only if this scanner's next token is a valid 1912 * short value in the default radix 1913 * @throws IllegalStateException if this scanner is closed 1914 */ hasNextShort()1915 public boolean hasNextShort() { 1916 return hasNextShort(defaultRadix); 1917 } 1918 1919 /** 1920 * Returns true if the next token in this scanner's input can be 1921 * interpreted as a short value in the specified radix using the 1922 * {@link #nextShort} method. The scanner does not advance past any input. 1923 * 1924 * @param radix the radix used to interpret the token as a short value 1925 * @return true if and only if this scanner's next token is a valid 1926 * short value in the specified radix 1927 * @throws IllegalStateException if this scanner is closed 1928 */ hasNextShort(int radix)1929 public boolean hasNextShort(int radix) { 1930 setRadix(radix); 1931 boolean result = hasNext(integerPattern()); 1932 if (result) { // Cache it 1933 try { 1934 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 1935 processIntegerToken(hasNextResult) : 1936 hasNextResult; 1937 typeCache = Short.parseShort(s, radix); 1938 } catch (NumberFormatException nfe) { 1939 result = false; 1940 } 1941 } 1942 return result; 1943 } 1944 1945 /** 1946 * Scans the next token of the input as a <tt>short</tt>. 1947 * 1948 * <p> An invocation of this method of the form 1949 * <tt>nextShort()</tt> behaves in exactly the same way as the 1950 * invocation <tt>nextShort(radix)</tt>, where <code>radix</code> 1951 * is the default radix of this scanner. 1952 * 1953 * @return the <tt>short</tt> scanned from the input 1954 * @throws InputMismatchException 1955 * if the next token does not match the <i>Integer</i> 1956 * regular expression, or is out of range 1957 * @throws NoSuchElementException if input is exhausted 1958 * @throws IllegalStateException if this scanner is closed 1959 */ nextShort()1960 public short nextShort() { 1961 return nextShort(defaultRadix); 1962 } 1963 1964 /** 1965 * Scans the next token of the input as a <tt>short</tt>. 1966 * This method will throw <code>InputMismatchException</code> 1967 * if the next token cannot be translated into a valid short value as 1968 * described below. If the translation is successful, the scanner advances 1969 * past the input that matched. 1970 * 1971 * <p> If the next token matches the <a 1972 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 1973 * above then the token is converted into a <tt>short</tt> value as if by 1974 * removing all locale specific prefixes, group separators, and locale 1975 * specific suffixes, then mapping non-ASCII digits into ASCII 1976 * digits via {@link Character#digit Character.digit}, prepending a 1977 * negative sign (-) if the locale specific negative prefixes and suffixes 1978 * were present, and passing the resulting string to 1979 * {@link Short#parseShort(String, int) Short.parseShort} with the 1980 * specified radix. 1981 * 1982 * @param radix the radix used to interpret the token as a short value 1983 * @return the <tt>short</tt> scanned from the input 1984 * @throws InputMismatchException 1985 * if the next token does not match the <i>Integer</i> 1986 * regular expression, or is out of range 1987 * @throws NoSuchElementException if input is exhausted 1988 * @throws IllegalStateException if this scanner is closed 1989 */ nextShort(int radix)1990 public short nextShort(int radix) { 1991 // Check cached result 1992 if ((typeCache != null) && (typeCache instanceof Short) 1993 && this.radix == radix) { 1994 short val = ((Short)typeCache).shortValue(); 1995 useTypeCache(); 1996 return val; 1997 } 1998 setRadix(radix); 1999 clearCaches(); 2000 // Search for next short 2001 try { 2002 String s = next(integerPattern()); 2003 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2004 s = processIntegerToken(s); 2005 return Short.parseShort(s, radix); 2006 } catch (NumberFormatException nfe) { 2007 position = matcher.start(); // don't skip bad token 2008 throw new InputMismatchException(nfe.getMessage()); 2009 } 2010 } 2011 2012 /** 2013 * Returns true if the next token in this scanner's input can be 2014 * interpreted as an int value in the default radix using the 2015 * {@link #nextInt} method. The scanner does not advance past any input. 2016 * 2017 * @return true if and only if this scanner's next token is a valid 2018 * int value 2019 * @throws IllegalStateException if this scanner is closed 2020 */ hasNextInt()2021 public boolean hasNextInt() { 2022 return hasNextInt(defaultRadix); 2023 } 2024 2025 /** 2026 * Returns true if the next token in this scanner's input can be 2027 * interpreted as an int value in the specified radix using the 2028 * {@link #nextInt} method. The scanner does not advance past any input. 2029 * 2030 * @param radix the radix used to interpret the token as an int value 2031 * @return true if and only if this scanner's next token is a valid 2032 * int value 2033 * @throws IllegalStateException if this scanner is closed 2034 */ hasNextInt(int radix)2035 public boolean hasNextInt(int radix) { 2036 setRadix(radix); 2037 boolean result = hasNext(integerPattern()); 2038 if (result) { // Cache it 2039 try { 2040 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 2041 processIntegerToken(hasNextResult) : 2042 hasNextResult; 2043 typeCache = Integer.parseInt(s, radix); 2044 } catch (NumberFormatException nfe) { 2045 result = false; 2046 } 2047 } 2048 return result; 2049 } 2050 2051 /** 2052 * The integer token must be stripped of prefixes, group separators, 2053 * and suffixes, non ascii digits must be converted into ascii digits 2054 * before parse will accept it. 2055 */ processIntegerToken(String token)2056 private String processIntegerToken(String token) { 2057 String result = token.replaceAll(""+groupSeparator, ""); 2058 boolean isNegative = false; 2059 int preLen = negativePrefix.length(); 2060 if ((preLen > 0) && result.startsWith(negativePrefix)) { 2061 isNegative = true; 2062 result = result.substring(preLen); 2063 } 2064 int sufLen = negativeSuffix.length(); 2065 if ((sufLen > 0) && result.endsWith(negativeSuffix)) { 2066 isNegative = true; 2067 result = result.substring(result.length() - sufLen, 2068 result.length()); 2069 } 2070 if (isNegative) 2071 result = "-" + result; 2072 return result; 2073 } 2074 2075 /** 2076 * Scans the next token of the input as an <tt>int</tt>. 2077 * 2078 * <p> An invocation of this method of the form 2079 * <tt>nextInt()</tt> behaves in exactly the same way as the 2080 * invocation <tt>nextInt(radix)</tt>, where <code>radix</code> 2081 * is the default radix of this scanner. 2082 * 2083 * @return the <tt>int</tt> scanned from the input 2084 * @throws InputMismatchException 2085 * if the next token does not match the <i>Integer</i> 2086 * regular expression, or is out of range 2087 * @throws NoSuchElementException if input is exhausted 2088 * @throws IllegalStateException if this scanner is closed 2089 */ nextInt()2090 public int nextInt() { 2091 return nextInt(defaultRadix); 2092 } 2093 2094 /** 2095 * Scans the next token of the input as an <tt>int</tt>. 2096 * This method will throw <code>InputMismatchException</code> 2097 * if the next token cannot be translated into a valid int value as 2098 * described below. If the translation is successful, the scanner advances 2099 * past the input that matched. 2100 * 2101 * <p> If the next token matches the <a 2102 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2103 * above then the token is converted into an <tt>int</tt> value as if by 2104 * removing all locale specific prefixes, group separators, and locale 2105 * specific suffixes, then mapping non-ASCII digits into ASCII 2106 * digits via {@link Character#digit Character.digit}, prepending a 2107 * negative sign (-) if the locale specific negative prefixes and suffixes 2108 * were present, and passing the resulting string to 2109 * {@link Integer#parseInt(String, int) Integer.parseInt} with the 2110 * specified radix. 2111 * 2112 * @param radix the radix used to interpret the token as an int value 2113 * @return the <tt>int</tt> scanned from the input 2114 * @throws InputMismatchException 2115 * if the next token does not match the <i>Integer</i> 2116 * regular expression, or is out of range 2117 * @throws NoSuchElementException if input is exhausted 2118 * @throws IllegalStateException if this scanner is closed 2119 */ nextInt(int radix)2120 public int nextInt(int radix) { 2121 // Check cached result 2122 if ((typeCache != null) && (typeCache instanceof Integer) 2123 && this.radix == radix) { 2124 int val = ((Integer)typeCache).intValue(); 2125 useTypeCache(); 2126 return val; 2127 } 2128 setRadix(radix); 2129 clearCaches(); 2130 // Search for next int 2131 try { 2132 String s = next(integerPattern()); 2133 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2134 s = processIntegerToken(s); 2135 return Integer.parseInt(s, radix); 2136 } catch (NumberFormatException nfe) { 2137 position = matcher.start(); // don't skip bad token 2138 throw new InputMismatchException(nfe.getMessage()); 2139 } 2140 } 2141 2142 /** 2143 * Returns true if the next token in this scanner's input can be 2144 * interpreted as a long value in the default radix using the 2145 * {@link #nextLong} method. The scanner does not advance past any input. 2146 * 2147 * @return true if and only if this scanner's next token is a valid 2148 * long value 2149 * @throws IllegalStateException if this scanner is closed 2150 */ hasNextLong()2151 public boolean hasNextLong() { 2152 return hasNextLong(defaultRadix); 2153 } 2154 2155 /** 2156 * Returns true if the next token in this scanner's input can be 2157 * interpreted as a long value in the specified radix using the 2158 * {@link #nextLong} method. The scanner does not advance past any input. 2159 * 2160 * @param radix the radix used to interpret the token as a long value 2161 * @return true if and only if this scanner's next token is a valid 2162 * long value 2163 * @throws IllegalStateException if this scanner is closed 2164 */ hasNextLong(int radix)2165 public boolean hasNextLong(int radix) { 2166 setRadix(radix); 2167 boolean result = hasNext(integerPattern()); 2168 if (result) { // Cache it 2169 try { 2170 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 2171 processIntegerToken(hasNextResult) : 2172 hasNextResult; 2173 typeCache = Long.parseLong(s, radix); 2174 } catch (NumberFormatException nfe) { 2175 result = false; 2176 } 2177 } 2178 return result; 2179 } 2180 2181 /** 2182 * Scans the next token of the input as a <tt>long</tt>. 2183 * 2184 * <p> An invocation of this method of the form 2185 * <tt>nextLong()</tt> behaves in exactly the same way as the 2186 * invocation <tt>nextLong(radix)</tt>, where <code>radix</code> 2187 * is the default radix of this scanner. 2188 * 2189 * @return the <tt>long</tt> scanned from the input 2190 * @throws InputMismatchException 2191 * if the next token does not match the <i>Integer</i> 2192 * regular expression, or is out of range 2193 * @throws NoSuchElementException if input is exhausted 2194 * @throws IllegalStateException if this scanner is closed 2195 */ nextLong()2196 public long nextLong() { 2197 return nextLong(defaultRadix); 2198 } 2199 2200 /** 2201 * Scans the next token of the input as a <tt>long</tt>. 2202 * This method will throw <code>InputMismatchException</code> 2203 * if the next token cannot be translated into a valid long value as 2204 * described below. If the translation is successful, the scanner advances 2205 * past the input that matched. 2206 * 2207 * <p> If the next token matches the <a 2208 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2209 * above then the token is converted into a <tt>long</tt> value as if by 2210 * removing all locale specific prefixes, group separators, and locale 2211 * specific suffixes, then mapping non-ASCII digits into ASCII 2212 * digits via {@link Character#digit Character.digit}, prepending a 2213 * negative sign (-) if the locale specific negative prefixes and suffixes 2214 * were present, and passing the resulting string to 2215 * {@link Long#parseLong(String, int) Long.parseLong} with the 2216 * specified radix. 2217 * 2218 * @param radix the radix used to interpret the token as an int value 2219 * @return the <tt>long</tt> scanned from the input 2220 * @throws InputMismatchException 2221 * if the next token does not match the <i>Integer</i> 2222 * regular expression, or is out of range 2223 * @throws NoSuchElementException if input is exhausted 2224 * @throws IllegalStateException if this scanner is closed 2225 */ nextLong(int radix)2226 public long nextLong(int radix) { 2227 // Check cached result 2228 if ((typeCache != null) && (typeCache instanceof Long) 2229 && this.radix == radix) { 2230 long val = ((Long)typeCache).longValue(); 2231 useTypeCache(); 2232 return val; 2233 } 2234 setRadix(radix); 2235 clearCaches(); 2236 try { 2237 String s = next(integerPattern()); 2238 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2239 s = processIntegerToken(s); 2240 return Long.parseLong(s, radix); 2241 } catch (NumberFormatException nfe) { 2242 position = matcher.start(); // don't skip bad token 2243 throw new InputMismatchException(nfe.getMessage()); 2244 } 2245 } 2246 2247 /** 2248 * The float token must be stripped of prefixes, group separators, 2249 * and suffixes, non ascii digits must be converted into ascii digits 2250 * before parseFloat will accept it. 2251 * 2252 * If there are non-ascii digits in the token these digits must 2253 * be processed before the token is passed to parseFloat. 2254 */ processFloatToken(String token)2255 private String processFloatToken(String token) { 2256 String result = token.replaceAll(groupSeparator, ""); 2257 if (!decimalSeparator.equals("\\.")) 2258 result = result.replaceAll(decimalSeparator, "."); 2259 boolean isNegative = false; 2260 int preLen = negativePrefix.length(); 2261 if ((preLen > 0) && result.startsWith(negativePrefix)) { 2262 isNegative = true; 2263 result = result.substring(preLen); 2264 } 2265 int sufLen = negativeSuffix.length(); 2266 if ((sufLen > 0) && result.endsWith(negativeSuffix)) { 2267 isNegative = true; 2268 result = result.substring(result.length() - sufLen, 2269 result.length()); 2270 } 2271 if (result.equals(nanString)) 2272 result = "NaN"; 2273 if (result.equals(infinityString)) 2274 result = "Infinity"; 2275 // Android-changed: Match the infinity symbol. 2276 if (result.equals("\u221E")) 2277 result = "Infinity"; 2278 if (isNegative) 2279 result = "-" + result; 2280 2281 // Translate non-ASCII digits 2282 Matcher m = NON_ASCII_DIGIT.matcher(result); 2283 if (m.find()) { 2284 StringBuilder inASCII = new StringBuilder(); 2285 for (int i=0; i<result.length(); i++) { 2286 char nextChar = result.charAt(i); 2287 if (Character.isDigit(nextChar)) { 2288 int d = Character.digit(nextChar, 10); 2289 if (d != -1) 2290 inASCII.append(d); 2291 else 2292 inASCII.append(nextChar); 2293 } else { 2294 inASCII.append(nextChar); 2295 } 2296 } 2297 result = inASCII.toString(); 2298 } 2299 2300 return result; 2301 } 2302 2303 /** 2304 * Returns true if the next token in this scanner's input can be 2305 * interpreted as a float value using the {@link #nextFloat} 2306 * method. The scanner does not advance past any input. 2307 * 2308 * @return true if and only if this scanner's next token is a valid 2309 * float value 2310 * @throws IllegalStateException if this scanner is closed 2311 */ hasNextFloat()2312 public boolean hasNextFloat() { 2313 setRadix(10); 2314 boolean result = hasNext(floatPattern()); 2315 if (result) { // Cache it 2316 try { 2317 String s = processFloatToken(hasNextResult); 2318 typeCache = Float.valueOf(Float.parseFloat(s)); 2319 } catch (NumberFormatException nfe) { 2320 result = false; 2321 } 2322 } 2323 return result; 2324 } 2325 2326 /** 2327 * Scans the next token of the input as a <tt>float</tt>. 2328 * This method will throw <code>InputMismatchException</code> 2329 * if the next token cannot be translated into a valid float value as 2330 * described below. If the translation is successful, the scanner advances 2331 * past the input that matched. 2332 * 2333 * <p> If the next token matches the <a 2334 * href="#Float-regex"><i>Float</i></a> regular expression defined above 2335 * then the token is converted into a <tt>float</tt> value as if by 2336 * removing all locale specific prefixes, group separators, and locale 2337 * specific suffixes, then mapping non-ASCII digits into ASCII 2338 * digits via {@link Character#digit Character.digit}, prepending a 2339 * negative sign (-) if the locale specific negative prefixes and suffixes 2340 * were present, and passing the resulting string to 2341 * {@link Float#parseFloat Float.parseFloat}. If the token matches 2342 * the localized NaN or infinity strings, then either "Nan" or "Infinity" 2343 * is passed to {@link Float#parseFloat(String) Float.parseFloat} as 2344 * appropriate. 2345 * 2346 * @return the <tt>float</tt> scanned from the input 2347 * @throws InputMismatchException 2348 * if the next token does not match the <i>Float</i> 2349 * regular expression, or is out of range 2350 * @throws NoSuchElementException if input is exhausted 2351 * @throws IllegalStateException if this scanner is closed 2352 */ nextFloat()2353 public float nextFloat() { 2354 // Check cached result 2355 if ((typeCache != null) && (typeCache instanceof Float)) { 2356 float val = ((Float)typeCache).floatValue(); 2357 useTypeCache(); 2358 return val; 2359 } 2360 setRadix(10); 2361 clearCaches(); 2362 try { 2363 return Float.parseFloat(processFloatToken(next(floatPattern()))); 2364 } catch (NumberFormatException nfe) { 2365 position = matcher.start(); // don't skip bad token 2366 throw new InputMismatchException(nfe.getMessage()); 2367 } 2368 } 2369 2370 /** 2371 * Returns true if the next token in this scanner's input can be 2372 * interpreted as a double value using the {@link #nextDouble} 2373 * method. The scanner does not advance past any input. 2374 * 2375 * @return true if and only if this scanner's next token is a valid 2376 * double value 2377 * @throws IllegalStateException if this scanner is closed 2378 */ hasNextDouble()2379 public boolean hasNextDouble() { 2380 setRadix(10); 2381 boolean result = hasNext(floatPattern()); 2382 if (result) { // Cache it 2383 try { 2384 String s = processFloatToken(hasNextResult); 2385 typeCache = Double.valueOf(Double.parseDouble(s)); 2386 } catch (NumberFormatException nfe) { 2387 result = false; 2388 } 2389 } 2390 return result; 2391 } 2392 2393 /** 2394 * Scans the next token of the input as a <tt>double</tt>. 2395 * This method will throw <code>InputMismatchException</code> 2396 * if the next token cannot be translated into a valid double value. 2397 * If the translation is successful, the scanner advances past the input 2398 * that matched. 2399 * 2400 * <p> If the next token matches the <a 2401 * href="#Float-regex"><i>Float</i></a> regular expression defined above 2402 * then the token is converted into a <tt>double</tt> value as if by 2403 * removing all locale specific prefixes, group separators, and locale 2404 * specific suffixes, then mapping non-ASCII digits into ASCII 2405 * digits via {@link Character#digit Character.digit}, prepending a 2406 * negative sign (-) if the locale specific negative prefixes and suffixes 2407 * were present, and passing the resulting string to 2408 * {@link Double#parseDouble Double.parseDouble}. If the token matches 2409 * the localized NaN or infinity strings, then either "Nan" or "Infinity" 2410 * is passed to {@link Double#parseDouble(String) Double.parseDouble} as 2411 * appropriate. 2412 * 2413 * @return the <tt>double</tt> scanned from the input 2414 * @throws InputMismatchException 2415 * if the next token does not match the <i>Float</i> 2416 * regular expression, or is out of range 2417 * @throws NoSuchElementException if the input is exhausted 2418 * @throws IllegalStateException if this scanner is closed 2419 */ nextDouble()2420 public double nextDouble() { 2421 // Check cached result 2422 if ((typeCache != null) && (typeCache instanceof Double)) { 2423 double val = ((Double)typeCache).doubleValue(); 2424 useTypeCache(); 2425 return val; 2426 } 2427 setRadix(10); 2428 clearCaches(); 2429 // Search for next float 2430 try { 2431 return Double.parseDouble(processFloatToken(next(floatPattern()))); 2432 } catch (NumberFormatException nfe) { 2433 position = matcher.start(); // don't skip bad token 2434 throw new InputMismatchException(nfe.getMessage()); 2435 } 2436 } 2437 2438 // Convenience methods for scanning multi precision numbers 2439 2440 /** 2441 * Returns true if the next token in this scanner's input can be 2442 * interpreted as a <code>BigInteger</code> in the default radix using the 2443 * {@link #nextBigInteger} method. The scanner does not advance past any 2444 * input. 2445 * 2446 * @return true if and only if this scanner's next token is a valid 2447 * <code>BigInteger</code> 2448 * @throws IllegalStateException if this scanner is closed 2449 */ hasNextBigInteger()2450 public boolean hasNextBigInteger() { 2451 return hasNextBigInteger(defaultRadix); 2452 } 2453 2454 /** 2455 * Returns true if the next token in this scanner's input can be 2456 * interpreted as a <code>BigInteger</code> in the specified radix using 2457 * the {@link #nextBigInteger} method. The scanner does not advance past 2458 * any input. 2459 * 2460 * @param radix the radix used to interpret the token as an integer 2461 * @return true if and only if this scanner's next token is a valid 2462 * <code>BigInteger</code> 2463 * @throws IllegalStateException if this scanner is closed 2464 */ hasNextBigInteger(int radix)2465 public boolean hasNextBigInteger(int radix) { 2466 setRadix(radix); 2467 boolean result = hasNext(integerPattern()); 2468 if (result) { // Cache it 2469 try { 2470 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 2471 processIntegerToken(hasNextResult) : 2472 hasNextResult; 2473 typeCache = new BigInteger(s, radix); 2474 } catch (NumberFormatException nfe) { 2475 result = false; 2476 } 2477 } 2478 return result; 2479 } 2480 2481 /** 2482 * Scans the next token of the input as a {@link java.math.BigInteger 2483 * BigInteger}. 2484 * 2485 * <p> An invocation of this method of the form 2486 * <tt>nextBigInteger()</tt> behaves in exactly the same way as the 2487 * invocation <tt>nextBigInteger(radix)</tt>, where <code>radix</code> 2488 * is the default radix of this scanner. 2489 * 2490 * @return the <tt>BigInteger</tt> scanned from the input 2491 * @throws InputMismatchException 2492 * if the next token does not match the <i>Integer</i> 2493 * regular expression, or is out of range 2494 * @throws NoSuchElementException if the input is exhausted 2495 * @throws IllegalStateException if this scanner is closed 2496 */ nextBigInteger()2497 public BigInteger nextBigInteger() { 2498 return nextBigInteger(defaultRadix); 2499 } 2500 2501 /** 2502 * Scans the next token of the input as a {@link java.math.BigInteger 2503 * BigInteger}. 2504 * 2505 * <p> If the next token matches the <a 2506 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2507 * above then the token is converted into a <tt>BigInteger</tt> value as if 2508 * by removing all group separators, mapping non-ASCII digits into ASCII 2509 * digits via the {@link Character#digit Character.digit}, and passing the 2510 * resulting string to the {@link 2511 * java.math.BigInteger#BigInteger(java.lang.String) 2512 * BigInteger(String, int)} constructor with the specified radix. 2513 * 2514 * @param radix the radix used to interpret the token 2515 * @return the <tt>BigInteger</tt> scanned from the input 2516 * @throws InputMismatchException 2517 * if the next token does not match the <i>Integer</i> 2518 * regular expression, or is out of range 2519 * @throws NoSuchElementException if the input is exhausted 2520 * @throws IllegalStateException if this scanner is closed 2521 */ nextBigInteger(int radix)2522 public BigInteger nextBigInteger(int radix) { 2523 // Check cached result 2524 if ((typeCache != null) && (typeCache instanceof BigInteger) 2525 && this.radix == radix) { 2526 BigInteger val = (BigInteger)typeCache; 2527 useTypeCache(); 2528 return val; 2529 } 2530 setRadix(radix); 2531 clearCaches(); 2532 // Search for next int 2533 try { 2534 String s = next(integerPattern()); 2535 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2536 s = processIntegerToken(s); 2537 return new BigInteger(s, radix); 2538 } catch (NumberFormatException nfe) { 2539 position = matcher.start(); // don't skip bad token 2540 throw new InputMismatchException(nfe.getMessage()); 2541 } 2542 } 2543 2544 /** 2545 * Returns true if the next token in this scanner's input can be 2546 * interpreted as a <code>BigDecimal</code> using the 2547 * {@link #nextBigDecimal} method. The scanner does not advance past any 2548 * input. 2549 * 2550 * @return true if and only if this scanner's next token is a valid 2551 * <code>BigDecimal</code> 2552 * @throws IllegalStateException if this scanner is closed 2553 */ hasNextBigDecimal()2554 public boolean hasNextBigDecimal() { 2555 setRadix(10); 2556 boolean result = hasNext(decimalPattern()); 2557 if (result) { // Cache it 2558 try { 2559 String s = processFloatToken(hasNextResult); 2560 typeCache = new BigDecimal(s); 2561 } catch (NumberFormatException nfe) { 2562 result = false; 2563 } 2564 } 2565 return result; 2566 } 2567 2568 /** 2569 * Scans the next token of the input as a {@link java.math.BigDecimal 2570 * BigDecimal}. 2571 * 2572 * <p> If the next token matches the <a 2573 * href="#Decimal-regex"><i>Decimal</i></a> regular expression defined 2574 * above then the token is converted into a <tt>BigDecimal</tt> value as if 2575 * by removing all group separators, mapping non-ASCII digits into ASCII 2576 * digits via the {@link Character#digit Character.digit}, and passing the 2577 * resulting string to the {@link 2578 * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)} 2579 * constructor. 2580 * 2581 * @return the <tt>BigDecimal</tt> scanned from the input 2582 * @throws InputMismatchException 2583 * if the next token does not match the <i>Decimal</i> 2584 * regular expression, or is out of range 2585 * @throws NoSuchElementException if the input is exhausted 2586 * @throws IllegalStateException if this scanner is closed 2587 */ nextBigDecimal()2588 public BigDecimal nextBigDecimal() { 2589 // Check cached result 2590 if ((typeCache != null) && (typeCache instanceof BigDecimal)) { 2591 BigDecimal val = (BigDecimal)typeCache; 2592 useTypeCache(); 2593 return val; 2594 } 2595 setRadix(10); 2596 clearCaches(); 2597 // Search for next float 2598 try { 2599 String s = processFloatToken(next(decimalPattern())); 2600 return new BigDecimal(s); 2601 } catch (NumberFormatException nfe) { 2602 position = matcher.start(); // don't skip bad token 2603 throw new InputMismatchException(nfe.getMessage()); 2604 } 2605 } 2606 2607 /** 2608 * Resets this scanner. 2609 * 2610 * <p> Resetting a scanner discards all of its explicit state 2611 * information which may have been changed by invocations of {@link 2612 * #useDelimiter}, {@link #useLocale}, or {@link #useRadix}. 2613 * 2614 * <p> An invocation of this method of the form 2615 * <tt>scanner.reset()</tt> behaves in exactly the same way as the 2616 * invocation 2617 * 2618 * <blockquote><pre> 2619 * scanner.useDelimiter("\\p{javaWhitespace}+") 2620 * .useLocale(Locale.getDefault()) 2621 * .useRadix(10); 2622 * </pre></blockquote> 2623 * 2624 * @return this scanner 2625 * 2626 * @since 1.6 2627 */ reset()2628 public Scanner reset() { 2629 delimPattern = WHITESPACE_PATTERN; 2630 useLocale(Locale.getDefault(Locale.Category.FORMAT)); 2631 useRadix(10); 2632 clearCaches(); 2633 return this; 2634 } 2635 } 2636