Home | History | Annotate | Download | only in util
      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  */
     16 package java.util;
     17 
     18 import java.io.Closeable;
     19 import java.io.File;
     20 import java.io.FileInputStream;
     21 import java.io.FileNotFoundException;
     22 import java.io.IOException;
     23 import java.io.InputStream;
     24 import java.io.InputStreamReader;
     25 import java.io.StringReader;
     26 import java.io.UnsupportedEncodingException;
     27 import java.math.BigDecimal;
     28 import java.math.BigInteger;
     29 import java.nio.CharBuffer;
     30 import java.nio.channels.Channels;
     31 import java.nio.channels.ReadableByteChannel;
     32 import java.nio.charset.Charset;
     33 import java.text.DecimalFormat;
     34 import java.text.NumberFormat;
     35 import java.util.regex.MatchResult;
     36 import java.util.regex.Matcher;
     37 import java.util.regex.Pattern;
     38 import 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  */
     62 public 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();
    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();
   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();
   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