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