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