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