1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package java.util;
17
18import java.io.Closeable;
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.FileNotFoundException;
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.InputStreamReader;
25import java.io.StringReader;
26import java.io.UnsupportedEncodingException;
27import java.math.BigDecimal;
28import java.math.BigInteger;
29import java.nio.CharBuffer;
30import java.nio.channels.Channels;
31import java.nio.channels.ReadableByteChannel;
32import java.nio.charset.Charset;
33import java.text.DecimalFormat;
34import java.text.DecimalFormatSymbols;
35import java.text.NumberFormat;
36import java.util.regex.MatchResult;
37import java.util.regex.Matcher;
38import java.util.regex.Pattern;
39import libcore.io.IoUtils;
40
41/**
42 * A parser that parses a text string of primitive types and strings with the
43 * help of regular expressions. This class is not as useful as it might seem.
44 * It's very inefficient for communicating between machines; you should use JSON,
45 * protobufs, or even XML for that. Very simple uses might get away with {@link String#split}.
46 * For input from humans, the use of locale-specific regular expressions make it not only
47 * expensive but also somewhat unpredictable.
48 *
49 * <p>This class supports localized numbers and various
50 * radixes. The input is broken into tokens by the delimiter pattern, which is
51 * {@code \\p{javaWhitespace}} by default.
52 *
53 * <p>Example:
54 * <pre>
55 * Scanner s = new Scanner("1A true");
56 * assertEquals(26, s.nextInt(16));
57 * assertEquals(true, s.nextBoolean());
58 * </pre>
59 *
60 * <p>The {@code Scanner} class is not thread-safe.
61 */
62public final class Scanner implements Closeable, Iterator<String> {
63
64    private static final String NL = "\n|\r\n|\r|\u0085|\u2028|\u2029";
65
66    // Default delimiting pattern.
67    private static final Pattern DEFAULT_DELIMITER = Pattern.compile("\\p{javaWhitespace}+");
68
69    // The boolean's pattern.
70    private static final Pattern BOOLEAN_PATTERN = Pattern.compile("true|false", Pattern.CASE_INSENSITIVE);
71
72    // Pattern used to recognize line terminator.
73    private static final Pattern LINE_TERMINATOR = Pattern.compile(NL);
74
75    // Pattern used to recognize multiple line terminators.
76    private static final Pattern MULTI_LINE_TERMINATOR = Pattern.compile("(" + NL + ")+");
77
78    // Pattern used to recognize a line with a line terminator.
79    private static final Pattern LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+$");
80
81    // The pattern matches anything.
82    private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*");
83
84    private static final int DEFAULT_RADIX = 10;
85
86    // The input source of scanner.
87    private Readable input;
88
89    private CharBuffer buffer = CharBuffer.allocate(1024);
90
91    private Pattern delimiter = DEFAULT_DELIMITER;
92
93    private Matcher matcher;
94
95    private int currentRadix = DEFAULT_RADIX;
96
97    private Locale locale = Locale.getDefault();
98
99    // The position where find begins.
100    private int findStartIndex = 0;
101
102    // The last find start position.
103    private int preStartIndex = findStartIndex;
104
105    // The length of the buffer.
106    private int bufferLength = 0;
107
108    // Record the status of this scanner. True if the scanner is closed.
109    private boolean closed = false;
110
111    private IOException lastIOException;
112
113    private boolean matchSuccessful = false;
114
115    private DecimalFormat decimalFormat;
116
117    // Records whether the underlying readable has more input.
118    private boolean inputExhausted = false;
119
120    private Object cachedNextValue = null;
121    private int cachedNextIndex = -1;
122
123    private Pattern cachedFloatPattern = null;
124
125    private int cachedIntegerPatternRadix = -1;
126    private Pattern cachedIntegerPattern = null;
127
128    /**
129     * Creates a {@code Scanner} with the specified {@code File} as input. The default charset
130     * is applied when reading the file.
131     *
132     * @param src
133     *            the file to be scanned.
134     * @throws FileNotFoundException
135     *             if the specified file does not exist.
136     */
137    public Scanner(File src) throws FileNotFoundException {
138        this(src, Charset.defaultCharset().name());
139    }
140
141    /**
142     * Creates a {@code Scanner} with the specified {@code File} as input. The specified charset
143     * is applied when reading the file.
144     *
145     * @param src
146     *            the file to be scanned.
147     * @param charsetName
148     *            the name of the encoding type of the file.
149     * @throws FileNotFoundException
150     *             if the specified file does not exist.
151     * @throws IllegalArgumentException
152     *             if the specified coding does not exist.
153     */
154    public Scanner(File src, String charsetName) throws FileNotFoundException {
155        if (src == null) {
156            throw new NullPointerException("src == null");
157        }
158        FileInputStream fis = new FileInputStream(src);
159        if (charsetName == null) {
160            throw new IllegalArgumentException("charsetName == null");
161        }
162
163        InputStreamReader streamReader;
164        try {
165            streamReader = new InputStreamReader(fis, charsetName);
166        } catch (UnsupportedEncodingException e) {
167            IoUtils.closeQuietly(fis);
168            throw new IllegalArgumentException(e.getMessage());
169        }
170        initialize(streamReader);
171    }
172
173    /**
174     * Creates a {@code Scanner} on the specified string.
175     *
176     * @param src
177     *            the string to be scanned.
178     */
179    public Scanner(String src) {
180        initialize(new StringReader(src));
181    }
182
183    /**
184     * Creates a {@code Scanner} on the specified {@code InputStream}. The default charset is
185     * applied when decoding the input.
186     *
187     * @param src
188     *            the {@code InputStream} to be scanned.
189     */
190    public Scanner(InputStream src) {
191        this(src, Charset.defaultCharset().name());
192    }
193
194    /**
195     * Creates a {@code Scanner} on the specified {@code InputStream}. The specified charset is
196     * applied when decoding the input.
197     *
198     * @param src
199     *            the {@code InputStream} to be scanned.
200     * @param charsetName
201     *            the encoding type of the {@code InputStream}.
202     * @throws IllegalArgumentException
203     *             if the specified character set is not found.
204     */
205    public Scanner(InputStream src, String charsetName) {
206        if (src == null) {
207            throw new NullPointerException("src == null");
208        }
209
210        InputStreamReader streamReader;
211        try {
212            streamReader = new InputStreamReader(src, charsetName);
213        } catch (UnsupportedEncodingException e) {
214            throw new IllegalArgumentException(e.getMessage());
215        }
216        initialize(streamReader);
217    }
218
219    /**
220     * Creates a {@code Scanner} with the specified {@code Readable} as input.
221     *
222     * @param src
223     *            the {@code Readable} to be scanned.
224     */
225    public Scanner(Readable src) {
226        if (src == null) {
227            throw new NullPointerException("src == null");
228        }
229        initialize(src);
230    }
231
232    /**
233     * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as
234     * input. The default charset is applied when decoding the input.
235     *
236     * @param src
237     *            the {@code ReadableByteChannel} to be scanned.
238     */
239    public Scanner(ReadableByteChannel src) {
240        this(src, Charset.defaultCharset().name());
241    }
242
243    /**
244     * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as
245     * input. The specified charset is applied when decoding the input.
246     *
247     * @param src
248     *            the {@code ReadableByteChannel} to be scanned.
249     * @param charsetName
250     *            the encoding type of the content.
251     * @throws IllegalArgumentException
252     *             if the specified character set is not found.
253     */
254    public Scanner(ReadableByteChannel src, String charsetName) {
255        if (src == null) {
256            throw new NullPointerException("src == null");
257        }
258        if (charsetName == null) {
259            throw new IllegalArgumentException("charsetName == null");
260        }
261        initialize(Channels.newReader(src, charsetName));
262    }
263
264    private void initialize(Readable input) {
265        this.input = input;
266        matcher = delimiter.matcher("");
267        matcher.useTransparentBounds(true);
268        matcher.useAnchoringBounds(false);
269    }
270
271    /**
272     * Closes this {@code Scanner} and the underlying input if the input implements
273     * {@code Closeable}. If the {@code Scanner} has been closed, this method will have
274     * no effect. Any scanning operation called after calling this method will throw
275     * an {@code IllegalStateException}.
276     *
277     * @see Closeable
278     */
279    public void close() {
280        if (closed) {
281            return;
282        }
283        if (input instanceof Closeable) {
284            try {
285                ((Closeable) input).close();
286            } catch (IOException e) {
287                lastIOException = e;
288            }
289        }
290        closed = true;
291    }
292
293    /**
294     * Returns the delimiter {@code Pattern} in use by this {@code Scanner}.
295     *
296     * @return the delimiter {@code Pattern} in use by this {@code Scanner}.
297     */
298    public Pattern delimiter() {
299        return delimiter;
300    }
301
302    /**
303     * Tries to find the pattern in the input. Delimiters are ignored. If the
304     * pattern is found before line terminator, the matched string will be
305     * returned, and the {@code Scanner} will advance to the end of the matched string.
306     * Otherwise, {@code null} will be returned and the {@code Scanner} will not advance.
307     * When waiting for input, the {@code Scanner} may be blocked. All the
308     * input may be cached if no line terminator exists in the buffer.
309     *
310     * @param pattern
311     *            the pattern to find in the input.
312     * @return the matched string or {@code null} if the pattern is not found
313     *         before the next line terminator.
314     * @throws IllegalStateException
315     *             if the {@code Scanner} is closed.
316     */
317    public String findInLine(Pattern pattern) {
318        checkOpen();
319        checkNotNull(pattern);
320        int horizonLineSeparator = 0;
321
322        matcher.usePattern(MULTI_LINE_TERMINATOR);
323        matcher.region(findStartIndex, bufferLength);
324
325        boolean findComplete = false;
326        int terminatorLength = 0;
327        while (!findComplete) {
328            if (matcher.find()) {
329                horizonLineSeparator = matcher.start();
330                terminatorLength = matcher.end() - matcher.start();
331                findComplete = true;
332            } else {
333                if (!inputExhausted) {
334                    readMore();
335                    resetMatcher();
336                } else {
337                    horizonLineSeparator = bufferLength;
338                    findComplete = true;
339                }
340            }
341        }
342
343        matcher.usePattern(pattern);
344
345        /*
346         * TODO The following 2 statements are used to deal with regex's bug.
347         * java.util.regex.Matcher.region(int start, int end) implementation
348         * does not have any effects when called. They will be removed once the
349         * bug is fixed.
350         */
351        int oldLimit = buffer.limit();
352        // Considering the look ahead feature, the line terminator should be involved as RI
353        buffer.limit(horizonLineSeparator + terminatorLength);
354        // ========== To deal with regex bug ====================
355
356        // Considering the look ahead feature, the line terminator should be involved as RI
357        matcher.region(findStartIndex, horizonLineSeparator + terminatorLength);
358        if (matcher.find()) {
359            // The scanner advances past the input that matched
360            findStartIndex = matcher.end();
361            // If the matched pattern is immediately followed by line
362            // terminator.
363            if (horizonLineSeparator == matcher.end()) {
364                findStartIndex += terminatorLength;
365            }
366            // the line terminator itself should not be a part of
367            // the match result according to the Spec
368            if (horizonLineSeparator != bufferLength
369                    && (horizonLineSeparator + terminatorLength == matcher
370                            .end())) {
371                // ========== To deal with regex bug ====================
372                buffer.limit(oldLimit);
373                // ========== To deal with regex bug ====================
374
375                matchSuccessful = false;
376                return null;
377            }
378            matchSuccessful = true;
379
380            // ========== To deal with regex bug ====================
381            buffer.limit(oldLimit);
382            // ========== To deal with regex bug ====================
383
384            return matcher.group();
385        }
386
387        // ========== To deal with regex bug ====================
388        buffer.limit(oldLimit);
389        // ========== To deal with regex bug ====================
390
391        matchSuccessful = false;
392        return null;
393    }
394
395    /**
396     * Compiles the pattern string and tries to find a substring matching it in the input data. The
397     * delimiter will be ignored. This is the same as invoking
398     * {@code findInLine(Pattern.compile(pattern))}.
399     *
400     * @param pattern
401     *            a string used to construct a pattern which is in turn used to
402     *            match a substring of the input data.
403     * @return the matched string or {@code null} if the pattern is not found
404     *         before the next line terminator.
405     * @throws IllegalStateException
406     *             if the {@code Scanner} is closed.
407     * @see #findInLine(Pattern)
408     */
409    public String findInLine(String pattern) {
410        return findInLine(Pattern.compile(pattern));
411    }
412
413    /**
414     * Tries to find the pattern in the input between the current position and the specified
415     * horizon. Delimiters are ignored. If the pattern is found, the matched
416     * string will be returned, and the {@code Scanner} will advance to the end of the
417     * matched string. Otherwise, null will be returned and {@code Scanner} will not
418     * advance. When waiting for input, the {@code Scanner} may be blocked.
419     * <p>
420     * The {@code Scanner}'s search will never go more than {@code horizon} code points from current
421     * position. The position of {@code horizon} does have an effect on the result of the
422     * match. For example, when the input is "123" and current position is at zero,
423     * <code>findWithinHorizon(Pattern.compile("\\p{Digit}{3}"), 2)</code>
424     * will return {@code null}, while
425     * <code>findWithinHorizon(Pattern.compile("\\p{Digit}{3}"), 3)</code>
426     * will return {@code "123"}. {@code horizon} is treated as a transparent,
427     * non-anchoring bound. (refer to
428     * {@link Matcher#useTransparentBounds(boolean)} and
429     * {@link Matcher#useAnchoringBounds(boolean)})
430     * <p>
431     * A {@code horizon} whose value is zero will be ignored and the whole input will be
432     * used for search. In this situation, all the input may be cached.
433     *
434     * @param pattern
435     *            the pattern used to scan.
436     * @param horizon
437     *            the search limit.
438     * @return the matched string or {@code null} if the pattern is not found
439     *         within the specified {@code horizon}.
440     * @throws IllegalStateException
441     *             if the {@code Scanner} is closed.
442     * @throws IllegalArgumentException
443     *             if {@code horizon} is less than zero.
444     */
445    public String findWithinHorizon(Pattern pattern, int horizon) {
446        checkOpen();
447        checkNotNull(pattern);
448        if (horizon < 0) {
449            throw new IllegalArgumentException("horizon < 0");
450        }
451        matcher.usePattern(pattern);
452
453        String result = null;
454        int horizonEndIndex = (horizon == 0) ? Integer.MAX_VALUE : findStartIndex + horizon;
455        while (true) {
456            // If horizon > 0, then search up to
457            // min( bufferLength, findStartIndex + horizon).
458            // Otherwise search until readable is exhausted.
459            int findEndIndex = Math.min(horizonEndIndex, bufferLength);
460            // If horizon == 0, consider horizon as always outside buffer.
461            boolean isHorizonInBuffer = (horizonEndIndex <= bufferLength);
462            // First, try to find pattern within buffer. If pattern can not be
463            // found in buffer, then expand the buffer and try again,
464            // util horizonEndIndex is exceeded or no more input left.
465            matcher.region(findStartIndex, findEndIndex);
466            if (matcher.find()) {
467                if ((horizon == 0 && !matcher.hitEnd()) || isHorizonInBuffer || inputExhausted) {
468                    result = matcher.group();
469                    break;
470                }
471            } else {
472                // Pattern is not found in buffer while horizonEndIndex is
473                // within buffer, or input is exhausted. Under this situation,
474                // it can be judged that find fails.
475                if (isHorizonInBuffer || inputExhausted) {
476                    break;
477                }
478            }
479
480            // Expand buffer and reset matcher if needed.
481            if (!inputExhausted) {
482                readMore();
483                resetMatcher();
484            }
485        }
486        if (result != null) {
487            findStartIndex = matcher.end();
488            matchSuccessful = true;
489        } else {
490            matchSuccessful = false;
491        }
492        return result;
493    }
494
495    /**
496     * Tries to find the pattern in the input between the current position and the specified
497     * {@code horizon}. Delimiters are ignored. This call is the same as invoking
498     * {@code findWithinHorizon(Pattern.compile(pattern))}.
499     *
500     * @param pattern
501     *            the pattern used to scan.
502     * @param horizon
503     *            the search limit.
504     * @return the matched string, or {@code null} if the pattern is not found
505     *         within the specified horizon.
506     * @throws IllegalStateException
507     *             if the {@code Scanner} is closed.
508     * @throws IllegalArgumentException
509     *             if {@code horizon} is less than zero.
510     * @see #findWithinHorizon(Pattern, int)
511     */
512    public String findWithinHorizon(String pattern, int horizon) {
513        return findWithinHorizon(Pattern.compile(pattern), horizon);
514    }
515
516    /**
517     * Returns whether this {@code Scanner} has one or more tokens remaining to parse.
518     * This method will block if the data is still being read.
519     *
520     * @return {@code true} if this {@code Scanner} has one or more tokens remaining,
521     *         otherwise {@code false}.
522     * @throws IllegalStateException
523     *             if the {@code Scanner} has been closed.
524     */
525    public boolean hasNext() {
526        return hasNext(ANY_PATTERN);
527    }
528
529    /**
530     * Returns whether this {@code Scanner} has one or more tokens remaining to parse
531     * and the next token matches the given pattern. This method will block if the data is
532     * still being read.
533     *
534     * @param pattern
535     *            the pattern to check for.
536     * @return {@code true} if this {@code Scanner} has more tokens and the next token
537     *         matches the pattern, {@code false} otherwise.
538     * @throws IllegalStateException
539     *             if the {@code Scanner} has been closed.
540     */
541    public boolean hasNext(Pattern pattern) {
542        checkOpen();
543        checkNotNull(pattern);
544        matchSuccessful = false;
545        prepareForScan();
546        // if the next token exists, set the match region, otherwise return
547        // false
548        if (!setTokenRegion()) {
549            recoverPreviousStatus();
550            return false;
551        }
552        matcher.usePattern(pattern);
553        boolean hasNext = false;
554        // check whether next token matches the specified pattern
555        if (matcher.matches()) {
556            cachedNextIndex = findStartIndex;
557            matchSuccessful = true;
558            hasNext = true;
559        }
560        recoverPreviousStatus();
561        return hasNext;
562    }
563
564    /**
565     * Returns {@code true} if this {@code Scanner} has one or more tokens remaining to parse
566     * and the next token matches a pattern compiled from the given string. This method will
567     * block if the data is still being read. This call is equivalent to
568     * {@code hasNext(Pattern.compile(pattern))}.
569     *
570     * @param pattern
571     *            the string specifying the pattern to scan for
572     * @return {@code true} if the specified pattern matches this {@code Scanner}'s
573     *         next token, {@code false} otherwise.
574     * @throws IllegalStateException
575     *             if the {@code Scanner} has been closed.
576     */
577    public boolean hasNext(String pattern) {
578        return hasNext(Pattern.compile(pattern));
579    }
580
581    /**
582     * Returns whether the next token can be translated into a valid
583     * {@code BigDecimal}.
584     *
585     * @return {@code true} if the next token can be translated into a valid
586     *         {@code BigDecimal}, otherwise {@code false.}
587     * @throws IllegalStateException
588     *             if the {@code Scanner} has been closed.
589     */
590    public boolean hasNextBigDecimal() {
591        Pattern floatPattern = getFloatPattern();
592        boolean isBigDecimalValue = false;
593        if (hasNext(floatPattern)) {
594            String floatString = matcher.group();
595            floatString = removeLocaleInfoFromFloat(floatString);
596            try {
597                cachedNextValue = new BigDecimal(floatString);
598                isBigDecimalValue = true;
599            } catch (NumberFormatException e) {
600                matchSuccessful = false;
601            }
602        }
603        return isBigDecimalValue;
604    }
605
606    /**
607     * Returns whether the next token can be translated into a valid
608     * {@code BigInteger} in the default radix.
609     *
610     * @return {@code true} if the next token can be translated into a valid
611     *         {@code BigInteger}, otherwise {@code false}.
612     * @throws IllegalStateException
613     *             if the {@code Scanner} has been closed.
614     */
615    public boolean hasNextBigInteger() {
616        return hasNextBigInteger(currentRadix);
617    }
618
619    /**
620     * Returns whether the next token can be translated into a valid
621     * {@code BigInteger} in the specified radix.
622     *
623     * @param radix
624     *            the radix used to translate the token into a
625     *            {@code BigInteger}.
626     * @return {@code true} if the next token can be translated into a valid
627     *         {@code BigInteger}, otherwise {@code false}.
628     * @throws IllegalStateException
629     *             if the {@code Scanner} has been closed.
630     */
631    public boolean hasNextBigInteger(int radix) {
632        Pattern integerPattern = getIntegerPattern(radix);
633        boolean isBigIntegerValue = false;
634        if (hasNext(integerPattern)) {
635            String intString = matcher.group();
636            intString = removeLocaleInfo(intString, int.class);
637            try {
638                cachedNextValue = new BigInteger(intString, radix);
639                isBigIntegerValue = true;
640            } catch (NumberFormatException e) {
641                matchSuccessful = false;
642            }
643        }
644        return isBigIntegerValue;
645    }
646
647    /**
648     * Returns whether the next token can be translated into a valid
649     * {@code boolean} value.
650     *
651     * @return {@code true} if the next token can be translated into a valid
652     *         {@code boolean} value, otherwise {@code false}.
653     * @throws IllegalStateException
654     *             if the {@code Scanner} has been closed.
655     */
656    public boolean hasNextBoolean() {
657        return hasNext(BOOLEAN_PATTERN);
658    }
659
660    /**
661     * Returns whether the next token can be translated into a valid
662     * {@code byte} value in the default radix.
663     *
664     * @return {@code true} if the next token can be translated into a valid
665     *         {@code byte} value, otherwise {@code false}.
666     * @throws IllegalStateException
667     *             if the {@code Scanner} has been closed.
668     */
669    public boolean hasNextByte() {
670        return hasNextByte(currentRadix);
671    }
672
673    /**
674     * Returns whether the next token can be translated into a valid
675     * {@code byte} value in the specified radix.
676     *
677     * @param radix
678     *            the radix used to translate the token into a {@code byte}
679     *            value
680     * @return {@code true} if the next token can be translated into a valid
681     *         {@code byte} value, otherwise {@code false}.
682     * @throws IllegalStateException
683     *             if the {@code Scanner} has been closed.
684     */
685    public boolean hasNextByte(int radix) {
686        Pattern integerPattern = getIntegerPattern(radix);
687        boolean isByteValue = false;
688        if (hasNext(integerPattern)) {
689            String intString = matcher.group();
690            intString = removeLocaleInfo(intString, int.class);
691            try {
692                cachedNextValue = Byte.valueOf(intString, radix);
693                isByteValue = true;
694            } catch (NumberFormatException e) {
695                matchSuccessful = false;
696            }
697        }
698        return isByteValue;
699    }
700
701    /**
702     * Returns whether the next token translated into a valid {@code double}
703     * value.
704     *
705     * @return {@code true} if the next token can be translated into a valid
706     *         {@code double} value, otherwise {@code false}.
707     * @throws IllegalStateException
708     *             if the {@code Scanner} has been closed.
709     */
710    public boolean hasNextDouble() {
711        Pattern floatPattern = getFloatPattern();
712        boolean isDoubleValue = false;
713        if (hasNext(floatPattern)) {
714            String floatString = matcher.group();
715            floatString = removeLocaleInfoFromFloat(floatString);
716            try {
717                cachedNextValue = Double.valueOf(floatString);
718                isDoubleValue = true;
719            } catch (NumberFormatException e) {
720                matchSuccessful = false;
721            }
722        }
723        return isDoubleValue;
724    }
725
726    /**
727     * Returns whether the next token can be translated into a valid
728     * {@code float} value.
729     *
730     * @return {@code true} if the next token can be translated into a valid
731     *         {@code float} value, otherwise {@code false}.
732     * @throws IllegalStateException
733     *             if the {@code Scanner} has been closed.
734     */
735    public boolean hasNextFloat() {
736        Pattern floatPattern = getFloatPattern();
737        boolean isFloatValue = false;
738        if (hasNext(floatPattern)) {
739            String floatString = matcher.group();
740            floatString = removeLocaleInfoFromFloat(floatString);
741            try {
742                cachedNextValue = Float.valueOf(floatString);
743                isFloatValue = true;
744            } catch (NumberFormatException e) {
745                matchSuccessful = false;
746            }
747        }
748        return isFloatValue;
749    }
750
751    /**
752     * Returns whether the next token can be translated into a valid {@code int}
753     * value in the default radix.
754     *
755     * @return {@code true} if the next token can be translated into a valid
756     *         {@code int} value, otherwise {@code false}.
757     * @throws IllegalStateException
758     *             if the {@code Scanner} has been closed,
759     */
760    public boolean hasNextInt() {
761        return hasNextInt(currentRadix);
762    }
763
764    /**
765     * Returns whether the next token can be translated into a valid {@code int}
766     * value in the specified radix.
767     *
768     * @param radix
769     *            the radix used to translate the token into an {@code int}
770     *            value.
771     * @return {@code true} if the next token in this {@code Scanner}'s input can be
772     *         translated into a valid {@code int} value, otherwise
773     *         {@code false}.
774     * @throws IllegalStateException
775     *             if the {@code Scanner} has been closed.
776     */
777    public boolean hasNextInt(int radix) {
778        Pattern integerPattern = getIntegerPattern(radix);
779        boolean isIntValue = false;
780        if (hasNext(integerPattern)) {
781            String intString = matcher.group();
782            intString = removeLocaleInfo(intString, int.class);
783            try {
784                cachedNextValue = Integer.valueOf(intString, radix);
785                isIntValue = true;
786            } catch (NumberFormatException e) {
787                matchSuccessful = false;
788            }
789        }
790        return isIntValue;
791    }
792
793    /**
794     * Returns true if there is a line terminator in the input.
795     * This method may block.
796     *
797     * @throws IllegalStateException if this {@code Scanner} is closed.
798     */
799    public boolean hasNextLine() {
800        prepareForScan();
801        String result = findWithinHorizon(LINE_PATTERN, 0);
802        recoverPreviousStatus();
803        return result != null;
804    }
805
806    /**
807     * Returns whether the next token can be translated into a valid
808     * {@code long} value in the default radix.
809     *
810     * @return {@code true} if the next token can be translated into a valid
811     *         {@code long} value, otherwise {@code false}.
812     * @throws IllegalStateException
813     *             if the {@code Scanner} has been closed.
814     */
815    public boolean hasNextLong() {
816        return hasNextLong(currentRadix);
817    }
818
819    /**
820     * Returns whether the next token can be translated into a valid
821     * {@code long} value in the specified radix.
822     *
823     * @param radix
824     *            the radix used to translate the token into a {@code long}
825     *            value.
826     * @return {@code true} if the next token can be translated into a valid
827     *         {@code long} value, otherwise {@code false}.
828     * @throws IllegalStateException
829     *             if the {@code Scanner} has been closed.
830     */
831    public boolean hasNextLong(int radix) {
832        Pattern integerPattern = getIntegerPattern(radix);
833        boolean isLongValue = false;
834        if (hasNext(integerPattern)) {
835            String intString = matcher.group();
836            intString = removeLocaleInfo(intString, int.class);
837            try {
838                cachedNextValue = Long.valueOf(intString, radix);
839                isLongValue = true;
840            } catch (NumberFormatException e) {
841                matchSuccessful = false;
842            }
843        }
844        return isLongValue;
845    }
846
847    /**
848     * Returns whether the next token can be translated into a valid
849     * {@code short} value in the default radix.
850     *
851     * @return {@code true} if the next token can be translated into a valid
852     *         {@code short} value, otherwise {@code false}.
853     * @throws IllegalStateException
854     *             if the {@code Scanner} has been closed.
855     */
856    public boolean hasNextShort() {
857        return hasNextShort(currentRadix);
858    }
859
860    /**
861     * Returns whether the next token can be translated into a valid
862     * {@code short} value in the specified radix.
863     *
864     * @param radix
865     *            the radix used to translate the token into a {@code short}
866     *            value.
867     * @return {@code true} if the next token can be translated into a valid
868     *         {@code short} value, otherwise {@code false}.
869     * @throws IllegalStateException
870     *             if the {@code Scanner} has been closed.
871     */
872    public boolean hasNextShort(int radix) {
873        Pattern integerPattern = getIntegerPattern(radix);
874        boolean isShortValue = false;
875        if (hasNext(integerPattern)) {
876            String intString = matcher.group();
877            intString = removeLocaleInfo(intString, int.class);
878            try {
879                cachedNextValue = Short.valueOf(intString, radix);
880                isShortValue = true;
881            } catch (NumberFormatException e) {
882                matchSuccessful = false;
883            }
884        }
885        return isShortValue;
886    }
887
888    /**
889     * Returns the last {@code IOException} that was raised while reading from the underlying
890     * input, or {@code null} if none was thrown.
891     */
892    public IOException ioException() {
893        return lastIOException;
894    }
895
896    /**
897     * Returns the {@code Locale} of this {@code Scanner}.
898     */
899    public Locale locale() {
900        return locale;
901    }
902
903    private void setLocale(Locale locale) {
904        this.locale = locale;
905        this.decimalFormat = null;
906        this.cachedFloatPattern = null;
907        this.cachedIntegerPatternRadix = -1;
908        this.cachedIntegerPattern = null;
909    }
910
911    /**
912     * Returns the result of the last matching operation.
913     * <p>
914     * The next* and find* methods return the match result in the case of a
915     * successful match.
916     *
917     * @return the match result of the last successful match operation
918     * @throws IllegalStateException
919     *             if the match result is not available, of if the last match
920     *             was not successful.
921     */
922    public MatchResult match() {
923        if (!matchSuccessful) {
924            throw new IllegalStateException();
925        }
926        return matcher.toMatchResult();
927    }
928
929    /**
930     * Returns the next token. The token will be both prefixed and suffixed by
931     * the delimiter that is currently being used (or a string that matches the
932     * delimiter pattern). This method will block if input is being read.
933     *
934     * @return the next complete token.
935     * @throws IllegalStateException
936     *             if this {@code Scanner} has been closed.
937     * @throws NoSuchElementException
938     *             if input has been exhausted.
939     */
940    public String next() {
941        return next(ANY_PATTERN);
942    }
943
944    /**
945     * Returns the next token if it matches the specified pattern. The token
946     * will be both prefixed and suffixed by the delimiter that is currently
947     * being used (or a string that matches the delimiter pattern). This method will block
948     * if input is being read.
949     *
950     * @param pattern
951     *            the specified pattern to scan.
952     * @return the next token.
953     * @throws IllegalStateException
954     *             if this {@code Scanner} has been closed.
955     * @throws NoSuchElementException
956     *             if input has been exhausted.
957     * @throws InputMismatchException
958     *             if the next token does not match the pattern given.
959     */
960    public String next(Pattern pattern) {
961        checkOpen();
962        checkNotNull(pattern);
963        matchSuccessful = false;
964        prepareForScan();
965        if (!setTokenRegion()) {
966            recoverPreviousStatus();
967            // if setting match region fails
968            throw new NoSuchElementException();
969        }
970        matcher.usePattern(pattern);
971        if (!matcher.matches()) {
972            recoverPreviousStatus();
973            throw new InputMismatchException();
974
975        }
976        matchSuccessful = true;
977        return matcher.group();
978    }
979
980    /**
981     * Returns the next token if it matches the specified pattern. The token
982     * will be both prefixed and suffixed by the delimiter that is currently
983     * being used (or a string that matches the delimiter pattern). This method will block
984     * if input is being read. Calling this method is equivalent to
985     * {@code next(Pattern.compile(pattern))}.
986     *
987     * @param pattern
988     *            the string specifying the pattern to scan for.
989     * @return the next token.
990     * @throws IllegalStateException
991     *             if this {@code Scanner} has been closed.
992     * @throws NoSuchElementException
993     *             if input has been exhausted.
994     * @throws InputMismatchException
995     *             if the next token does not match the pattern given.
996     */
997    public String next(String pattern) {
998        return next(Pattern.compile(pattern));
999    }
1000
1001    /**
1002     * Returns the next token as a {@code BigDecimal}. This method will block if input is
1003     * being read. If the next token can be translated into a {@code BigDecimal}
1004     * the following is done: All {@code Locale}-specific prefixes, group separators,
1005     * and {@code Locale}-specific suffixes are removed. Then non-ASCII digits are
1006     * mapped into ASCII digits via {@link Character#digit(char, int)}, and a
1007     * negative sign (-) is added if the {@code Locale}-specific negative prefix or
1008     * suffix was present. Finally the resulting string is passed to
1009     * {@code BigDecimal(String) }.
1010     *
1011     * @return the next token as a {@code BigDecimal}.
1012     * @throws IllegalStateException
1013     *             if this {@code Scanner} has been closed.
1014     * @throws NoSuchElementException
1015     *             if input has been exhausted.
1016     * @throws InputMismatchException
1017     *             if the next token can not be translated into a valid
1018     *             {@code BigDecimal}.
1019     */
1020    public BigDecimal nextBigDecimal() {
1021        checkOpen();
1022        Object obj = cachedNextValue;
1023        cachedNextValue = null;
1024        if (obj instanceof BigDecimal) {
1025            findStartIndex = cachedNextIndex;
1026            return (BigDecimal) obj;
1027        }
1028        Pattern floatPattern = getFloatPattern();
1029        String floatString = next(floatPattern);
1030        floatString = removeLocaleInfoFromFloat(floatString);
1031        BigDecimal bigDecimalValue;
1032        try {
1033            bigDecimalValue = new BigDecimal(floatString);
1034        } catch (NumberFormatException e) {
1035            matchSuccessful = false;
1036            recoverPreviousStatus();
1037            throw new InputMismatchException();
1038        }
1039        return bigDecimalValue;
1040    }
1041
1042    /**
1043     * Returns the next token as a {@code BigInteger} in the current radix.
1044     * This method may block for more input.
1045     *
1046     * @throws IllegalStateException
1047     *             if this {@code Scanner} has been closed.
1048     * @throws NoSuchElementException
1049     *             if input has been exhausted.
1050     * @throws InputMismatchException
1051     *             if the next token can not be translated into a valid
1052     *             {@code BigInteger}.
1053     */
1054    public BigInteger nextBigInteger() {
1055        return nextBigInteger(currentRadix);
1056    }
1057
1058    /**
1059     * Returns the next token as a {@code BigInteger} with the specified radix.
1060     * This method will block if input is being read. If the next token can be translated
1061     * into a {@code BigInteger} the following is done: All {@code Locale}-specific
1062     * prefixes, group separators, and {@code Locale}-specific suffixes are removed.
1063     * Then non-ASCII digits are mapped into ASCII digits via
1064     * {@link Character#digit(char, int)}, and a negative sign (-) is added if the
1065     * {@code Locale}-specific negative prefix or suffix was present. Finally the
1066     * resulting String is passed to {@link BigInteger#BigInteger(String, int)}}
1067     * with the specified radix.
1068     *
1069     * @param radix
1070     *            the radix used to translate the token into a
1071     *            {@code BigInteger}.
1072     * @return the next token as a {@code BigInteger}
1073     * @throws IllegalStateException
1074     *             if this {@code Scanner} has been closed.
1075     * @throws NoSuchElementException
1076     *             if input has been exhausted.
1077     * @throws InputMismatchException
1078     *             if the next token can not be translated into a valid
1079     *             {@code BigInteger}.
1080     */
1081    public BigInteger nextBigInteger(int radix) {
1082        checkOpen();
1083        Object obj = cachedNextValue;
1084        cachedNextValue = null;
1085        if (obj instanceof BigInteger) {
1086            findStartIndex = cachedNextIndex;
1087            return (BigInteger) obj;
1088        }
1089        Pattern integerPattern = getIntegerPattern(radix);
1090        String intString = next(integerPattern);
1091        intString = removeLocaleInfo(intString, int.class);
1092        BigInteger bigIntegerValue;
1093        try {
1094            bigIntegerValue = new BigInteger(intString, radix);
1095        } catch (NumberFormatException e) {
1096            matchSuccessful = false;
1097            recoverPreviousStatus();
1098            throw new InputMismatchException();
1099        }
1100        return bigIntegerValue;
1101    }
1102
1103    /**
1104     * Returns the next token as a {@code boolean}. This method will block if input is
1105     * being read.
1106     *
1107     * @return the next token as a {@code boolean}.
1108     * @throws IllegalStateException
1109     *             if this {@code Scanner} has been closed.
1110     * @throws NoSuchElementException
1111     *             if input has been exhausted.
1112     * @throws InputMismatchException
1113     *             if the next token can not be translated into a valid
1114     *             {@code boolean} value.
1115     */
1116    public boolean nextBoolean() {
1117        return Boolean.parseBoolean(next(BOOLEAN_PATTERN));
1118    }
1119
1120    /**
1121     * Returns the next token as a {@code byte} in the current radix.
1122     * This method may block for more input.
1123     *
1124     * @throws IllegalStateException
1125     *             if this {@code Scanner} has been closed.
1126     * @throws NoSuchElementException
1127     *             if input has been exhausted.
1128     * @throws InputMismatchException
1129     *             if the next token can not be translated into a valid
1130     *             {@code byte} value.
1131     */
1132    public byte nextByte() {
1133        return nextByte(currentRadix);
1134    }
1135
1136    /**
1137     * Returns the next token as a {@code byte} with the specified radix. Will
1138     * block if input is being read. If the next token can be translated into a
1139     * {@code byte} the following is done: All {@code Locale}-specific prefixes, group
1140     * separators, and {@code Locale}-specific suffixes are removed. Then non-ASCII
1141     * digits are mapped into ASCII digits via
1142     * {@link Character#digit(char, int)}, and a negative sign (-) is added if the
1143     * {@code Locale}-specific negative prefix or suffix was present. Finally the
1144     * resulting String is passed to {@link Byte#parseByte(String, int)}} with
1145     * the specified radix.
1146     *
1147     * @param radix
1148     *            the radix used to translate the token into {@code byte} value.
1149     * @return the next token as a {@code byte}.
1150     * @throws IllegalStateException
1151     *             if this {@code Scanner} has been closed.
1152     * @throws NoSuchElementException
1153     *             if input has been exhausted.
1154     * @throws InputMismatchException
1155     *             if the next token can not be translated into a valid
1156     *             {@code byte} value.
1157     */
1158    @SuppressWarnings("boxing")
1159    public byte nextByte(int radix) {
1160        checkOpen();
1161        Object obj = cachedNextValue;
1162        cachedNextValue = null;
1163        if (obj instanceof Byte) {
1164            findStartIndex = cachedNextIndex;
1165            return (Byte) obj;
1166        }
1167        Pattern integerPattern = getIntegerPattern(radix);
1168        String intString = next(integerPattern);
1169        intString = removeLocaleInfo(intString, int.class);
1170        byte byteValue = 0;
1171        try {
1172            byteValue = Byte.parseByte(intString, radix);
1173        } catch (NumberFormatException e) {
1174            matchSuccessful = false;
1175            recoverPreviousStatus();
1176            throw new InputMismatchException();
1177        }
1178        return byteValue;
1179    }
1180
1181    /**
1182     * Returns the next token as a {@code double}. This method will block if input is being
1183     * read. If the next token can be translated into a {@code double} the
1184     * following is done: All {@code Locale}-specific prefixes, group separators, and
1185     * {@code Locale}-specific suffixes are removed. Then non-ASCII digits are mapped
1186     * into ASCII digits via {@link Character#digit(char, int)}, and a negative
1187     * sign (-) is added if the {@code Locale}-specific negative prefix or suffix was
1188     * present. Finally the resulting String is passed to
1189     * {@link Double#parseDouble(String)}}. If the token matches the localized
1190     * NaN or infinity strings, it is also passed to
1191     * {@link Double#parseDouble(String)}}.
1192     *
1193     * @return the next token as a {@code double}.
1194     * @throws IllegalStateException
1195     *             if this {@code Scanner} has been closed.
1196     * @throws NoSuchElementException
1197     *             if input has been exhausted.
1198     * @throws InputMismatchException
1199     *             if the next token can not be translated into a valid
1200     *             {@code double} value.
1201     */
1202    @SuppressWarnings("boxing")
1203    public double nextDouble() {
1204        checkOpen();
1205        Object obj = cachedNextValue;
1206        cachedNextValue = null;
1207        if (obj instanceof Double) {
1208            findStartIndex = cachedNextIndex;
1209            return (Double) obj;
1210        }
1211        Pattern floatPattern = getFloatPattern();
1212        String floatString = next(floatPattern);
1213        floatString = removeLocaleInfoFromFloat(floatString);
1214        double doubleValue;
1215        try {
1216            doubleValue = Double.parseDouble(floatString);
1217        } catch (NumberFormatException e) {
1218            matchSuccessful = false;
1219            recoverPreviousStatus();
1220            throw new InputMismatchException();
1221        }
1222        return doubleValue;
1223    }
1224
1225    /**
1226     * Returns the next token as a {@code float}. This method will block if input is being
1227     * read. If the next token can be translated into a {@code float} the
1228     * following is done: All {@code Locale}-specific prefixes, group separators, and
1229     * {@code Locale}-specific suffixes are removed. Then non-ASCII digits are mapped
1230     * into ASCII digits via {@link Character#digit(char, int)}, and a negative
1231     * sign (-) is added if the {@code Locale}-specific negative prefix or suffix was
1232     * present. Finally the resulting String is passed to
1233     * {@link Float#parseFloat(String)}}.If the token matches the localized NaN
1234     * or infinity strings, it is also passed to
1235     * {@link Float#parseFloat(String)}}.
1236     *
1237     * @return the next token as a {@code float}.
1238     * @throws IllegalStateException
1239     *             if this {@code Scanner} has been closed.
1240     * @throws NoSuchElementException
1241     *             if input has been exhausted.
1242     * @throws InputMismatchException
1243     *             if the next token can not be translated into a valid
1244     *             {@code float} value.
1245     */
1246    @SuppressWarnings("boxing")
1247    public float nextFloat() {
1248        checkOpen();
1249        Object obj = cachedNextValue;
1250        cachedNextValue = null;
1251        if (obj instanceof Float) {
1252            findStartIndex = cachedNextIndex;
1253            return (Float) obj;
1254        }
1255        Pattern floatPattern = getFloatPattern();
1256        String floatString = next(floatPattern);
1257        floatString = removeLocaleInfoFromFloat(floatString);
1258        float floatValue;
1259        try {
1260            floatValue = Float.parseFloat(floatString);
1261        } catch (NumberFormatException e) {
1262            matchSuccessful = false;
1263            recoverPreviousStatus();
1264            throw new InputMismatchException();
1265        }
1266        return floatValue;
1267    }
1268
1269    /**
1270     * Returns the next token as an {@code int} in the current radix.
1271     * This method may block for more input.
1272     *
1273     * @throws IllegalStateException
1274     *             if this {@code Scanner} has been closed.
1275     * @throws NoSuchElementException
1276     *             if input has been exhausted.
1277     * @throws InputMismatchException
1278     *             if the next token can not be translated into a valid
1279     *             {@code int} value.
1280     */
1281    public int nextInt() {
1282        return nextInt(currentRadix);
1283    }
1284
1285    /**
1286     * Returns the next token as an {@code int} with the specified radix. This method will
1287     * block if input is being read. If the next token can be translated into an
1288     * {@code int} the following is done: All {@code Locale}-specific prefixes, group
1289     * separators, and {@code Locale}-specific suffixes are removed. Then non-ASCII
1290     * digits are mapped into ASCII digits via
1291     * {@link Character#digit(char, int)}, and a negative sign (-) is added if the
1292     * {@code Locale}-specific negative prefix or suffix was present. Finally the
1293     * resulting String is passed to {@link Integer#parseInt(String, int)} with
1294     * the specified radix.
1295     *
1296     * @param radix
1297     *            the radix used to translate the token into an {@code int}
1298     *            value.
1299     * @return the next token as an {@code int}.
1300     * @throws IllegalStateException
1301     *             if this {@code Scanner} has been closed.
1302     * @throws NoSuchElementException
1303     *             if input has been exhausted.
1304     * @throws InputMismatchException
1305     *             if the next token can not be translated into a valid
1306     *             {@code int} value.
1307     */
1308    @SuppressWarnings("boxing")
1309    public int nextInt(int radix) {
1310        checkOpen();
1311        Object obj = cachedNextValue;
1312        cachedNextValue = null;
1313        if (obj instanceof Integer) {
1314            findStartIndex = cachedNextIndex;
1315            return (Integer) obj;
1316        }
1317        Pattern integerPattern = getIntegerPattern(radix);
1318        String intString = next(integerPattern);
1319        intString = removeLocaleInfo(intString, int.class);
1320        int intValue;
1321        try {
1322            intValue = Integer.parseInt(intString, radix);
1323        } catch (NumberFormatException e) {
1324            matchSuccessful = false;
1325            recoverPreviousStatus();
1326            throw new InputMismatchException();
1327        }
1328        return intValue;
1329    }
1330
1331    /**
1332     * Returns the skipped input and advances the {@code Scanner} to the beginning of
1333     * the next line. The returned result will exclude any line terminator. When
1334     * searching, if no line terminator is found, then a large amount of input
1335     * will be cached. If no line at all can be found, a {@code NoSuchElementException}
1336     * will be thrown.
1337     *
1338     * @return the skipped line.
1339     * @throws IllegalStateException
1340     *             if the {@code Scanner} is closed.
1341     * @throws NoSuchElementException
1342     *             if no line can be found, e.g. when input is an empty string.
1343     */
1344    public String nextLine() {
1345        checkOpen();
1346
1347        matcher.usePattern(LINE_PATTERN);
1348        matcher.region(findStartIndex, bufferLength);
1349
1350        String result;
1351        while (true) {
1352            if (matcher.find()) {
1353                if (inputExhausted || matcher.end() != bufferLength
1354                        || bufferLength < buffer.capacity()) {
1355                    matchSuccessful = true;
1356                    findStartIndex = matcher.end();
1357                    result = matcher.group();
1358                    break;
1359                }
1360            } else {
1361                if (inputExhausted) {
1362                    matchSuccessful = false;
1363                    throw new NoSuchElementException();
1364                }
1365            }
1366            if (!inputExhausted) {
1367                readMore();
1368                resetMatcher();
1369            }
1370        }
1371        // Find text without line terminator here.
1372        if (result != null) {
1373            Matcher terminatorMatcher = LINE_TERMINATOR.matcher(result);
1374            if (terminatorMatcher.find()) {
1375                result = result.substring(0, terminatorMatcher.start());
1376            }
1377        }
1378        return result;
1379    }
1380
1381    /**
1382     * Returns the next token as a {@code long} in the current radix.
1383     * This method may block for more input.
1384     *
1385     * @throws IllegalStateException
1386     *             if this {@code Scanner} has been closed.
1387     * @throws NoSuchElementException
1388     *             if input has been exhausted.
1389     * @throws InputMismatchException
1390     *             if the next token can not be translated into a valid
1391     *             {@code long} value.
1392     */
1393    public long nextLong() {
1394        return nextLong(currentRadix);
1395    }
1396
1397    /**
1398     * Returns the next token as a {@code long} with the specified radix. This method will
1399     * block if input is being read. If the next token can be translated into a
1400     * {@code long} the following is done: All {@code Locale}-specific prefixes, group
1401     * separators, and {@code Locale}-specific suffixes are removed. Then non-ASCII
1402     * digits are mapped into ASCII digits via
1403     * {@link Character#digit(char, int)}, and a negative sign (-) is added if the
1404     * {@code Locale}-specific negative prefix or suffix was present. Finally the
1405     * resulting String is passed to {@link Long#parseLong(String, int)}} with
1406     * the specified radix.
1407     *
1408     * @param radix
1409     *            the radix used to translate the token into a {@code long}
1410     *            value.
1411     * @return the next token as a {@code long}.
1412     * @throws IllegalStateException
1413     *             if this {@code Scanner} has been closed.
1414     * @throws NoSuchElementException
1415     *             if input has been exhausted.
1416     * @throws InputMismatchException
1417     *             if the next token can not be translated into a valid
1418     *             {@code long} value.
1419     */
1420    @SuppressWarnings("boxing")
1421    public long nextLong(int radix) {
1422        checkOpen();
1423        Object obj = cachedNextValue;
1424        cachedNextValue = null;
1425        if (obj instanceof Long) {
1426            findStartIndex = cachedNextIndex;
1427            return (Long) obj;
1428        }
1429        Pattern integerPattern = getIntegerPattern(radix);
1430        String intString = next(integerPattern);
1431        intString = removeLocaleInfo(intString, int.class);
1432        long longValue;
1433        try {
1434            longValue = Long.parseLong(intString, radix);
1435        } catch (NumberFormatException e) {
1436            matchSuccessful = false;
1437            recoverPreviousStatus();
1438            throw new InputMismatchException();
1439        }
1440        return longValue;
1441    }
1442
1443    /**
1444     * Returns the next token as a {@code short} in the current radix.
1445     * This method may block for more input.
1446     *
1447     * @throws IllegalStateException
1448     *             if this {@code Scanner} has been closed.
1449     * @throws NoSuchElementException
1450     *             if input has been exhausted.
1451     * @throws InputMismatchException
1452     *             if the next token can not be translated into a valid
1453     *             {@code short} value.
1454     */
1455    public short nextShort() {
1456        return nextShort(currentRadix);
1457    }
1458
1459    /**
1460     * Returns the next token as a {@code short} with the specified radix. This method will
1461     * block if input is being read. If the next token can be translated into a
1462     * {@code short} the following is done: All {@code Locale}-specific prefixes, group
1463     * separators, and {@code Locale}-specific suffixes are removed. Then non-ASCII
1464     * digits are mapped into ASCII digits via
1465     * {@link Character#digit(char, int)}, and a negative sign (-) is added if the
1466     * {@code Locale}-specific negative prefix or suffix was present. Finally the
1467     * resulting String is passed to {@link Short#parseShort(String, int)}}
1468     * with the specified radix.
1469     *
1470     * @param radix
1471     *            the radix used to translate the token into {@code short}
1472     *            value.
1473     * @return the next token as a {@code short}.
1474     * @throws IllegalStateException
1475     *             if this {@code Scanner} has been closed.
1476     * @throws NoSuchElementException
1477     *             if input has been exhausted.
1478     * @throws InputMismatchException
1479     *             if the next token can not be translated into a valid
1480     *             {@code short} value.
1481     */
1482    @SuppressWarnings("boxing")
1483    public short nextShort(int radix) {
1484        checkOpen();
1485        Object obj = cachedNextValue;
1486        cachedNextValue = null;
1487        if (obj instanceof Short) {
1488            findStartIndex = cachedNextIndex;
1489            return (Short) obj;
1490        }
1491        Pattern integerPattern = getIntegerPattern(radix);
1492        String intString = next(integerPattern);
1493        intString = removeLocaleInfo(intString, int.class);
1494        short shortValue;
1495        try {
1496            shortValue = Short.parseShort(intString, radix);
1497        } catch (NumberFormatException e) {
1498            matchSuccessful = false;
1499            recoverPreviousStatus();
1500            throw new InputMismatchException();
1501        }
1502        return shortValue;
1503    }
1504
1505    /**
1506     * Return the radix of this {@code Scanner}.
1507     *
1508     * @return the radix of this {@code Scanner}
1509     */
1510    public int radix() {
1511        return currentRadix;
1512    }
1513
1514    /**
1515     * Tries to use specified pattern to match input starting from the current position.
1516     * The delimiter will be ignored. If a match is found, the matched input will be
1517     * skipped. If an anchored match of the specified pattern succeeds, the corresponding input
1518     * will also be skipped. Otherwise, a {@code NoSuchElementException} will be thrown.
1519     * Patterns that can match a lot of input may cause the {@code Scanner} to read
1520     * in a large amount of input.
1521     *
1522     * @param pattern
1523     *            used to skip over input.
1524     * @return the {@code Scanner} itself.
1525     * @throws IllegalStateException
1526     *             if the {@code Scanner} is closed.
1527     * @throws NoSuchElementException
1528     *             if the specified pattern match fails.
1529     */
1530    public Scanner skip(Pattern pattern) {
1531        checkOpen();
1532        checkNotNull(pattern);
1533        matcher.usePattern(pattern);
1534        matcher.region(findStartIndex, bufferLength);
1535        while (true) {
1536            if (matcher.lookingAt()) {
1537                boolean matchInBuffer = matcher.end() < bufferLength
1538                        || (matcher.end() == bufferLength && inputExhausted);
1539                if (matchInBuffer) {
1540                    matchSuccessful = true;
1541                    findStartIndex = matcher.end();
1542                    break;
1543                }
1544            } else {
1545                if (inputExhausted) {
1546                    matchSuccessful = false;
1547                    throw new NoSuchElementException();
1548                }
1549            }
1550            if (!inputExhausted) {
1551                readMore();
1552                resetMatcher();
1553            }
1554        }
1555        return this;
1556    }
1557
1558    /**
1559     * Tries to use the specified string to construct a pattern and then uses
1560     * the constructed pattern to match input starting from the current position. The
1561     * delimiter will be ignored. This call is the same as invoke
1562     * {@code skip(Pattern.compile(pattern))}.
1563     *
1564     * @param pattern
1565     *            the string used to construct a pattern which in turn is used to
1566     *            match input.
1567     * @return the {@code Scanner} itself.
1568     * @throws IllegalStateException
1569     *             if the {@code Scanner} is closed.
1570     */
1571    public Scanner skip(String pattern) {
1572        return skip(Pattern.compile(pattern));
1573    }
1574
1575    /**
1576     * Returns a string representation of this {@code Scanner}. The information
1577     * returned may be helpful for debugging. The format of the string is unspecified.
1578     *
1579     * @return a string representation of this {@code Scanner}.
1580     */
1581    @Override
1582    public String toString() {
1583        return getClass().getName() +
1584                "[delimiter=" + delimiter +
1585                ",findStartIndex=" + findStartIndex +
1586                ",matchSuccessful=" + matchSuccessful +
1587                ",closed=" + closed +
1588                "]";
1589    }
1590
1591    /**
1592     * Sets the delimiting pattern of this {@code Scanner}.
1593     *
1594     * @param pattern
1595     *            the delimiting pattern to use.
1596     * @return this {@code Scanner}.
1597     */
1598    public Scanner useDelimiter(Pattern pattern) {
1599        delimiter = pattern;
1600        return this;
1601    }
1602
1603    /**
1604     * Sets the delimiting pattern of this {@code Scanner} with a pattern compiled from
1605     * the supplied string value.
1606     *
1607     * @param pattern
1608     *            a string from which a {@code Pattern} can be compiled.
1609     * @return this {@code Scanner}.
1610     */
1611    public Scanner useDelimiter(String pattern) {
1612        return useDelimiter(Pattern.compile(pattern));
1613    }
1614
1615    /**
1616     * Sets the {@code Locale} of this {@code Scanner} to a specified {@code Locale}.
1617     *
1618     * @param l
1619     *            the specified {@code Locale} to use.
1620     * @return this {@code Scanner}.
1621     */
1622    public Scanner useLocale(Locale l) {
1623        if (l == null) {
1624            throw new NullPointerException("l == null");
1625        }
1626        setLocale(l);
1627        return this;
1628    }
1629
1630    /**
1631     * Sets the radix of this {@code Scanner} to the specified radix.
1632     *
1633     * @param radix
1634     *            the specified radix to use.
1635     * @return this {@code Scanner}.
1636     */
1637    public Scanner useRadix(int radix) {
1638        checkRadix(radix);
1639        this.currentRadix = radix;
1640        return this;
1641    }
1642
1643    private void checkRadix(int radix) {
1644        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
1645            throw new IllegalArgumentException("Invalid radix: " + radix);
1646        }
1647    }
1648
1649    /**
1650     * Remove is not a supported operation on {@code Scanner}.
1651     *
1652     * @throws UnsupportedOperationException
1653     *             if this method is invoked.
1654     */
1655    public void remove() {
1656        throw new UnsupportedOperationException();
1657    }
1658
1659    private void checkOpen() {
1660        if (closed) {
1661            throw new IllegalStateException();
1662        }
1663    }
1664
1665    private void checkNotNull(Pattern pattern) {
1666        if (pattern == null) {
1667            throw new NullPointerException("pattern == null");
1668        }
1669    }
1670
1671    /*
1672     * Change the matcher's input after modifying the contents of the buffer.
1673     * The current implementation of Matcher causes a copy of the buffer to be taken.
1674     */
1675    private void resetMatcher() {
1676        matcher.reset(buffer);
1677        matcher.region(findStartIndex, bufferLength);
1678    }
1679
1680    /*
1681     * Recover buffer space for characters that are already processed and save the matcher's state
1682     * in case parsing fails. See recoverPrevousState. This method must be called before
1683     * any buffer offsets are calculated.
1684     */
1685    private void prepareForScan() {
1686        // Compacting the buffer recovers space taken by already processed characters. This does not
1687        // prevent the buffer growing in all situations but keeps the buffer small when delimiters
1688        // exist regularly.
1689        if (findStartIndex >= buffer.capacity() / 2) {
1690            // When over half the buffer is filled with characters no longer being considered by the
1691            // scanner we take the cost of compacting the buffer.
1692
1693            // Move all characters from [findStartIndex, findStartIndex + remaining()) to
1694            // [0, remaining()).
1695            int oldPosition = buffer.position();
1696            buffer.position(findStartIndex);
1697            buffer.compact();
1698            buffer.position(oldPosition);
1699
1700            // Update Scanner state to reflect the new buffer state.
1701            bufferLength -= findStartIndex;
1702            findStartIndex = 0;
1703            preStartIndex = -1;
1704
1705            // The matcher must also be informed that the buffer has changed because it operates on
1706            // a String copy.
1707            resetMatcher();
1708        }
1709
1710        // Save the matcher's last find position so it can be returned to if the next token cannot
1711        // be parsed.
1712        preStartIndex = findStartIndex;
1713    }
1714
1715    /*
1716     * Change the matcher's status to last find position
1717     */
1718    private void recoverPreviousStatus() {
1719        findStartIndex = preStartIndex;
1720    }
1721
1722    private Pattern getIntegerPattern(int radix) {
1723        checkRadix(radix);
1724
1725        if (decimalFormat == null) {
1726            decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
1727        }
1728
1729        if (cachedIntegerPatternRadix == radix) {
1730            return cachedIntegerPattern;
1731        }
1732
1733        String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
1734        String ASCIIDigit = digits.substring(0, radix);
1735        String nonZeroASCIIDigit = digits.substring(1, radix);
1736
1737        String digit = "((?i)[" + ASCIIDigit + "]|\\p{javaDigit})";
1738        String nonZeroDigit = "((?i)[" + nonZeroASCIIDigit + "]|([\\p{javaDigit}&&[^0]]))";
1739        String numeral = getNumeral(digit, nonZeroDigit);
1740
1741        String regex = "(([-+]?(" + numeral + ")))|" +
1742            "(" + addPositiveSign(numeral) + ")|" +
1743            "(" + addNegativeSign(numeral) + ")";
1744
1745        cachedIntegerPatternRadix = radix;
1746        cachedIntegerPattern = Pattern.compile(regex);
1747        return cachedIntegerPattern;
1748    }
1749
1750    private Pattern getFloatPattern() {
1751        if (decimalFormat == null) {
1752            decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
1753        }
1754
1755        if (cachedFloatPattern != null) {
1756            return cachedFloatPattern;
1757        }
1758
1759        DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
1760
1761        String digit = "([0-9]|(\\p{javaDigit}))";
1762        String nonZeroDigit = "[\\p{javaDigit}&&[^0]]";
1763        String numeral = getNumeral(digit, nonZeroDigit);
1764
1765        String decimalSeparator = "\\" + dfs.getDecimalSeparator();
1766        String decimalNumeral = "(" + numeral + "|" +
1767            numeral + decimalSeparator + digit + "*+|" +
1768            decimalSeparator + digit + "++)";
1769        String exponent = "([eE][+-]?" + digit + "+)?";
1770
1771        String decimal = "(([-+]?" + decimalNumeral + "(" + exponent + "?)" + ")|" +
1772            "(" + addPositiveSign(decimalNumeral) + "(" + exponent + "?)" + ")|" +
1773            "(" + addNegativeSign(decimalNumeral) + "(" + exponent + "?)" + "))";
1774
1775        String hexFloat = "([-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?)";
1776        String localNaN = dfs.getNaN();
1777        String localeInfinity = dfs.getInfinity();
1778        String nonNumber = "(NaN|\\Q" + localNaN + "\\E|Infinity|\\Q" + localeInfinity + "\\E)";
1779        String signedNonNumber = "((([-+]?(" + nonNumber + ")))|" +
1780            "(" + addPositiveSign(nonNumber) + ")|" +
1781            "(" + addNegativeSign(nonNumber) + "))";
1782
1783        cachedFloatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" + signedNonNumber);
1784        return cachedFloatPattern;
1785    }
1786
1787    private String getNumeral(String digit, String nonZeroDigit) {
1788        String groupSeparator = "\\" + decimalFormat.getDecimalFormatSymbols().getGroupingSeparator();
1789        String groupedNumeral = "(" + nonZeroDigit + digit + "?" + digit + "?" +
1790            "(" + groupSeparator + digit + digit + digit + ")+)";
1791        return "((" + digit + "++)|" + groupedNumeral + ")";
1792    }
1793
1794    /*
1795     * Add the locale specific positive prefixes and suffixes to the pattern
1796     */
1797    private String addPositiveSign(String unsignedNumeral) {
1798        String positivePrefix = "";
1799        String positiveSuffix = "";
1800        if (!decimalFormat.getPositivePrefix().isEmpty()) {
1801            positivePrefix = "\\Q" + decimalFormat.getPositivePrefix() + "\\E";
1802        }
1803        if (!decimalFormat.getPositiveSuffix().isEmpty()) {
1804            positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E";
1805        }
1806        return positivePrefix + unsignedNumeral + positiveSuffix;
1807    }
1808
1809    /*
1810     * Add the locale specific negative prefixes and suffixes to the pattern
1811     */
1812    private String addNegativeSign(String unsignedNumeral) {
1813        String negativePrefix = "";
1814        String negativeSuffix = "";
1815        if (!decimalFormat.getNegativePrefix().isEmpty()) {
1816            negativePrefix = "\\Q" + decimalFormat.getNegativePrefix() + "\\E";
1817        }
1818        if (!decimalFormat.getNegativeSuffix().isEmpty()) {
1819            negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E";
1820        }
1821        return negativePrefix + unsignedNumeral + negativeSuffix;
1822    }
1823
1824    /*
1825     * Remove locale related information from float String
1826     */
1827    private String removeLocaleInfoFromFloat(String floatString) {
1828        // If the token is HexFloat
1829        if (floatString.indexOf('x') != -1 || floatString.indexOf('X') != -1) {
1830            return floatString;
1831        }
1832
1833        // If the token is scientific notation
1834        int exponentIndex;
1835        if ((exponentIndex = floatString.indexOf('e')) != -1 || (exponentIndex = floatString.indexOf('E')) != -1) {
1836            String decimalNumeralString = floatString.substring(0, exponentIndex);
1837            String exponentString = floatString.substring(exponentIndex + 1, floatString.length());
1838            decimalNumeralString = removeLocaleInfo(decimalNumeralString, float.class);
1839            return decimalNumeralString + "e" + exponentString;
1840        }
1841        return removeLocaleInfo(floatString, float.class);
1842    }
1843
1844    /*
1845     * Remove the locale specific prefixes, group separators, and locale
1846     * specific suffixes from input string
1847     */
1848    private String removeLocaleInfo(String token, Class<?> type) {
1849        DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
1850
1851        StringBuilder tokenBuilder = new StringBuilder(token);
1852        boolean negative = removeLocaleSign(tokenBuilder);
1853        // Remove group separator
1854        String groupSeparator = String.valueOf(dfs.getGroupingSeparator());
1855        int separatorIndex;
1856        while ((separatorIndex = tokenBuilder.indexOf(groupSeparator)) != -1) {
1857            tokenBuilder.delete(separatorIndex, separatorIndex + 1);
1858        }
1859        // Remove decimal separator
1860        String decimalSeparator = String.valueOf(dfs.getDecimalSeparator());
1861        separatorIndex = tokenBuilder.indexOf(decimalSeparator);
1862        StringBuilder result = new StringBuilder("");
1863        if (type == int.class) {
1864            for (int i = 0; i < tokenBuilder.length(); i++) {
1865                if (Character.digit(tokenBuilder.charAt(i), Character.MAX_RADIX) != -1) {
1866                    result.append(tokenBuilder.charAt(i));
1867                }
1868            }
1869        } else if (type == float.class) {
1870            if (tokenBuilder.toString().equals(dfs.getNaN())) {
1871                result.append("NaN");
1872            } else if (tokenBuilder.toString().equals(dfs.getInfinity())) {
1873                result.append("Infinity");
1874            } else {
1875                for (int i = 0; i < tokenBuilder.length(); i++) {
1876                    if (Character.digit(tokenBuilder.charAt(i), 10) != -1) {
1877                        result.append(Character.digit(tokenBuilder.charAt(i), 10));
1878                    }
1879                }
1880            }
1881        } else {
1882            throw new AssertionError("Unsupported type: " + type);
1883        }
1884        // Token is NaN or Infinity
1885        if (result.length() == 0) {
1886            result = tokenBuilder;
1887        }
1888        if (separatorIndex != -1) {
1889            result.insert(separatorIndex, ".");
1890        }
1891        // If input is negative
1892        if (negative) {
1893            result.insert(0, '-');
1894        }
1895        return result.toString();
1896    }
1897
1898    /*
1899     * Remove positive and negative sign from the parameter stringBuilder, and
1900     * return whether the input string is negative
1901     */
1902    private boolean removeLocaleSign(StringBuilder tokenBuilder) {
1903        String positivePrefix = decimalFormat.getPositivePrefix();
1904        String positiveSuffix = decimalFormat.getPositiveSuffix();
1905        String negativePrefix = decimalFormat.getNegativePrefix();
1906        String negativeSuffix = decimalFormat.getNegativeSuffix();
1907
1908        if (tokenBuilder.indexOf("+") == 0) {
1909            tokenBuilder.delete(0, 1);
1910        }
1911        if (!positivePrefix.isEmpty() && tokenBuilder.indexOf(positivePrefix) == 0) {
1912            tokenBuilder.delete(0, positivePrefix.length());
1913        }
1914        if (!positiveSuffix.isEmpty() && tokenBuilder.indexOf(positiveSuffix) != -1) {
1915            tokenBuilder.delete(tokenBuilder.length() - positiveSuffix.length(),
1916                                tokenBuilder.length());
1917        }
1918        boolean negative = false;
1919        if (tokenBuilder.indexOf("-") == 0) {
1920            tokenBuilder.delete(0, 1);
1921            negative = true;
1922        }
1923        if (!negativePrefix.isEmpty() && tokenBuilder.indexOf(negativePrefix) == 0) {
1924            tokenBuilder.delete(0, negativePrefix.length());
1925            negative = true;
1926        }
1927        if (!negativeSuffix.isEmpty() && tokenBuilder.indexOf(negativeSuffix) != -1) {
1928            tokenBuilder.delete(tokenBuilder.length() - negativeSuffix.length(),
1929                                tokenBuilder.length());
1930            negative = true;
1931        }
1932        return negative;
1933    }
1934
1935    /*
1936     * Find the prefixed delimiter and suffixed delimiter in the input resource
1937     * and set the start index and end index of Matcher region. If the suffixed
1938     * delimiter does not exist, the end index is set to be end of input.
1939     */
1940    private boolean setTokenRegion() {
1941        // The position where token begins
1942        int tokenStartIndex;
1943        // The position where token ends
1944        int tokenEndIndex;
1945        // Use delimiter pattern
1946        matcher.usePattern(delimiter);
1947        matcher.region(findStartIndex, bufferLength);
1948
1949        tokenStartIndex = findPreDelimiter();
1950        if (setHeadTokenRegion(tokenStartIndex)) {
1951            return true;
1952        }
1953        tokenEndIndex = findDelimiterAfter();
1954        // If the second delimiter is not found
1955        if (tokenEndIndex == -1) {
1956            // Just first Delimiter Exists
1957            if (findStartIndex == bufferLength) {
1958                return false;
1959            }
1960            tokenEndIndex = bufferLength;
1961            findStartIndex = bufferLength;
1962        }
1963
1964        matcher.region(tokenStartIndex, tokenEndIndex);
1965        return true;
1966    }
1967
1968    /*
1969     * Find prefix delimiter
1970     */
1971    private int findPreDelimiter() {
1972        int tokenStartIndex;
1973        boolean findComplete = false;
1974        while (!findComplete) {
1975            if (matcher.find()) {
1976                findComplete = true;
1977                // If just delimiter remains
1978                if (matcher.start() == findStartIndex && matcher.end() == bufferLength) {
1979                    // If more input resource exists
1980                    if (!inputExhausted) {
1981                        readMore();
1982                        resetMatcher();
1983                        findComplete = false;
1984                    }
1985                }
1986            } else {
1987                if (!inputExhausted) {
1988                    readMore();
1989                    resetMatcher();
1990                } else {
1991                    return -1;
1992                }
1993            }
1994        }
1995        tokenStartIndex = matcher.end();
1996        findStartIndex = tokenStartIndex;
1997        return tokenStartIndex;
1998    }
1999
2000    /*
2001     * Handle some special cases
2002     */
2003    private boolean setHeadTokenRegion(int findIndex) {
2004        int tokenStartIndex;
2005        int tokenEndIndex;
2006        boolean setSuccess = false;
2007        // If no delimiter exists, but something exists in this scanner
2008        if (findIndex == -1 && preStartIndex != bufferLength) {
2009            tokenStartIndex = preStartIndex;
2010            tokenEndIndex = bufferLength;
2011            findStartIndex = bufferLength;
2012            matcher.region(tokenStartIndex, tokenEndIndex);
2013            setSuccess = true;
2014        }
2015        // If the first delimiter of scanner is not at the find start position
2016        if (findIndex != -1 && preStartIndex != matcher.start()) {
2017            tokenStartIndex = preStartIndex;
2018            tokenEndIndex = matcher.start();
2019            findStartIndex = matcher.start();
2020            // set match region and return
2021            matcher.region(tokenStartIndex, tokenEndIndex);
2022            setSuccess = true;
2023        }
2024        return setSuccess;
2025    }
2026
2027    private int findDelimiterAfter() {
2028        int tokenEndIndex;
2029        boolean findComplete = false;
2030        while (!findComplete) {
2031            if (matcher.find()) {
2032                findComplete = true;
2033                if (matcher.start() == findStartIndex && matcher.start() == matcher.end()) {
2034                    findComplete = false;
2035                }
2036            } else {
2037                if (!inputExhausted) {
2038                    readMore();
2039                    resetMatcher();
2040                } else {
2041                    return -1;
2042                }
2043            }
2044        }
2045        tokenEndIndex = matcher.start();
2046        findStartIndex = tokenEndIndex;
2047        return tokenEndIndex;
2048    }
2049
2050    /*
2051     * Read more data from underlying Readable. If nothing is available or I/O
2052     * operation fails, global boolean variable inputExhausted will be set to
2053     * true, otherwise set to false.
2054     */
2055    private void readMore() {
2056        int oldPosition = buffer.position();
2057        int oldBufferLength = bufferLength;
2058        // Increase capacity if empty space is not enough
2059        if (bufferLength >= buffer.capacity()) {
2060            expandBuffer();
2061        }
2062
2063        // Read input resource
2064        int readCount;
2065        try {
2066            buffer.limit(buffer.capacity());
2067            buffer.position(oldBufferLength);
2068            while ((readCount = input.read(buffer)) == 0) {
2069                // nothing to do here
2070            }
2071        } catch (IOException e) {
2072            // Consider the scenario: readable puts 4 chars into
2073            // buffer and then an IOException is thrown out. In this case,
2074            // buffer is actually grown, but readable.read() will never return.
2075            bufferLength = buffer.position();
2076            // Use -1 to record IOException occurring, and no more input can be read.
2077            readCount = -1;
2078            lastIOException = e;
2079        }
2080
2081        buffer.flip();
2082        buffer.position(oldPosition);
2083        if (readCount == -1) {
2084            inputExhausted = true;
2085        } else {
2086            bufferLength = readCount + bufferLength;
2087        }
2088    }
2089
2090    // Expand the size of internal buffer.
2091    private void expandBuffer() {
2092        int oldPosition = buffer.position();
2093        int oldCapacity = buffer.capacity();
2094        int oldLimit = buffer.limit();
2095        int newCapacity = oldCapacity * 2;
2096        char[] newBuffer = new char[newCapacity];
2097        System.arraycopy(buffer.array(), 0, newBuffer, 0, oldLimit);
2098        buffer = CharBuffer.wrap(newBuffer, 0, newCapacity);
2099        buffer.position(oldPosition);
2100        buffer.limit(oldLimit);
2101    }
2102
2103    /**
2104     * Resets this scanner's delimiter, locale, and radix.
2105     *
2106     * @return this scanner
2107     * @since 1.6
2108     */
2109    public Scanner reset() {
2110        delimiter = DEFAULT_DELIMITER;
2111        setLocale(Locale.getDefault());
2112        currentRadix = DEFAULT_RADIX;
2113        return this;
2114    }
2115}
2116