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