Source Code Cross Referenced for Scanner.java in  » Apache-Harmony-Java-SE » java-package » java » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » java package » java.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Licensed to the Apache Software Foundation (ASF) under one or more
0002:         * contributor license agreements.  See the NOTICE file distributed with
0003:         * this work for additional information regarding copyright ownership.
0004:         * The ASF licenses this file to You under the Apache License, Version 2.0
0005:         * (the "License"); you may not use this file except in compliance with
0006:         * the License.  You may obtain a copy of the License at
0007:         * 
0008:         *     http://www.apache.org/licenses/LICENSE-2.0
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package java.util;
0017:
0018:        import java.io.Closeable;
0019:        import java.io.File;
0020:        import java.io.FileInputStream;
0021:        import java.io.FileNotFoundException;
0022:        import java.io.IOException;
0023:        import java.io.InputStream;
0024:        import java.io.InputStreamReader;
0025:        import java.io.StringReader;
0026:        import java.io.UnsupportedEncodingException;
0027:        import java.math.BigDecimal;
0028:        import java.math.BigInteger;
0029:        import java.nio.CharBuffer;
0030:        import java.nio.channels.Channels;
0031:        import java.nio.channels.ReadableByteChannel;
0032:        import java.nio.charset.Charset;
0033:        import java.text.DecimalFormat;
0034:        import java.text.NumberFormat;
0035:        import java.util.regex.MatchResult;
0036:        import java.util.regex.Matcher;
0037:        import java.util.regex.Pattern;
0038:
0039:        /**
0040:         * A parser that parses a text string of primitive types and strings with the
0041:         * help of regular expressions. It supports localized numbers and various
0042:         * radixes.
0043:         * 
0044:         * The input is broken into tokens by the delimiter pattern, which is whitespace
0045:         * by default. The primitive types can be obtained via corresponding next*
0046:         * methods. If the token is not in a valid format, an InputMismatchException is
0047:         * thrown.
0048:         * 
0049:         * For example: <code>Scanner s = new Scanner("1A true");
0050:         * System.out.println(s.nextInt(16)); System.out.println(s.nextBoolean());</code>
0051:         * The result: <code>26 true</code>
0052:         * 
0053:         * A scanner can also find or skip specific patterns with no regard to the
0054:         * delimiter. All these methods and the various next* and hasNext* methods may
0055:         * block.
0056:         * 
0057:         * The Scanner class is not thread-safe.
0058:         */
0059:        public final class Scanner implements  Iterator<String> {
0060:
0061:            // Default delimiting pattern.
0062:            private static final Pattern DEFAULT_DELIMITER = Pattern
0063:                    .compile("\\p{javaWhitespace}+"); //$NON-NLS-1$
0064:
0065:            // The boolean's pattern.
0066:            private static final Pattern BOOLEAN_PATTERN = Pattern.compile(
0067:                    "true|false", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
0068:
0069:            // Pattern used to recognize line terminator.
0070:            private static final Pattern LINE_TERMINATOR;
0071:
0072:            // Pattern used to recognize multiple line terminators.
0073:            private static final Pattern MULTI_LINE_TERMINATOR;
0074:
0075:            // Pattern used to recognize a line with a line terminator.
0076:            private static final Pattern LINE_PATTERN;
0077:
0078:            static {
0079:                String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029"; //$NON-NLS-1$
0080:
0081:                LINE_TERMINATOR = Pattern.compile(terminator);
0082:
0083:                StringBuilder multiTerminator = new StringBuilder();
0084:                MULTI_LINE_TERMINATOR = Pattern.compile(multiTerminator.append(
0085:                        "(") //$NON-NLS-1$
0086:                        .append(terminator).append(")+").toString()); //$NON-NLS-1$
0087:                StringBuilder line = new StringBuilder();
0088:                LINE_PATTERN = Pattern.compile(line.append(".*(") //$NON-NLS-1$
0089:                        .append(terminator).append(")|.+(") //$NON-NLS-1$
0090:                        .append(terminator).append(")?").toString()); //$NON-NLS-1$
0091:            }
0092:
0093:            // The pattern matches anything.
0094:            private static final Pattern ANY_PATTERN = Pattern
0095:                    .compile("(?s).*"); //$NON-NLS-1$
0096:
0097:            private static final int DIPLOID = 2;
0098:
0099:            // Default radix.
0100:            private static final int DEFAULT_RADIX = 10;
0101:
0102:            private static final int DEFAULT_TRUNK_SIZE = 1024;
0103:
0104:            // The input source of scanner.
0105:            private Readable input;
0106:
0107:            private CharBuffer buffer;
0108:
0109:            private Pattern delimiter = DEFAULT_DELIMITER;
0110:
0111:            private Matcher matcher;
0112:
0113:            private int integerRadix = DEFAULT_RADIX;
0114:
0115:            private Locale locale = Locale.getDefault();
0116:
0117:            // The position where find begins.
0118:            private int findStartIndex = 0;
0119:
0120:            // The last find start position.
0121:            private int preStartIndex = findStartIndex;
0122:
0123:            // The length of the buffer.
0124:            private int bufferLength = 0;
0125:
0126:            // Record the status of this scanner. True if the scanner
0127:            // is closed.
0128:            private boolean closed = false;
0129:
0130:            private IOException lastIOException;
0131:
0132:            private boolean matchSuccessful = false;
0133:
0134:            private DecimalFormat decimalFormat;
0135:
0136:            // Records whether the underlying readable has more input.
0137:            private boolean inputExhausted = false;
0138:
0139:            private Object cacheHasNextValue = null;
0140:
0141:            private int cachehasNextIndex = -1;
0142:
0143:            private enum DataType {
0144:                /*
0145:                 * Stands for Integer
0146:                 */
0147:                INT,
0148:                /*
0149:                 * Stands for Float
0150:                 */
0151:                FLOAT;
0152:            }
0153:
0154:            /**
0155:             * Constructs a scanner that uses File as its input. The default charset is
0156:             * applied when reading the file.
0157:             * 
0158:             * @param src
0159:             *            the file to be scanned
0160:             * @throws FileNotFoundException
0161:             *             if the specified file is not found
0162:             */
0163:            public Scanner(File src) throws FileNotFoundException {
0164:                this (src, Charset.defaultCharset().name());
0165:            }
0166:
0167:            /**
0168:             * Constructs a scanner that uses File as its input. The specified charset
0169:             * is applied when reading the file.
0170:             * 
0171:             * @param src
0172:             *            the file to be scanned
0173:             * @param charsetName
0174:             *            the name of the encoding type of the file
0175:             * @throws FileNotFoundException
0176:             *             if the specified file is not found
0177:             * @throws IllegalArgumentException
0178:             *             if the specified coding does not exist
0179:             */
0180:            public Scanner(File src, String charsetName)
0181:                    throws FileNotFoundException {
0182:                if (null == src) {
0183:                    throw new NullPointerException(
0184:                            org.apache.harmony.luni.util.Msg.getString("KA00a")); //$NON-NLS-1$
0185:                }
0186:                FileInputStream fis = new FileInputStream(src);
0187:                if (null == charsetName) {
0188:                    throw new IllegalArgumentException(
0189:                            org.apache.harmony.luni.util.Msg.getString("KA009")); //$NON-NLS-1$
0190:                }
0191:                try {
0192:                    input = new InputStreamReader(fis, charsetName);
0193:                } catch (UnsupportedEncodingException e) {
0194:                    try {
0195:                        fis.close();
0196:                    } catch (IOException ioException) {
0197:                        // ignore
0198:                    }
0199:                    throw new IllegalArgumentException(e.getMessage());
0200:                }
0201:                initialization();
0202:            }
0203:
0204:            /**
0205:             * Constructs a scanner that uses String as its input.
0206:             * 
0207:             * @param src
0208:             *            the string to be scanned
0209:             */
0210:            public Scanner(String src) {
0211:                input = new StringReader(src);
0212:                initialization();
0213:            }
0214:
0215:            /**
0216:             * Constructs a scanner that uses InputStream as its input. The default
0217:             * charset is applied when decoding the input.
0218:             * 
0219:             * @param src
0220:             *            the input stream to be scanned
0221:             */
0222:            public Scanner(InputStream src) {
0223:                this (src, Charset.defaultCharset().name());
0224:            }
0225:
0226:            /**
0227:             * Constructs a scanner that uses InputStream as its input. The specified
0228:             * charset is applied when decoding the input.
0229:             * 
0230:             * @param src
0231:             *            the input stream to be scanned
0232:             * @param charsetName
0233:             *            the encoding type of the input stream
0234:             * @throws IllegalArgumentException
0235:             *             if the specified character set is not found
0236:             */
0237:            public Scanner(InputStream src, String charsetName) {
0238:                if (null == src) {
0239:                    throw new NullPointerException(
0240:                            org.apache.harmony.luni.util.Msg.getString("KA00b")); //$NON-NLS-1$
0241:                }
0242:                try {
0243:                    input = new InputStreamReader(src, charsetName);
0244:                } catch (UnsupportedEncodingException e) {
0245:                    throw new IllegalArgumentException(e.getMessage());
0246:                }
0247:                initialization();
0248:            }
0249:
0250:            /**
0251:             * Constructs a scanner that uses Readable as its input.
0252:             * 
0253:             * @param src
0254:             *            the Readable to be scanned
0255:             */
0256:            public Scanner(Readable src) {
0257:                if (null == src) {
0258:                    throw new NullPointerException();
0259:                }
0260:                input = src;
0261:                initialization();
0262:            }
0263:
0264:            /**
0265:             * Constructs a scanner that uses ReadableByteChannel as its input. The
0266:             * default charset is applied when decoding the input.
0267:             * 
0268:             * @param src
0269:             *            the ReadableByteChannel to be scanned
0270:             */
0271:            public Scanner(ReadableByteChannel src) {
0272:                this (src, Charset.defaultCharset().name());
0273:            }
0274:
0275:            /**
0276:             * Constructs a scanner that uses ReadableByteChannel as its input. The
0277:             * specified charset is applied when decoding the input.
0278:             * 
0279:             * @param src
0280:             *            the ReadableByteChannel to be scanned
0281:             * @param charsetName
0282:             *            the encoding type of the content in the ReadableByteChannel
0283:             * @throws IllegalArgumentException
0284:             *             if the specified character set is not found
0285:             */
0286:            public Scanner(ReadableByteChannel src, String charsetName) {
0287:                if (null == src) {
0288:                    throw new NullPointerException(
0289:                            org.apache.harmony.luni.util.Msg.getString("KA00d")); //$NON-NLS-1$
0290:                }
0291:                if (null == charsetName) {
0292:                    throw new IllegalArgumentException(
0293:                            org.apache.harmony.luni.util.Msg.getString("KA009")); //$NON-NLS-1$
0294:                }
0295:                input = Channels.newReader(src, charsetName);
0296:                initialization();
0297:            }
0298:
0299:            /**
0300:             * Closes the underlying input if the input implements Closeable. If the
0301:             * scanner has been closed, this method will take no effect. The scanning
0302:             * operation after calling this method will throw IllegalStateException
0303:             * 
0304:             */
0305:            public void close() {
0306:                if (closed) {
0307:                    return;
0308:                }
0309:                if (input instanceof  Closeable) {
0310:                    try {
0311:                        ((Closeable) input).close();
0312:                    } catch (IOException e) {
0313:                        lastIOException = e;
0314:                    }
0315:                }
0316:                closed = true;
0317:            }
0318:
0319:            /**
0320:             * Returns the <code>Pattern</code> in use by this scanner.
0321:             * 
0322:             * @return the <code>Pattern</code> presently in use by this scanner
0323:             */
0324:            public Pattern delimiter() {
0325:                return delimiter;
0326:            }
0327:
0328:            /**
0329:             * Tries to find the pattern in input. Delimiters are ignored. If the
0330:             * pattern is found before line terminator, the matched string will be
0331:             * returned, and the scanner will advance to the end of the matched string.
0332:             * Otherwise, null will be returned and the scanner will not advance the
0333:             * input. When waiting for input, the scanner may be blocked.
0334:             * 
0335:             * All the input may be cached if no line terminator exists in the buffer.
0336:             * 
0337:             * @param pattern
0338:             *            the pattern used to match input
0339:             * @return the matched string
0340:             * @throws IllegalStateException
0341:             *             if the scanner is closed
0342:             */
0343:            public String findInLine(Pattern pattern) {
0344:                checkClosed();
0345:                checkNull(pattern);
0346:                int horizonLineSeparator = 0;
0347:
0348:                matcher.usePattern(MULTI_LINE_TERMINATOR);
0349:                matcher.region(findStartIndex, bufferLength);
0350:
0351:                boolean findComplete = false;
0352:                int terminatorLength = 0;
0353:                while (!findComplete) {
0354:                    if (matcher.find()) {
0355:                        horizonLineSeparator = matcher.start();
0356:                        terminatorLength = matcher.end() - matcher.start();
0357:                        findComplete = true;
0358:                    } else {
0359:                        if (!inputExhausted) {
0360:                            readMore();
0361:                            resetMatcher();
0362:                        } else {
0363:                            horizonLineSeparator = bufferLength;
0364:                            findComplete = true;
0365:                        }
0366:                    }
0367:                }
0368:
0369:                matcher.usePattern(pattern);
0370:
0371:                /*
0372:                 * TODO The following 2 statements are used to deal with regex's bug.
0373:                 * java.util.regex.Matcher.region(int start, int end) implementation
0374:                 * does not have any effects when called. They will be removed once the
0375:                 * bug is fixed.
0376:                 */
0377:                int oldLimit = buffer.limit();
0378:                buffer.limit(horizonLineSeparator);
0379:                // ========== To deal with regex bug ====================
0380:
0381:                matcher.region(findStartIndex, horizonLineSeparator);
0382:                if (matcher.find()) {
0383:                    // The scanner advances past the input that matched
0384:                    findStartIndex = matcher.end();
0385:                    // If the matched pattern is immediately followed by line
0386:                    // terminator.
0387:                    if (horizonLineSeparator == matcher.end()) {
0388:                        findStartIndex += terminatorLength;
0389:                    }
0390:                    matchSuccessful = true;
0391:
0392:                    // ========== To deal with regex bug ====================
0393:                    buffer.limit(oldLimit);
0394:                    // ========== To deal with regex bug ====================
0395:
0396:                    return matcher.group();
0397:                }
0398:
0399:                // ========== To deal with regex bug ====================
0400:                buffer.limit(oldLimit);
0401:                // ========== To deal with regex bug ====================
0402:
0403:                matchSuccessful = false;
0404:                return null;
0405:            }
0406:
0407:            /**
0408:             * Tries to find the pattern compiled from the specified string. The
0409:             * delimiter will be ignored. It is the same as invoke
0410:             * findInLine(Pattern.compile(pattern))
0411:             * 
0412:             * @param pattern
0413:             *            a string used to construct a pattern which in turn used to
0414:             *            match input
0415:             * @return the matched string
0416:             * @throws IllegalStateException
0417:             *             if the scanner is closed
0418:             */
0419:            public String findInLine(String pattern) {
0420:                return findInLine(Pattern.compile(pattern));
0421:            }
0422:
0423:            /**
0424:             * Tries to find the pattern in input from current position to the specified
0425:             * horizon. Delimiters are ignored. If the pattern is found, the matched
0426:             * string will be returned, and the scanner will advance to the end of the
0427:             * matched string. Otherwise, null will be returned and scanner will not
0428:             * advance the input. When waiting for input, the scanner may be blocked.
0429:             * 
0430:             * Scanner will never search exceed horizon code points from current
0431:             * position. The position of horizon does have effects on the result of
0432:             * match. For example, when input is "123", and current position is at zero,
0433:             * findWithinHorizon(Pattern.compile("\\p{Digit}{3}"), 2) will return null.
0434:             * While findWithinHorizon(Pattern.compile("\\p{Digit}{3}"), 3) will return
0435:             * "123". Horizon is treated as a transparent, non-anchoring bound. (refer
0436:             * to {@link Matcher#useTransparentBounds} and
0437:             * {@link Matcher#useAnchoringBounds})
0438:             * 
0439:             * Horizon whose value is zero will be ignored and the whole input will be
0440:             * used for search. Under this situation, all the input may be cached.
0441:             * 
0442:             * An IllegalArgumentException will be thrown out if horizon is less than
0443:             * zero.
0444:             * 
0445:             * @param pattern
0446:             *            the pattern used to scan
0447:             * @param horizon
0448:             *            the search limit
0449:             * @return the matched string
0450:             * @throws IllegalStateException
0451:             *             if the scanner is closed
0452:             * @throws IllegalArgumentException
0453:             *             if horizon is less than zero
0454:             */
0455:            public String findWithinHorizon(Pattern pattern, int horizon) {
0456:                checkClosed();
0457:                checkNull(pattern);
0458:                if (horizon < 0) {
0459:                    throw new IllegalArgumentException(
0460:                            org.apache.harmony.luni.util.Msg.getString("KA00e")); //$NON-NLS-1$
0461:                }
0462:                matcher.usePattern(pattern);
0463:
0464:                String result = null;
0465:                int findEndIndex = 0;
0466:                int horizonEndIndex = 0;
0467:                if (horizon == 0) {
0468:                    horizonEndIndex = Integer.MAX_VALUE;
0469:                } else {
0470:                    horizonEndIndex = findStartIndex + horizon;
0471:                }
0472:                while (true) {
0473:                    findEndIndex = bufferLength;
0474:
0475:                    // If horizon > 0, then search up to
0476:                    // min( bufferLength, findStartIndex + horizon).
0477:                    // Otherwise search until readable is exhausted.
0478:                    findEndIndex = Math.min(horizonEndIndex, bufferLength);
0479:                    // If horizon == 0, consider horizon as always outside buffer.
0480:                    boolean isHorizonInBuffer = (horizonEndIndex <= bufferLength);
0481:                    // First, try to find pattern within buffer. If pattern can not be
0482:                    // found in buffer, then expand the buffer and try again,
0483:                    // util horizonEndIndex is exceeded or no more input left.
0484:                    matcher.region(findStartIndex, findEndIndex);
0485:                    if (matcher.find()) {
0486:                        if (isHorizonInBuffer || inputExhausted) {
0487:                            result = matcher.group();
0488:                            break;
0489:                        }
0490:                    } else {
0491:                        // Pattern is not found in buffer while horizonEndIndex is
0492:                        // within buffer, or input is exhausted. Under this situation,
0493:                        // it can be judged that find fails.
0494:                        if (isHorizonInBuffer || inputExhausted) {
0495:                            break;
0496:                        }
0497:                    }
0498:
0499:                    // Expand buffer and reset matcher if needed.
0500:                    if (!inputExhausted) {
0501:                        readMore();
0502:                        resetMatcher();
0503:                    }
0504:                }
0505:                if (null != result) {
0506:                    findStartIndex = matcher.end();
0507:                    matchSuccessful = true;
0508:                } else {
0509:                    matchSuccessful = false;
0510:                }
0511:                return result;
0512:            }
0513:
0514:            /**
0515:             * Tries to find the pattern in input from current position to the specified
0516:             * horizon. Delimiters are ignored.
0517:             * 
0518:             * It is the same as invoke findWithinHorizon(Pattern.compile(pattern)).
0519:             * 
0520:             * @param pattern
0521:             *            the pattern used to scan
0522:             * @param horizon
0523:             *            the search limit
0524:             * @return the matched string
0525:             * @throws IllegalStateException
0526:             *             if the scanner is closed
0527:             * @throws IllegalArgumentException
0528:             *             if horizon is less than zero
0529:             */
0530:            public String findWithinHorizon(String pattern, int horizon) {
0531:                return findWithinHorizon(Pattern.compile(pattern), horizon);
0532:            }
0533:
0534:            /**
0535:             * Returns true if this scanner has one or more tokens remaining to parse.
0536:             * Will block if the data is still being read.
0537:             * 
0538:             * @return true if this scanner has one or more tokens remaining
0539:             * @throws IllegalStateException
0540:             *             if the scanner has been closed
0541:             */
0542:            public boolean hasNext() {
0543:                return hasNext(ANY_PATTERN);
0544:            }
0545:
0546:            /**
0547:             * Returns true if this scanner has one or more tokens remaining to parse
0548:             * and the next token matches the given pattern. Will block if the data is
0549:             * still being read.
0550:             * 
0551:             * @param pattern
0552:             *            the pattern to check for
0553:             * @return true if this scanner has more tokens and the next token matches
0554:             *         the pattern
0555:             * @throws IllegalStateException
0556:             *             if the scanner has been closed
0557:             */
0558:            public boolean hasNext(Pattern pattern) {
0559:                checkClosed();
0560:                checkNull(pattern);
0561:                matchSuccessful = false;
0562:                saveCurrentStatus();
0563:                // if the next token exists, set the match region, otherwise return
0564:                // false
0565:                if (!setTokenRegion()) {
0566:                    recoverPreviousStatus();
0567:                    return false;
0568:                }
0569:                matcher.usePattern(pattern);
0570:                boolean hasNext = false;
0571:                // check whether next token matches the specified pattern
0572:                if (matcher.matches()) {
0573:                    cachehasNextIndex = findStartIndex;
0574:                    matchSuccessful = true;
0575:                    hasNext = true;
0576:                }
0577:                recoverPreviousStatus();
0578:                return hasNext;
0579:            }
0580:
0581:            /**
0582:             * Returns true if this scanner has one or more tokens remaining to parse
0583:             * and the next token matches a pattern compiled from the given string. Will
0584:             * block if the data is still being read.
0585:             * 
0586:             * Equivalent to <code>hasNext(Pattern.compile(pattern))</code>.
0587:             * 
0588:             * @param pattern
0589:             *            the string representation of the pattern to check for
0590:             * @return true if this scanner has more tokens and the next token matches
0591:             *         the pattern
0592:             * @throws IllegalStateException
0593:             *             if the scanner has been closed
0594:             */
0595:            public boolean hasNext(String pattern) {
0596:                return hasNext(Pattern.compile(pattern));
0597:            }
0598:
0599:            /**
0600:             * Returns true if this scanner's next token can be translated into a valid
0601:             * BigDecimal.
0602:             * 
0603:             * @return true if the next token in this scanner's input can be translated
0604:             *         into a valid BigDecimal
0605:             * @throws IllegalStateException
0606:             *             if the scanner has been closed
0607:             */
0608:            public boolean hasNextBigDecimal() {
0609:                Pattern floatPattern = getFloatPattern();
0610:                boolean isBigDecimalValue = false;
0611:                if (hasNext(floatPattern)) {
0612:                    String floatString = matcher.group();
0613:                    floatString = removeLocaleInfoFromFloat(floatString);
0614:                    try {
0615:                        cacheHasNextValue = new BigDecimal(floatString);
0616:                        isBigDecimalValue = true;
0617:                    } catch (NumberFormatException e) {
0618:                        matchSuccessful = false;
0619:                    }
0620:                }
0621:                return isBigDecimalValue;
0622:            }
0623:
0624:            /**
0625:             * Returns true if this scanner's next token can be translated into a valid
0626:             * BigInteger in the default radix.
0627:             * 
0628:             * @return true if the next token in this scanner's input can be translated
0629:             *         into a valid BigInteger
0630:             * @throws IllegalStateException
0631:             *             if the scanner has been closed
0632:             */
0633:            public boolean hasNextBigInteger() {
0634:                return hasNextBigInteger(integerRadix);
0635:            }
0636:
0637:            /**
0638:             * Returns true if this scanner's next token can be translated into a valid
0639:             * BigInteger in the specified radix.
0640:             * 
0641:             * @param radix
0642:             *            the radix used to translate the token into a BigInteger
0643:             * @return true if the next token in this scanner's input can be translated
0644:             *         into a valid BigInteger
0645:             * @throws IllegalStateException
0646:             *             if the scanner has been closed
0647:             */
0648:            public boolean hasNextBigInteger(int radix) {
0649:                Pattern integerPattern = getIntegerPattern(radix);
0650:                boolean isBigIntegerValue = false;
0651:                if (hasNext(integerPattern)) {
0652:                    String intString = matcher.group();
0653:                    intString = removeLocaleInfo(intString, DataType.INT);
0654:                    try {
0655:                        cacheHasNextValue = new BigInteger(intString, radix);
0656:                        isBigIntegerValue = true;
0657:                    } catch (NumberFormatException e) {
0658:                        matchSuccessful = false;
0659:                    }
0660:                }
0661:                return isBigIntegerValue;
0662:            }
0663:
0664:            /**
0665:             * Returns true if this scanner's next token can be translated into a valid
0666:             * boolean value.
0667:             * 
0668:             * @return true if the next token in this scanner's input can be translated
0669:             *         into a valid boolean value
0670:             * @throws IllegalStateException
0671:             *             if the scanner has been closed
0672:             */
0673:            public boolean hasNextBoolean() {
0674:                return hasNext(BOOLEAN_PATTERN);
0675:            }
0676:
0677:            /**
0678:             * Returns true if this scanner's next token can be translated into a valid
0679:             * byte value in the default radix.
0680:             * 
0681:             * @return true if the next token in this scanner's input can be translated
0682:             *         into a valid byte value
0683:             * @throws IllegalStateException
0684:             *             if the scanner has been closed
0685:             */
0686:            public boolean hasNextByte() {
0687:                return hasNextByte(integerRadix);
0688:            }
0689:
0690:            /**
0691:             * Returns true if this scanner's next token can be translated into a valid
0692:             * byte value in the specified radix.
0693:             * 
0694:             * @param radix
0695:             *            the radix used to translate the token into a byte value
0696:             * @return true if the next token in this scanner's input can be translated
0697:             *         into a valid byte value
0698:             * @throws IllegalStateException
0699:             *             if the scanner has been closed
0700:             */
0701:            public boolean hasNextByte(int radix) {
0702:                Pattern integerPattern = getIntegerPattern(radix);
0703:                boolean isByteValue = false;
0704:                if (hasNext(integerPattern)) {
0705:                    String intString = matcher.group();
0706:                    intString = removeLocaleInfo(intString, DataType.INT);
0707:                    try {
0708:                        cacheHasNextValue = Byte.valueOf(intString, radix);
0709:                        isByteValue = true;
0710:                    } catch (NumberFormatException e) {
0711:                        matchSuccessful = false;
0712:                    }
0713:                }
0714:                return isByteValue;
0715:            }
0716:
0717:            /**
0718:             * Returns true if this scanner's next token can be translated into a valid
0719:             * double value.
0720:             * 
0721:             * @return true if the next token in this scanner's input can be translated
0722:             *         into a valid double value
0723:             * @throws IllegalStateException
0724:             *             if the scanner has been closed
0725:             */
0726:            public boolean hasNextDouble() {
0727:                Pattern floatPattern = getFloatPattern();
0728:                boolean isDoubleValue = false;
0729:                if (hasNext(floatPattern)) {
0730:                    String floatString = matcher.group();
0731:                    floatString = removeLocaleInfoFromFloat(floatString);
0732:                    try {
0733:                        cacheHasNextValue = Double.valueOf(floatString);
0734:                        isDoubleValue = true;
0735:                    } catch (NumberFormatException e) {
0736:                        matchSuccessful = false;
0737:                    }
0738:                }
0739:                return isDoubleValue;
0740:            }
0741:
0742:            /**
0743:             * Returns true if this scanner's next token can be translated into a valid
0744:             * float value.
0745:             * 
0746:             * @return true if the next token in this scanner's input can be translated
0747:             *         into a valid float value
0748:             * @throws IllegalStateException
0749:             *             if the scanner has been closed
0750:             */
0751:            public boolean hasNextFloat() {
0752:                Pattern floatPattern = getFloatPattern();
0753:                boolean isFloatValue = false;
0754:                if (hasNext(floatPattern)) {
0755:                    String floatString = matcher.group();
0756:                    floatString = removeLocaleInfoFromFloat(floatString);
0757:                    try {
0758:                        cacheHasNextValue = Float.valueOf(floatString);
0759:                        isFloatValue = true;
0760:                    } catch (NumberFormatException e) {
0761:                        matchSuccessful = false;
0762:                    }
0763:                }
0764:                return isFloatValue;
0765:            }
0766:
0767:            /**
0768:             * Returns true if this scanner's next token can be translated into a valid
0769:             * int value in the default radix.
0770:             * 
0771:             * @return true if the next token in this scanner's input can be translated
0772:             *         into a valid int value
0773:             * @throws IllegalStateException
0774:             *             if the scanner has been closed
0775:             */
0776:            public boolean hasNextInt() {
0777:                return hasNextInt(integerRadix);
0778:            }
0779:
0780:            /**
0781:             * Returns true if this scanner's next token can be translated into a valid
0782:             * int value in the specified radix.
0783:             * 
0784:             * @param radix
0785:             *            the radix used to translate the token into an int value
0786:             * @return true if the next token in this scanner's input can be translated
0787:             *         into a valid int value
0788:             * @throws IllegalStateException
0789:             *             if the scanner has been closed
0790:             */
0791:            public boolean hasNextInt(int radix) {
0792:                Pattern integerPattern = getIntegerPattern(radix);
0793:                boolean isIntValue = false;
0794:                if (hasNext(integerPattern)) {
0795:                    String intString = matcher.group();
0796:                    intString = removeLocaleInfo(intString, DataType.INT);
0797:                    try {
0798:                        cacheHasNextValue = Integer.valueOf(intString, radix);
0799:                        isIntValue = true;
0800:                    } catch (NumberFormatException e) {
0801:                        matchSuccessful = false;
0802:                    }
0803:                }
0804:                return isIntValue;
0805:            }
0806:
0807:            /**
0808:             * Returns true if there is another line in the input. Otherwise, returns
0809:             * false. When waiting for input, the scanner may be blocked.
0810:             * 
0811:             * @return true if there is another line in the input. Otherwise, false will
0812:             *         be returned.
0813:             * @throws IllegalStateException
0814:             *             if the scanner is closed
0815:             */
0816:            public boolean hasNextLine() {
0817:                checkClosed();
0818:                matcher.usePattern(LINE_PATTERN);
0819:                matcher.region(findStartIndex, bufferLength);
0820:
0821:                boolean hasNextLine = false;
0822:                while (true) {
0823:                    if (matcher.find()) {
0824:                        matchSuccessful = true;
0825:                        hasNextLine = true;
0826:                        break;
0827:                    } else {
0828:                        if (inputExhausted) {
0829:                            matchSuccessful = false;
0830:                            break;
0831:                        }
0832:                    }
0833:                    if (!inputExhausted) {
0834:                        readMore();
0835:                        resetMatcher();
0836:                    }
0837:                }
0838:                return hasNextLine;
0839:            }
0840:
0841:            /**
0842:             * Returns true if this scanner's next token can be translated into a valid
0843:             * long value in the default radix.
0844:             * 
0845:             * @return true if the next token in this scanner's input can be translated
0846:             *         into a valid long value
0847:             * @throws IllegalStateException
0848:             *             if the scanner has been closed
0849:             */
0850:            public boolean hasNextLong() {
0851:                return hasNextLong(integerRadix);
0852:            }
0853:
0854:            /**
0855:             * Returns true if this scanner's next token can be translated into a valid
0856:             * long value in the specified radix.
0857:             * 
0858:             * @param radix
0859:             *            the radix used to translate the token into a long value
0860:             * @return true if the next token in this scanner's input can be translated
0861:             *         into a valid long value
0862:             * @throws IllegalStateException
0863:             *             if the scanner has been closed
0864:             */
0865:            public boolean hasNextLong(int radix) {
0866:                Pattern integerPattern = getIntegerPattern(radix);
0867:                boolean isLongValue = false;
0868:                if (hasNext(integerPattern)) {
0869:                    String intString = matcher.group();
0870:                    intString = removeLocaleInfo(intString, DataType.INT);
0871:                    try {
0872:                        cacheHasNextValue = Long.valueOf(intString, radix);
0873:                        isLongValue = true;
0874:                    } catch (NumberFormatException e) {
0875:                        matchSuccessful = false;
0876:                    }
0877:                }
0878:                return isLongValue;
0879:            }
0880:
0881:            /**
0882:             * Returns true if this scanner's next token can be translated into a valid
0883:             * short value in the default radix.
0884:             * 
0885:             * @return true if the next token in this scanner's input can be translated
0886:             *         into a valid short value
0887:             * @throws IllegalStateException
0888:             *             if the scanner has been closed
0889:             */
0890:            public boolean hasNextShort() {
0891:                return hasNextShort(integerRadix);
0892:            }
0893:
0894:            /**
0895:             * Returns true if this scanner's next token can be translated into a valid
0896:             * short value in the specified radix.
0897:             * 
0898:             * @param radix
0899:             *            the radix used to translate the token into a short value
0900:             * @return true if the next token in this scanner's input can be translated
0901:             *         into a valid short value
0902:             * @throws IllegalStateException
0903:             *             if the scanner has been closed
0904:             */
0905:            public boolean hasNextShort(int radix) {
0906:                Pattern integerPattern = getIntegerPattern(radix);
0907:                boolean isShortValue = false;
0908:                if (hasNext(integerPattern)) {
0909:                    String intString = matcher.group();
0910:                    intString = removeLocaleInfo(intString, DataType.INT);
0911:                    try {
0912:                        cacheHasNextValue = Short.valueOf(intString, radix);
0913:                        isShortValue = true;
0914:                    } catch (NumberFormatException e) {
0915:                        matchSuccessful = false;
0916:                    }
0917:                }
0918:                return isShortValue;
0919:            }
0920:
0921:            /**
0922:             * Returns the last IOException thrown when reading the underlying input. If
0923:             * no exception is thrown, return null.
0924:             * 
0925:             * @return the last IOException thrown
0926:             */
0927:            public IOException ioException() {
0928:                return lastIOException;
0929:            }
0930:
0931:            /**
0932:             * Return the locale of this scanner.
0933:             * 
0934:             * @return the locale of this scanner
0935:             */
0936:            public Locale locale() {
0937:                return locale;
0938:            }
0939:
0940:            /**
0941:             * Returns the match result of this scanner's last match operation.This
0942:             * method throws IllegalStateException if no match operation has been
0943:             * performed, or if the last match was unsuccessful.
0944:             * 
0945:             * The various nextXXX methods of Scanner provide a match result if they do
0946:             * not complete with throwing an exception. For example, after an invocation
0947:             * of the nextBoolean() method which returned a boolean value, this method
0948:             * returns a match result for the search of the Boolean regular expression
0949:             * defined above. In the same way,the findInLine(java.lang.String),
0950:             * findWithinHorizon(java.lang.String, int), and
0951:             * skip(java.util.regex.Pattern) methods will provide a match result if they
0952:             * are successful.
0953:             * 
0954:             * @return the match result of the last match operation
0955:             * @throws IllegalStateException
0956:             *             if the match result is not available
0957:             */
0958:            public MatchResult match() {
0959:                if (!matchSuccessful) {
0960:                    throw new IllegalStateException();
0961:                }
0962:                return matcher.toMatchResult();
0963:            }
0964:
0965:            /**
0966:             * Returns the next token. The token will be both prefixed and postfixed by
0967:             * the delimiter that is currently being used (or a string that matches the
0968:             * delimiter pattern). Will block if input is being read.
0969:             * 
0970:             * @return the next token
0971:             * @throws IllegalStateException
0972:             *             if this scanner has been closed
0973:             * @throws NoSuchElementException
0974:             *             if input has been exhausted
0975:             */
0976:            public String next() {
0977:                return next(ANY_PATTERN);
0978:            }
0979:
0980:            /**
0981:             * Returns the next token if it matches the specified pattern. The token
0982:             * will be both prefixed and postfixed by the delimiter that is currently
0983:             * being used (or a string that matches the delimiter pattern). Will block
0984:             * if input is being read.
0985:             * 
0986:             * @param pattern
0987:             *            the pattern to check for
0988:             * @return the next token
0989:             * @throws IllegalStateException
0990:             *             if this scanner has been closed
0991:             * @throws NoSuchElementException
0992:             *             if input has been exhausted
0993:             * @throws InputMismatchException
0994:             *             if the next token does not match the pattern given
0995:             */
0996:            public String next(Pattern pattern) {
0997:                checkClosed();
0998:                checkNull(pattern);
0999:                matchSuccessful = false;
1000:                saveCurrentStatus();
1001:                if (!setTokenRegion()) {
1002:                    recoverPreviousStatus();
1003:                    // if setting match region fails
1004:                    throw new NoSuchElementException();
1005:                }
1006:                matcher.usePattern(pattern);
1007:                if (!matcher.matches()) {
1008:                    recoverPreviousStatus();
1009:                    throw new InputMismatchException();
1010:
1011:                }
1012:                matchSuccessful = true;
1013:                return matcher.group();
1014:            }
1015:
1016:            /**
1017:             * Returns the next token if it matches the specified pattern. The token
1018:             * will be both prefixed and postfixed by the delimiter that is currently
1019:             * being used (or a string that matches the delimiter pattern). Will block
1020:             * if input is being read.
1021:             * 
1022:             * Equivalent to <code>next(Pattern.compile(pattern))</code>.
1023:             * 
1024:             * @param pattern
1025:             *            the string representation of the pattern to check for
1026:             * @return the next token
1027:             * @throws IllegalStateException
1028:             *             if this scanner has been closed
1029:             * @throws NoSuchElementException
1030:             *             if input has been exhausted
1031:             * @throws InputMismatchException
1032:             *             if the next token does not match the pattern given
1033:             */
1034:            public String next(String pattern) {
1035:                return next(Pattern.compile(pattern));
1036:            }
1037:
1038:            /**
1039:             * Returns the next token as a BigDecimal. Will block if input is being
1040:             * read.
1041:             * 
1042:             * If the next token can be translated into a BigDecimal the following is
1043:             * done: All locale specific prefixes, group separators, and locale specific
1044:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1045:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1046:             * the locale specific negative prefix or suffix was present. Finally the
1047:             * resulting String is passed to {@link BigDecimal#BigDecimal(String)}}.
1048:             * 
1049:             * @return the next token as a BigDecimal
1050:             * @throws IllegalStateException
1051:             *             if this scanner has been closed
1052:             * @throws NoSuchElementException
1053:             *             if input has been exhausted
1054:             * @throws InputMismatchException
1055:             *             if the next token can not be translated into a valid
1056:             *             BigDecimal
1057:             */
1058:            public BigDecimal nextBigDecimal() {
1059:                checkClosed();
1060:                Object obj = cacheHasNextValue;
1061:                cacheHasNextValue = null;
1062:                if (obj instanceof  BigDecimal) {
1063:                    findStartIndex = cachehasNextIndex;
1064:                    return (BigDecimal) obj;
1065:                }
1066:                Pattern floatPattern = getFloatPattern();
1067:                String floatString = next(floatPattern);
1068:                floatString = removeLocaleInfoFromFloat(floatString);
1069:                BigDecimal bigDecimalValue;
1070:                try {
1071:                    bigDecimalValue = new BigDecimal(floatString);
1072:                } catch (NumberFormatException e) {
1073:                    matchSuccessful = false;
1074:                    recoverPreviousStatus();
1075:                    throw new InputMismatchException();
1076:                }
1077:                return bigDecimalValue;
1078:            }
1079:
1080:            /**
1081:             * Returns the next token as a BigInteger. Will block if input is being
1082:             * read.
1083:             * 
1084:             * Equivalent to <code>nextBigInteger(DEFAULT_RADIX)</code>
1085:             * 
1086:             * @return the next token as a BigInteger
1087:             * @throws IllegalStateException
1088:             *             if this scanner has been closed
1089:             * @throws NoSuchElementException
1090:             *             if input has been exhausted
1091:             * @throws InputMismatchException
1092:             *             if the next token can not be translated into a valid
1093:             *             BigInteger
1094:             */
1095:            public BigInteger nextBigInteger() {
1096:                return nextBigInteger(integerRadix);
1097:            }
1098:
1099:            /**
1100:             * Returns the next token as a BigInteger with the specified radix. Will
1101:             * block if input is being read.
1102:             * 
1103:             * If the next token can be translated into a BigInteger the following is
1104:             * done: All locale specific prefixes, group separators, and locale specific
1105:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1106:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1107:             * the locale specific negative prefix or suffix was present. Finally the
1108:             * resulting String is passed to {@link BigInteger#BigInteger(String, int)}}
1109:             * with the specified radix.
1110:             * 
1111:             * @param radix
1112:             *            the radix used to translate the token into a BigInteger
1113:             * @return the next token as a BigInteger
1114:             * @throws IllegalStateException
1115:             *             if this scanner has been closed
1116:             * @throws NoSuchElementException
1117:             *             if input has been exhausted
1118:             * @throws InputMismatchException
1119:             *             if the next token can not be translated into a valid
1120:             *             BigInteger
1121:             */
1122:            public BigInteger nextBigInteger(int radix) {
1123:                checkClosed();
1124:                Object obj = cacheHasNextValue;
1125:                cacheHasNextValue = null;
1126:                if (obj instanceof  BigInteger) {
1127:                    findStartIndex = cachehasNextIndex;
1128:                    return (BigInteger) obj;
1129:                }
1130:                Pattern integerPattern = getIntegerPattern(radix);
1131:                String intString = next(integerPattern);
1132:                intString = removeLocaleInfo(intString, DataType.INT);
1133:                BigInteger bigIntegerValue;
1134:                try {
1135:                    bigIntegerValue = new BigInteger(intString, radix);
1136:                } catch (NumberFormatException e) {
1137:                    matchSuccessful = false;
1138:                    recoverPreviousStatus();
1139:                    throw new InputMismatchException();
1140:                }
1141:                return bigIntegerValue;
1142:            }
1143:
1144:            /**
1145:             * Returns the next token as a boolean. Will block if input is being read.
1146:             * 
1147:             * @return the next token as a boolean
1148:             * @throws IllegalStateException
1149:             *             if this 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 boolean
1154:             *             value
1155:             */
1156:            public boolean nextBoolean() {
1157:                return Boolean.parseBoolean(next(BOOLEAN_PATTERN));
1158:            }
1159:
1160:            /**
1161:             * Returns the next token as a byte. Will block if input is being read.
1162:             * 
1163:             * Equivalent to <code>nextByte(DEFAULT_RADIX)</code>
1164:             * 
1165:             * @return the next token as a byte
1166:             * @throws IllegalStateException
1167:             *             if this scanner has been closed
1168:             * @throws NoSuchElementException
1169:             *             if input has been exhausted
1170:             * @throws InputMismatchException
1171:             *             if the next token can not be translated into a valid byte
1172:             *             value
1173:             */
1174:            public byte nextByte() {
1175:                return nextByte(integerRadix);
1176:            }
1177:
1178:            /**
1179:             * Returns the next token as a byte with the specified radix. Will block if
1180:             * input is being read.
1181:             * 
1182:             * If the next token can be translated into a byte the following is done:
1183:             * All locale specific prefixes, group separators, and locale specific
1184:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1185:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1186:             * the locale specific negative prefix or suffix was present. Finally the
1187:             * resulting String is passed to {@link Byte#parseByte(String, int)}} with
1188:             * the specified radix.
1189:             * 
1190:             * @param radix
1191:             *            the radix used to translate the token into byte value
1192:             * @return the next token as a byte
1193:             * @throws IllegalStateException
1194:             *             if this scanner has been closed
1195:             * @throws NoSuchElementException
1196:             *             if input has been exhausted
1197:             * @throws InputMismatchException
1198:             *             if the next token can not be translated into a valid byte
1199:             *             value
1200:             */
1201:            @SuppressWarnings("boxing")
1202:            public byte nextByte(int radix) {
1203:                checkClosed();
1204:                Object obj = cacheHasNextValue;
1205:                cacheHasNextValue = null;
1206:                if (obj instanceof  Byte) {
1207:                    findStartIndex = cachehasNextIndex;
1208:                    return (Byte) obj;
1209:                }
1210:                Pattern integerPattern = getIntegerPattern(radix);
1211:                String intString = next(integerPattern);
1212:                intString = removeLocaleInfo(intString, DataType.INT);
1213:                byte byteValue = 0;
1214:                try {
1215:                    byteValue = Byte.parseByte(intString, radix);
1216:                } catch (NumberFormatException e) {
1217:                    matchSuccessful = false;
1218:                    recoverPreviousStatus();
1219:                    throw new InputMismatchException();
1220:                }
1221:                return byteValue;
1222:            }
1223:
1224:            /**
1225:             * Returns the next token as a double. Will block if input is being read.
1226:             * 
1227:             * If the next token can be translated into a double the following is done:
1228:             * All locale specific prefixes, group separators, and locale specific
1229:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1230:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1231:             * the locale specific negative prefix or suffix was present. Finally the
1232:             * resulting String is passed to {@link Double#parseDouble(String)}}. If
1233:             * the token matches the localized NaN or infinity strings, it is also
1234:             * passed to {@link Double#parseDouble(String)}}.
1235:             * 
1236:             * @return the next token as a double
1237:             * @throws IllegalStateException
1238:             *             if this scanner has been closed
1239:             * @throws NoSuchElementException
1240:             *             if input has been exhausted
1241:             * @throws InputMismatchException
1242:             *             if the next token can not be translated into a valid double
1243:             *             value
1244:             */
1245:            @SuppressWarnings("boxing")
1246:            public double nextDouble() {
1247:                checkClosed();
1248:                Object obj = cacheHasNextValue;
1249:                cacheHasNextValue = null;
1250:                if (obj instanceof  Double) {
1251:                    findStartIndex = cachehasNextIndex;
1252:                    return (Double) obj;
1253:                }
1254:                Pattern floatPattern = getFloatPattern();
1255:                String floatString = next(floatPattern);
1256:                floatString = removeLocaleInfoFromFloat(floatString);
1257:                double doubleValue = 0;
1258:                try {
1259:                    doubleValue = Double.parseDouble(floatString);
1260:                } catch (NumberFormatException e) {
1261:                    matchSuccessful = false;
1262:                    recoverPreviousStatus();
1263:                    throw new InputMismatchException();
1264:                }
1265:                return doubleValue;
1266:            }
1267:
1268:            /**
1269:             * Returns the next token as a float. Will block if input is being read.
1270:             * 
1271:             * If the next token can be translated into a float the following is done:
1272:             * All locale specific prefixes, group separators, and locale specific
1273:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1274:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1275:             * the locale specific negative prefix or suffix was present. Finally the
1276:             * resulting String is passed to {@link Float#parseFloat(String)}}.If the
1277:             * token matches the localized NaN or infinity strings, it is also passed to
1278:             * {@link Float#parseFloat(String)}}.
1279:             * 
1280:             * @return the next token as a float
1281:             * @throws IllegalStateException
1282:             *             if this scanner has been closed
1283:             * @throws NoSuchElementException
1284:             *             if input has been exhausted
1285:             * @throws InputMismatchException
1286:             *             if the next token can not be translated into a valid float
1287:             *             value
1288:             */
1289:            @SuppressWarnings("boxing")
1290:            public float nextFloat() {
1291:                checkClosed();
1292:                Object obj = cacheHasNextValue;
1293:                cacheHasNextValue = null;
1294:                if (obj instanceof  Float) {
1295:                    findStartIndex = cachehasNextIndex;
1296:                    return (Float) obj;
1297:                }
1298:                Pattern floatPattern = getFloatPattern();
1299:                String floatString = next(floatPattern);
1300:                floatString = removeLocaleInfoFromFloat(floatString);
1301:                float floatValue = 0;
1302:                try {
1303:                    floatValue = Float.parseFloat(floatString);
1304:                } catch (NumberFormatException e) {
1305:                    matchSuccessful = false;
1306:                    recoverPreviousStatus();
1307:                    throw new InputMismatchException();
1308:                }
1309:                return floatValue;
1310:            }
1311:
1312:            /**
1313:             * Returns the next token as an int. Will block if input is being read.
1314:             * 
1315:             * Equivalent to <code>nextInt(DEFAULT_RADIX)</code>.
1316:             * 
1317:             * @return the next token as an int
1318:             * @throws IllegalStateException
1319:             *             if this scanner has been closed
1320:             * @throws NoSuchElementException
1321:             *             if input has been exhausted
1322:             * @throws InputMismatchException
1323:             *             if the next token can not be translated into a valid int
1324:             *             value
1325:             */
1326:            public int nextInt() {
1327:                return nextInt(integerRadix);
1328:            }
1329:
1330:            /**
1331:             * Returns the next token as an int with the specified radix. Will block if
1332:             * input is being read.
1333:             * 
1334:             * If the next token can be translated into an int the following is done:
1335:             * All locale specific prefixes, group separators, and locale specific
1336:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1337:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1338:             * the locale specific negative prefix or suffix was present. Finally the
1339:             * resulting String is passed to {@link Integer#parseInt(String, int)} with
1340:             * the specified radix.
1341:             * 
1342:             * @param radix
1343:             *            the radix used to translate the token into an int value
1344:             * @return the next token as an int
1345:             * @throws IllegalStateException
1346:             *             if this scanner has been closed
1347:             * @throws NoSuchElementException
1348:             *             if input has been exhausted
1349:             * @throws InputMismatchException
1350:             *             if the next token can not be translated into a valid int
1351:             *             value
1352:             */
1353:            @SuppressWarnings("boxing")
1354:            public int nextInt(int radix) {
1355:                checkClosed();
1356:                Object obj = cacheHasNextValue;
1357:                cacheHasNextValue = null;
1358:                if (obj instanceof  Integer) {
1359:                    findStartIndex = cachehasNextIndex;
1360:                    return (Integer) obj;
1361:                }
1362:                Pattern integerPattern = getIntegerPattern(radix);
1363:                String intString = next(integerPattern);
1364:                intString = removeLocaleInfo(intString, DataType.INT);
1365:                int intValue = 0;
1366:                try {
1367:                    intValue = Integer.parseInt(intString, radix);
1368:                } catch (NumberFormatException e) {
1369:                    matchSuccessful = false;
1370:                    recoverPreviousStatus();
1371:                    throw new InputMismatchException();
1372:                }
1373:                return intValue;
1374:            }
1375:
1376:            /**
1377:             * Returns the skipped input and advances the scanner to the beginning of
1378:             * the next line. The returned result will exclude any line terminator.
1379:             * 
1380:             * When searching, if no line terminator is found, then a large amount of
1381:             * input will be cached. If no line at all can be found, a
1382:             * NoSuchElementException will be thrown out.
1383:             * 
1384:             * @return the skipped line
1385:             * @throws IllegalStateException
1386:             *             if the scanner is closed
1387:             * @throws NoSuchElementException
1388:             *             if no line can be found, e.g. when input is an empty string
1389:             */
1390:            public String nextLine() {
1391:                checkClosed();
1392:
1393:                matcher.usePattern(LINE_PATTERN);
1394:                matcher.region(findStartIndex, bufferLength);
1395:                String result = null;
1396:                while (true) {
1397:                    if (matcher.find()) {
1398:                        matchSuccessful = true;
1399:                        findStartIndex = matcher.end();
1400:                        result = matcher.group();
1401:                        break;
1402:                    } else {
1403:                        if (inputExhausted) {
1404:                            matchSuccessful = false;
1405:                            throw new NoSuchElementException();
1406:                        }
1407:                    }
1408:                    if (!inputExhausted) {
1409:                        readMore();
1410:                        resetMatcher();
1411:                    }
1412:                }
1413:                // Find text without line terminator here.
1414:                if (null != result) {
1415:                    Matcher terminatorMatcher = LINE_TERMINATOR.matcher(result);
1416:                    if (terminatorMatcher.find()) {
1417:                        result = result.substring(0, terminatorMatcher.start());
1418:                    }
1419:                }
1420:                return result;
1421:            }
1422:
1423:            /**
1424:             * Returns the next token as a long. Will block if input is being read.
1425:             * 
1426:             * Equivalent to <code>nextLong(DEFAULT_RADIX)</code>.
1427:             * 
1428:             * @return the next token as a long
1429:             * @throws IllegalStateException
1430:             *             if this scanner has been closed
1431:             * @throws NoSuchElementException
1432:             *             if input has been exhausted
1433:             * @throws InputMismatchException
1434:             *             if the next token can not be translated into a valid long
1435:             *             value
1436:             */
1437:            public long nextLong() {
1438:                return nextLong(integerRadix);
1439:            }
1440:
1441:            /**
1442:             * Returns the next token as a long with the specified radix. Will block if
1443:             * input is being read.
1444:             * 
1445:             * If the next token can be translated into a long the following is done:
1446:             * All locale specific prefixes, group separators, and locale specific
1447:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1448:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1449:             * the locale specific negative prefix or suffix was present. Finally the
1450:             * resulting String is passed to {@link Long#parseLong(String, int)}} with
1451:             * the specified radix.
1452:             * 
1453:             * @param radix
1454:             *            the radix used to translate the token into a long value
1455:             * @return the long value scanned from the input
1456:             * @throws IllegalStateException
1457:             *             if this scanner has been closed
1458:             * @throws NoSuchElementException
1459:             *             if input has been exhausted
1460:             * @throws InputMismatchException
1461:             *             if the next token can not be translated into a valid long
1462:             *             value
1463:             */
1464:            @SuppressWarnings("boxing")
1465:            public long nextLong(int radix) {
1466:                checkClosed();
1467:                Object obj = cacheHasNextValue;
1468:                cacheHasNextValue = null;
1469:                if (obj instanceof  Long) {
1470:                    findStartIndex = cachehasNextIndex;
1471:                    return (Long) obj;
1472:                }
1473:                Pattern integerPattern = getIntegerPattern(radix);
1474:                String intString = next(integerPattern);
1475:                intString = removeLocaleInfo(intString, DataType.INT);
1476:                long longValue = 0;
1477:                try {
1478:                    longValue = Long.parseLong(intString, radix);
1479:                } catch (NumberFormatException e) {
1480:                    matchSuccessful = false;
1481:                    recoverPreviousStatus();
1482:                    throw new InputMismatchException();
1483:                }
1484:                return longValue;
1485:            }
1486:
1487:            /**
1488:             * Returns the next token as a short. Will block if input is being read.
1489:             * 
1490:             * Equivalent to <code>nextShort(DEFAULT_RADIX)</code>.
1491:             * 
1492:             * @return the next token as a short
1493:             * @throws IllegalStateException
1494:             *             if this scanner has been closed
1495:             * @throws NoSuchElementException
1496:             *             if input has been exhausted
1497:             * @throws InputMismatchException
1498:             *             if the next token can not be translated into a valid short
1499:             *             value
1500:             */
1501:            public short nextShort() {
1502:                return nextShort(integerRadix);
1503:            }
1504:
1505:            /**
1506:             * Returns the next token as a short with the specified radix. Will block if
1507:             * input is being read.
1508:             * 
1509:             * If the next token can be translated into a short the following is done:
1510:             * All locale specific prefixes, group separators, and locale specific
1511:             * suffixes are removed. Then non-ASCII digits are mapped into ASCII digits
1512:             * via {@link Character#digit(char, int)}, a negative sign (-) is added if
1513:             * the locale specific negative prefix or suffix was present. Finally the
1514:             * resulting String is passed to {@link Short#parseShort(String, int)}}
1515:             * with the specified radix.
1516:             * 
1517:             * @param radix
1518:             *            the radix used to translate the token into short value
1519:             * @return the short value scanned from the input
1520:             * @throws IllegalStateException
1521:             *             if this scanner has been closed
1522:             * @throws NoSuchElementException
1523:             *             if input has been exhausted
1524:             * @throws InputMismatchException
1525:             *             if the next token can not be translated into a valid short
1526:             *             value
1527:             */
1528:            @SuppressWarnings("boxing")
1529:            public short nextShort(int radix) {
1530:                checkClosed();
1531:                Object obj = cacheHasNextValue;
1532:                cacheHasNextValue = null;
1533:                if (obj instanceof  Short) {
1534:                    findStartIndex = cachehasNextIndex;
1535:                    return (Short) obj;
1536:                }
1537:                Pattern integerPattern = getIntegerPattern(radix);
1538:                String intString = next(integerPattern);
1539:                intString = removeLocaleInfo(intString, DataType.INT);
1540:                short shortValue = 0;
1541:                try {
1542:                    shortValue = Short.parseShort(intString, radix);
1543:                } catch (NumberFormatException e) {
1544:                    matchSuccessful = false;
1545:                    recoverPreviousStatus();
1546:                    throw new InputMismatchException();
1547:                }
1548:                return shortValue;
1549:            }
1550:
1551:            /**
1552:             * Return the radix of this scanner.
1553:             * 
1554:             * @return the radix of this scanner
1555:             */
1556:            public int radix() {
1557:                return integerRadix;
1558:            }
1559:
1560:            /**
1561:             * Tries to use specified pattern to match input from the current position.
1562:             * The delimiter will be ignored. If matches, the matched input will be
1563:             * skipped. If an anchored match of the specified pattern succeeds, input
1564:             * will also be skipped. Otherwise, a NoSuchElementException will be thrown
1565:             * out.
1566:             * 
1567:             * Patterns that can match a lot of input may cause the scanner to read in a
1568:             * large amount of input.
1569:             * 
1570:             * Uses a pattern that matches nothing( sc.skip(Pattern.compile("[ \t]*")) )
1571:             * will suppress NoSuchElementException.
1572:             * 
1573:             * @param pattern
1574:             *            used to skip over input
1575:             * @return the scanner itself
1576:             * @throws IllegalStateException
1577:             *             if the scanner is closed
1578:             * @throws NoSuchElementException
1579:             *             if the specified pattern match fails
1580:             */
1581:            public Scanner skip(Pattern pattern) {
1582:                checkClosed();
1583:                checkNull(pattern);
1584:                matcher.usePattern(pattern);
1585:                matcher.region(findStartIndex, bufferLength);
1586:                while (true) {
1587:                    if (matcher.lookingAt()) {
1588:                        boolean matchInBuffer = matcher.end() < bufferLength
1589:                                || (matcher.end() == bufferLength && inputExhausted);
1590:                        if (matchInBuffer) {
1591:                            matchSuccessful = true;
1592:                            findStartIndex = matcher.end();
1593:                            break;
1594:                        }
1595:                    } else {
1596:                        if (inputExhausted) {
1597:                            matchSuccessful = false;
1598:                            throw new NoSuchElementException();
1599:                        }
1600:                    }
1601:                    if (!inputExhausted) {
1602:                        readMore();
1603:                        resetMatcher();
1604:                    }
1605:                }
1606:                return this ;
1607:            }
1608:
1609:            /**
1610:             * Tries to use the specified string to construct a pattern. And then uses
1611:             * the constructed pattern to match input from the current position. The
1612:             * delimiter will be ignored.
1613:             * 
1614:             * It is the same as invoke skip(Pattern.compile(pattern))
1615:             * 
1616:             * @param pattern
1617:             *            the string used to construct a pattern which in turn used to
1618:             *            match input
1619:             * @return the matched input
1620:             * @throws IllegalStateException
1621:             *             if the scanner is closed
1622:             */
1623:            public Scanner skip(String pattern) {
1624:                return skip(Pattern.compile(pattern));
1625:            }
1626:
1627:            /**
1628:             * Returns a string. The string is used to represent this scanner. Contained
1629:             * information may be helpful for debugging. The format of the string is
1630:             * unspecified.
1631:             * 
1632:             * @return a string to represent this scanner
1633:             */
1634:            @Override
1635:            public String toString() {
1636:                StringBuilder stringBuilder = new StringBuilder();
1637:                stringBuilder.append(this .getClass()).append(": ") //$NON-NLS-1$
1638:                        .append("{(delimiter:") //$NON-NLS-1$
1639:                        .append(delimiter).append(")(findStartIndex=") //$NON-NLS-1$
1640:                        .append(findStartIndex).append(")(match succeed=") //$NON-NLS-1$
1641:                        .append(matchSuccessful).append(")(closed=") //$NON-NLS-1$
1642:                        .append(closed).append(")}"); //$NON-NLS-1$
1643:                return stringBuilder.toString();
1644:            }
1645:
1646:            /**
1647:             * Set the delimiting pattern of this scanner
1648:             * 
1649:             * @param pattern
1650:             *            the delimiting pattern to use
1651:             * @return this scanner
1652:             */
1653:            public Scanner useDelimiter(Pattern pattern) {
1654:                delimiter = pattern;
1655:                return this ;
1656:            }
1657:
1658:            /**
1659:             * Set the delimiting pattern of this scanner with a pattern compiled from
1660:             * the supplied string value
1661:             * 
1662:             * @param pattern
1663:             *            a string from which a <code>Pattern</code> can be compiled
1664:             * @return this scanner
1665:             */
1666:            public Scanner useDelimiter(String pattern) {
1667:                return useDelimiter(Pattern.compile(pattern));
1668:            }
1669:
1670:            /**
1671:             * 
1672:             * Set the locale of this scanner to a specified locale.
1673:             * 
1674:             * @param l
1675:             *            the specified locale to use
1676:             * @return this scanner
1677:             */
1678:            public Scanner useLocale(Locale l) {
1679:                if (null == l) {
1680:                    throw new NullPointerException();
1681:                }
1682:                this .locale = l;
1683:                return this ;
1684:            }
1685:
1686:            /**
1687:             * 
1688:             * Set the radix of this scanner to the specified radix.
1689:             * 
1690:             * @param radix
1691:             *            the specified radix to use
1692:             * @return this scanner
1693:             */
1694:            public Scanner useRadix(int radix) {
1695:                if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
1696:                    throw new IllegalArgumentException(
1697:                            org.apache.harmony.luni.util.Msg.getString(
1698:                                    "KA008", radix)); //$NON-NLS-1$
1699:                }
1700:                this .integerRadix = radix;
1701:                return this ;
1702:            }
1703:
1704:            /**
1705:             * Remove is not a supported operation on Scanner.
1706:             * 
1707:             * @throws UnsupportedOperationException if this method is invoked
1708:             */
1709:            public void remove() {
1710:                throw new UnsupportedOperationException();
1711:            }
1712:
1713:            /*
1714:             * Initialize some components.
1715:             */
1716:            private void initialization() {
1717:                buffer = CharBuffer.allocate(DEFAULT_TRUNK_SIZE);
1718:                buffer.limit(0);
1719:                matcher = delimiter.matcher(buffer);
1720:            }
1721:
1722:            /*
1723:             * Check the scanner's state, if it is closed, IllegalStateException will be
1724:             * thrown.
1725:             */
1726:            private void checkClosed() {
1727:                if (closed) {
1728:                    throw new IllegalStateException();
1729:                }
1730:            }
1731:
1732:            /*
1733:             * Check the given pattern. If it is null, then a NullPointerException will
1734:             * be thrown.
1735:             */
1736:            private void checkNull(Pattern pattern) {
1737:                if (null == pattern) {
1738:                    throw new NullPointerException();
1739:                }
1740:            }
1741:
1742:            /*
1743:             * Change the matcher's string after reading input
1744:             */
1745:            private void resetMatcher() {
1746:                if (null == matcher) {
1747:                    matcher = delimiter.matcher(buffer);
1748:                } else {
1749:                    matcher.reset(buffer);
1750:                }
1751:                matcher.region(findStartIndex, bufferLength);
1752:            }
1753:
1754:            /*
1755:             * Save the matcher's last find position
1756:             */
1757:            private void saveCurrentStatus() {
1758:                preStartIndex = findStartIndex;
1759:            }
1760:
1761:            /*
1762:             * Change the matcher's status to last find position
1763:             */
1764:            private void recoverPreviousStatus() {
1765:                findStartIndex = preStartIndex;
1766:            }
1767:
1768:            /*
1769:             * Get integer's pattern
1770:             */
1771:            private Pattern getIntegerPattern(int radix) {
1772:                if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
1773:                    throw new IllegalArgumentException(
1774:                            org.apache.harmony.luni.util.Msg.getString(
1775:                                    "KA00e", radix)); //$NON-NLS-1$
1776:                }
1777:                decimalFormat = (DecimalFormat) NumberFormat
1778:                        .getInstance(locale);
1779:
1780:                String allAvailableDigits = "0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$ 
1781:                String ASCIIDigit = allAvailableDigits.substring(0, radix);
1782:                String nonZeroASCIIDigit = allAvailableDigits.substring(1,
1783:                        radix);
1784:
1785:                StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$ 
1786:                        .append("]|\\p{javaDigit})"); //$NON-NLS-1$
1787:                StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append( //$NON-NLS-1$
1788:                                nonZeroASCIIDigit).append(
1789:                                "]|([\\p{javaDigit}&&[^0]]))"); //$NON-NLS-1$
1790:                StringBuilder numeral = getNumeral(digit, nonZeroDigit);
1791:
1792:                StringBuilder integer = new StringBuilder("(([-+]?(").append(numeral) //$NON-NLS-1$
1793:                        .append(")))|(").append(addPositiveSign(numeral)).append(")|(") //$NON-NLS-1$ //$NON-NLS-2$
1794:                        .append(addNegativeSign(numeral)).append(")"); //$NON-NLS-1$
1795:
1796:                Pattern integerPattern = Pattern.compile(integer.toString());
1797:                return integerPattern;
1798:            }
1799:
1800:            /*
1801:             * Get pattern of float
1802:             */
1803:            private Pattern getFloatPattern() {
1804:                decimalFormat = (DecimalFormat) NumberFormat
1805:                        .getInstance(locale);
1806:
1807:                StringBuilder digit = new StringBuilder(
1808:                        "([0-9]|(\\p{javaDigit}))"); //$NON-NLS-1$
1809:                StringBuilder nonZeroDigit = new StringBuilder(
1810:                        "[\\p{javaDigit}&&[^0]]"); //$NON-NLS-1$
1811:                StringBuilder numeral = getNumeral(digit, nonZeroDigit);
1812:
1813:                String decimalSeparator = "\\" + decimalFormat.getDecimalFormatSymbols()//$NON-NLS-1$
1814:                                .getDecimalSeparator();
1815:                StringBuilder decimalNumeral = new StringBuilder("(").append(numeral) //$NON-NLS-1$
1816:                        .append("|").append(numeral) //$NON-NLS-1$
1817:                        .append(decimalSeparator).append(digit)
1818:                        .append("*+|").append( //$NON-NLS-1$
1819:                                decimalSeparator).append(digit).append("++)"); //$NON-NLS-1$
1820:                StringBuilder exponent = new StringBuilder("([eE][+-]?").append(digit) //$NON-NLS-1$
1821:                        .append("+)?"); //$NON-NLS-1$
1822:
1823:                StringBuilder decimal = new StringBuilder("(([-+]?").append( //$NON-NLS-1$
1824:                                decimalNumeral)
1825:                        .append("(").append(exponent).append("?)") //$NON-NLS-1$ //$NON-NLS-2$
1826:                        .append(")|(").append(addPositiveSign(decimalNumeral)).append( //$NON-NLS-1$
1827:                                "(")
1828:                        .append(exponent)
1829:                        .append("?)").append(")|(") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1830:                        .append(addNegativeSign(decimalNumeral))
1831:                        .append("(").append( //$NON-NLS-1$
1832:                                exponent).append("?)").append("))"); //$NON-NLS-1$ //$NON-NLS-2$
1833:
1834:                StringBuilder hexFloat = new StringBuilder(
1835:                        "([-+]?0[xX][0-9a-fA-F]*") //$NON-NLS-1$
1836:                        .append("\\.").append(//$NON-NLS-1$
1837:                                "[0-9a-fA-F]+([pP][-+]?[0-9]+)?)"); //$NON-NLS-1$
1838:                String localNaN = decimalFormat.getDecimalFormatSymbols()
1839:                        .getNaN();
1840:                String localeInfinity = decimalFormat.getDecimalFormatSymbols()
1841:                        .getInfinity();
1842:                StringBuilder nonNumber = new StringBuilder("(NaN|\\Q").append(localNaN) //$NON-NLS-1$
1843:                        .append("\\E|Infinity|\\Q").append(localeInfinity).append("\\E)"); //$NON-NLS-1$ //$NON-NLS-2$
1844:                StringBuilder singedNonNumber = new StringBuilder("((([-+]?(").append( //$NON-NLS-1$
1845:                                nonNumber)
1846:                        .append(")))|(").append(addPositiveSign(nonNumber)) //$NON-NLS-1$
1847:                        .append(")|(").append(addNegativeSign(nonNumber)).append("))"); //$NON-NLS-1$ //$NON-NLS-2$
1848:
1849:                StringBuilder floatString = new StringBuilder()
1850:                        .append(decimal)
1851:                        .append("|").append(hexFloat).append("|").append(singedNonNumber); //$NON-NLS-1$ //$NON-NLS-2$
1852:                Pattern floatPattern = Pattern.compile(floatString.toString());
1853:                return floatPattern;
1854:            }
1855:
1856:            private StringBuilder getNumeral(StringBuilder digit,
1857:                    StringBuilder nonZeroDigit) {
1858:                String groupSeparator = "\\"//$NON-NLS-1$
1859:                        + decimalFormat.getDecimalFormatSymbols()
1860:                                .getGroupingSeparator();
1861:                StringBuilder groupedNumeral = new StringBuilder("(").append( //$NON-NLS-1$
1862:                        nonZeroDigit).append(digit)
1863:                        .append("?").append(digit).append( //$NON-NLS-1$
1864:                                "?(").append(groupSeparator).append(digit)
1865:                        .append(digit) //$NON-NLS-1$
1866:                        .append(digit).append(")+)"); //$NON-NLS-1$
1867:                StringBuilder numeral = new StringBuilder("((").append(digit).append( //$NON-NLS-1$
1868:                                "++)|").append(groupedNumeral).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
1869:                return numeral;
1870:            }
1871:
1872:            /*
1873:             * Add the locale specific positive prefixes and suffixes to the pattern
1874:             */
1875:            private StringBuilder addPositiveSign(StringBuilder unSignNumeral) {
1876:                String positivePrefix = ""; //$NON-NLS-1$
1877:                String positiveSuffix = ""; //$NON-NLS-1$
1878:                if (!decimalFormat.getPositivePrefix().equals("")) { //$NON-NLS-1$
1879:                    positivePrefix = "\\Q" + decimalFormat.getPositivePrefix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$
1880:                }
1881:                if (!decimalFormat.getPositiveSuffix().equals("")) { //$NON-NLS-1$
1882:                    positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$
1883:                }
1884:                StringBuilder signedNumeral = new StringBuilder().append(
1885:                        positivePrefix).append(unSignNumeral).append(
1886:                        positiveSuffix);
1887:                return signedNumeral;
1888:            }
1889:
1890:            /*
1891:             * Add the locale specific negative prefixes and suffixes to the pattern
1892:             */
1893:            private StringBuilder addNegativeSign(StringBuilder unSignNumeral) {
1894:                String negativePrefix = ""; //$NON-NLS-1$
1895:                String negativeSuffix = ""; //$NON-NLS-1$
1896:                if (!decimalFormat.getNegativePrefix().equals("")) { //$NON-NLS-1$
1897:                    negativePrefix = "\\Q" + decimalFormat.getNegativePrefix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$
1898:                }
1899:                if (!decimalFormat.getNegativeSuffix().equals("")) { //$NON-NLS-1$
1900:                    negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$
1901:                }
1902:                StringBuilder signedNumeral = new StringBuilder().append(
1903:                        negativePrefix).append(unSignNumeral).append(
1904:                        negativeSuffix);
1905:                return signedNumeral;
1906:            }
1907:
1908:            /*
1909:             * Remove locale related information from float String
1910:             */
1911:            private String removeLocaleInfoFromFloat(String floatString) {
1912:                // If the token is HexFloat
1913:                if (-1 != floatString.indexOf('x')
1914:                        || -1 != floatString.indexOf('X')) {
1915:                    return floatString;
1916:                }
1917:
1918:                int exponentIndex;
1919:                String decimalNumeralString;
1920:                String exponentString;
1921:                // If the token is scientific notation
1922:                if (-1 != (exponentIndex = floatString.indexOf('e'))
1923:                        || -1 != (exponentIndex = floatString.indexOf('E'))) {
1924:                    decimalNumeralString = floatString.substring(0,
1925:                            exponentIndex);
1926:                    exponentString = floatString.substring(exponentIndex + 1,
1927:                            floatString.length());
1928:                    decimalNumeralString = removeLocaleInfo(
1929:                            decimalNumeralString, DataType.FLOAT);
1930:                    return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$ 
1931:                }
1932:                return removeLocaleInfo(floatString, DataType.FLOAT);
1933:            }
1934:
1935:            /*
1936:             * Remove the locale specific prefixes, group separators, and locale
1937:             * specific suffixes from input string
1938:             */
1939:            private String removeLocaleInfo(String token, DataType type) {
1940:                StringBuilder tokenBuilder = new StringBuilder(token);
1941:                boolean negative = removeLocaleSign(tokenBuilder);
1942:                // Remove group separator
1943:                String groupSeparator = String.valueOf(decimalFormat
1944:                        .getDecimalFormatSymbols().getGroupingSeparator());
1945:                int separatorIndex = -1;
1946:                while (-1 != (separatorIndex = tokenBuilder
1947:                        .indexOf(groupSeparator))) {
1948:                    tokenBuilder.delete(separatorIndex, separatorIndex + 1);
1949:                }
1950:                // Remove decimal separator
1951:                String decimalSeparator = String.valueOf(decimalFormat
1952:                        .getDecimalFormatSymbols().getDecimalSeparator());
1953:                separatorIndex = tokenBuilder.indexOf(decimalSeparator);
1954:                StringBuilder result = new StringBuilder(""); //$NON-NLS-1$
1955:                if (DataType.INT == type) {
1956:                    for (int i = 0; i < tokenBuilder.length(); i++) {
1957:                        if (-1 != Character.digit(tokenBuilder.charAt(i),
1958:                                Character.MAX_RADIX)) {
1959:                            result.append(tokenBuilder.charAt(i));
1960:                        }
1961:                    }
1962:                }
1963:                if (DataType.FLOAT == type) {
1964:                    if (tokenBuilder.toString().equals(
1965:                            decimalFormat.getDecimalFormatSymbols().getNaN())) {
1966:                        result.append("NaN");//$NON-NLS-1$ 
1967:                    } else if (tokenBuilder.toString().equals(
1968:                            decimalFormat.getDecimalFormatSymbols()
1969:                                    .getInfinity())) {
1970:                        result.append("Infinity");//$NON-NLS-1$ 
1971:                    } else {
1972:                        for (int i = 0; i < tokenBuilder.length(); i++) {
1973:                            if (-1 != Character.digit(tokenBuilder.charAt(i),
1974:                                    10)) {
1975:                                result.append(Character.digit(tokenBuilder
1976:                                        .charAt(i), 10));
1977:                            }
1978:                        }
1979:                    }
1980:                }
1981:                // Token is NaN or Infinity
1982:                if (0 == result.length()) {
1983:                    result = tokenBuilder;
1984:                }
1985:                if (-1 != separatorIndex) {
1986:                    result.insert(separatorIndex, "."); //$NON-NLS-1$
1987:                }
1988:                // If input is negative
1989:                if (negative) {
1990:                    result.insert(0, '-');
1991:                }
1992:                return result.toString();
1993:            }
1994:
1995:            /*
1996:             * Remove positive and negative sign from the parameter stringBuilder, and
1997:             * return whether the input string is negative
1998:             */
1999:            private boolean removeLocaleSign(StringBuilder tokenBuilder) {
2000:                String positivePrefix = decimalFormat.getPositivePrefix();
2001:                String positiveSuffix = decimalFormat.getPositiveSuffix();
2002:                String negativePrefix = decimalFormat.getNegativePrefix();
2003:                String negativeSuffix = decimalFormat.getNegativeSuffix();
2004:
2005:                if (0 == tokenBuilder.indexOf("+")) { //$NON-NLS-1$
2006:                    tokenBuilder.delete(0, 1);
2007:                }
2008:                if (!positivePrefix.equals("") //$NON-NLS-1$
2009:                        && 0 == tokenBuilder.indexOf(positivePrefix)) {
2010:                    tokenBuilder.delete(0, positivePrefix.length());
2011:                }
2012:                if (!positiveSuffix.equals("") //$NON-NLS-1$
2013:                        && -1 != tokenBuilder.indexOf(positiveSuffix)) {
2014:                    tokenBuilder.delete(tokenBuilder.length()
2015:                            - positiveSuffix.length(), tokenBuilder.length());
2016:                }
2017:                boolean negative = false;
2018:                if (0 == tokenBuilder.indexOf("-")) { //$NON-NLS-1$
2019:                    tokenBuilder.delete(0, 1);
2020:                    negative = true;
2021:                }
2022:                if (!negativePrefix.equals("") //$NON-NLS-1$
2023:                        && 0 == tokenBuilder.indexOf(negativePrefix)) {
2024:                    tokenBuilder.delete(0, negativePrefix.length());
2025:                    negative = true;
2026:                }
2027:                if (!negativeSuffix.equals("") //$NON-NLS-1$
2028:                        && -1 != tokenBuilder.indexOf(negativeSuffix)) {
2029:                    tokenBuilder.delete(tokenBuilder.length()
2030:                            - negativeSuffix.length(), tokenBuilder.length());
2031:                    negative = true;
2032:                }
2033:                return negative;
2034:            }
2035:
2036:            /*
2037:             * Find the prefixed delimiter and posefixed delimiter in the input resource
2038:             * and set the start index and end index of Matcher region. If postfixed
2039:             * delimiter does not exist, the end index is set to be end of input.
2040:             */
2041:            private boolean setTokenRegion() {
2042:                // The position where token begins
2043:                int tokenStartIndex = 0;
2044:                // The position where token ends
2045:                int tokenEndIndex = 0;
2046:                // Use delimiter pattern
2047:                matcher.usePattern(delimiter);
2048:                matcher.region(findStartIndex, bufferLength);
2049:
2050:                tokenStartIndex = findPreDelimiter();
2051:                if (setHeadTokenRegion(tokenStartIndex)) {
2052:                    return true;
2053:                }
2054:                tokenEndIndex = findPostDelimiter();
2055:                // If the second delimiter is not found
2056:                if (-1 == tokenEndIndex) {
2057:                    // Just first Delimiter Exists
2058:                    if (findStartIndex == bufferLength) {
2059:                        return false;
2060:                    }
2061:                    tokenEndIndex = bufferLength;
2062:                    findStartIndex = bufferLength;
2063:                }
2064:
2065:                matcher.region(tokenStartIndex, tokenEndIndex);
2066:                return true;
2067:            }
2068:
2069:            /*
2070:             * Find prefix delimiter
2071:             */
2072:            private int findPreDelimiter() {
2073:                int tokenStartIndex;
2074:                boolean findComplete = false;
2075:                while (!findComplete) {
2076:                    if (matcher.find()) {
2077:                        findComplete = true;
2078:                        // If just delimiter remains
2079:                        if (matcher.start() == findStartIndex
2080:                                && matcher.end() == bufferLength) {
2081:                            // If more input resource exists
2082:                            if (!inputExhausted) {
2083:                                readMore();
2084:                                resetMatcher();
2085:                                findComplete = false;
2086:                            }
2087:                        }
2088:                    } else {
2089:                        if (!inputExhausted) {
2090:                            readMore();
2091:                            resetMatcher();
2092:                        } else {
2093:                            return -1;
2094:                        }
2095:                    }
2096:                }
2097:                tokenStartIndex = matcher.end();
2098:                findStartIndex = matcher.end();
2099:                return tokenStartIndex;
2100:            }
2101:
2102:            /*
2103:             * Handle some special cases
2104:             */
2105:            private boolean setHeadTokenRegion(int findIndex) {
2106:                int tokenStartIndex;
2107:                int tokenEndIndex;
2108:                boolean setSuccess = false;
2109:                // If no delimiter exists, but something exites in this scanner
2110:                if (-1 == findIndex && preStartIndex != bufferLength) {
2111:                    tokenStartIndex = preStartIndex;
2112:                    tokenEndIndex = bufferLength;
2113:                    findStartIndex = bufferLength;
2114:                    matcher.region(tokenStartIndex, tokenEndIndex);
2115:                    setSuccess = true;
2116:                }
2117:                // If the first delimiter of scanner is not at the find start position
2118:                if (-1 != findIndex && preStartIndex != matcher.start()) {
2119:                    tokenStartIndex = preStartIndex;
2120:                    tokenEndIndex = matcher.start();
2121:                    findStartIndex = matcher.start();
2122:                    // set match region and return
2123:                    matcher.region(tokenStartIndex, tokenEndIndex);
2124:                    setSuccess = true;
2125:                }
2126:                return setSuccess;
2127:            }
2128:
2129:            /*
2130:             * Find postfix delimiter
2131:             */
2132:            private int findPostDelimiter() {
2133:                int tokenEndIndex = 0;
2134:                boolean findComplete = false;
2135:                while (!findComplete) {
2136:                    if (matcher.find()) {
2137:                        findComplete = true;
2138:                        if (matcher.start() == findStartIndex
2139:                                && matcher.start() == matcher.end()) {
2140:                            findComplete = false;
2141:                        }
2142:                    } else {
2143:                        if (!inputExhausted) {
2144:                            readMore();
2145:                            resetMatcher();
2146:                        } else {
2147:                            return -1;
2148:                        }
2149:                    }
2150:                }
2151:                tokenEndIndex = matcher.start();
2152:                findStartIndex = matcher.start();
2153:                return tokenEndIndex;
2154:            }
2155:
2156:            /*
2157:             * Read more data from underlying Readable. If nothing is available or I/O
2158:             * operation fails, global boolean variable inputExhausted will be set to
2159:             * true, otherwise set to false.
2160:             */
2161:            private void readMore() {
2162:                int oldPosition = buffer.position();
2163:                int oldBufferLength = bufferLength;
2164:                // Increase capacity if empty space is not enough
2165:                if (bufferLength >= buffer.capacity()) {
2166:                    expandBuffer();
2167:                }
2168:
2169:                // Read input resource
2170:                int readCount = 0;
2171:                try {
2172:                    buffer.limit(buffer.capacity());
2173:                    buffer.position(oldBufferLength);
2174:                    while ((readCount = input.read(buffer)) == 0) {
2175:                        // nothing to do here
2176:                    }
2177:                } catch (IOException e) {
2178:                    // Consider the scenario: readable puts 4 chars into
2179:                    // buffer and then an IOException is thrown out. In this case,
2180:                    // buffer is
2181:                    // actually grown, but readable.read() will never return.
2182:                    bufferLength = buffer.position();
2183:                    /*
2184:                     * Uses -1 to record IOException occurring, and no more input can be
2185:                     * read.
2186:                     */
2187:                    readCount = -1;
2188:                    lastIOException = e;
2189:                }
2190:
2191:                buffer.flip();
2192:                buffer.position(oldPosition);
2193:                if (-1 == readCount) {
2194:                    inputExhausted = true;
2195:                } else {
2196:                    bufferLength = readCount + bufferLength;
2197:                }
2198:            }
2199:
2200:            // Expand the size of internal buffer.
2201:            private void expandBuffer() {
2202:                int oldPosition = buffer.position();
2203:                int oldCapacity = buffer.capacity();
2204:                int oldLimit = buffer.limit();
2205:                int newCapacity = oldCapacity * DIPLOID;
2206:                char[] newBuffer = new char[newCapacity];
2207:                System.arraycopy(buffer.array(), 0, newBuffer, 0, oldLimit);
2208:                buffer = CharBuffer.wrap(newBuffer, 0, newCapacity);
2209:                buffer.position(oldPosition);
2210:                buffer.limit(oldLimit);
2211:            }
2212:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.