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