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