blob: 8fd828fffe9e55222becfda780eee2d888c4a774 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.util;
27
28import java.util.regex.*;
29import java.io.*;
30import java.math.*;
31import java.nio.*;
32import java.nio.channels.*;
33import java.nio.charset.*;
34import java.text.*;
35import java.util.Locale;
36import sun.misc.LRUCache;
37
38/**
39 * A simple text scanner which can parse primitive types and strings using
40 * regular expressions.
41 *
42 * <p>A <code>Scanner</code> breaks its input into tokens using a
43 * delimiter pattern, which by default matches whitespace. The resulting
44 * tokens may then be converted into values of different types using the
45 * various <tt>next</tt> methods.
46 *
47 * <p>For example, this code allows a user to read a number from
48 * <tt>System.in</tt>:
49 * <blockquote><pre>
50 * Scanner sc = new Scanner(System.in);
51 * int i = sc.nextInt();
52 * </pre></blockquote>
53 *
54 * <p>As another example, this code allows <code>long</code> types to be
55 * assigned from entries in a file <code>myNumbers</code>:
56 * <blockquote><pre>
57 * Scanner sc = new Scanner(new File("myNumbers"));
58 * while (sc.hasNextLong()) {
59 * long aLong = sc.nextLong();
60 * }</pre></blockquote>
61 *
62 * <p>The scanner can also use delimiters other than whitespace. This
63 * example reads several items in from a string:
64 *<blockquote><pre>
65 * String input = "1 fish 2 fish red fish blue fish";
66 * Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
67 * System.out.println(s.nextInt());
68 * System.out.println(s.nextInt());
69 * System.out.println(s.next());
70 * System.out.println(s.next());
71 * s.close(); </pre></blockquote>
72 * <p>
73 * prints the following output:
74 * <blockquote><pre>
75 * 1
76 * 2
77 * red
78 * blue </pre></blockquote>
79 *
80 * <p>The same output can be generated with this code, which uses a regular
81 * expression to parse all four tokens at once:
82 *<blockquote><pre>
83 * String input = "1 fish 2 fish red fish blue fish";
84 * Scanner s = new Scanner(input);
85 * s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
86 * MatchResult result = s.match();
87 * for (int i=1; i<=result.groupCount(); i++)
88 * System.out.println(result.group(i));
89 * s.close(); </pre></blockquote>
90 *
91 * <p>The <a name="default-delimiter">default whitespace delimiter</a> used
92 * by a scanner is as recognized by {@link java.lang.Character}.{@link
93 * java.lang.Character#isWhitespace(char) isWhitespace}. The {@link #reset}
94 * method will reset the value of the scanner's delimiter to the default
95 * whitespace delimiter regardless of whether it was previously changed.
96 *
97 * <p>A scanning operation may block waiting for input.
98 *
99 * <p>The {@link #next} and {@link #hasNext} methods and their
100 * primitive-type companion methods (such as {@link #nextInt} and
101 * {@link #hasNextInt}) first skip any input that matches the delimiter
102 * pattern, and then attempt to return the next token. Both <tt>hasNext</tt>
103 * and <tt>next</tt> methods may block waiting for further input. Whether a
104 * <tt>hasNext</tt> method blocks has no connection to whether or not its
105 * associated <tt>next</tt> method will block.
106 *
107 * <p> The {@link #findInLine}, {@link #findWithinHorizon}, and {@link #skip}
108 * methods operate independently of the delimiter pattern. These methods will
109 * attempt to match the specified pattern with no regard to delimiters in the
110 * input and thus can be used in special circumstances where delimiters are
111 * not relevant. These methods may block waiting for more input.
112 *
113 * <p>When a scanner throws an {@link InputMismatchException}, the scanner
114 * will not pass the token that caused the exception, so that it may be
115 * retrieved or skipped via some other method.
116 *
117 * <p>Depending upon the type of delimiting pattern, empty tokens may be
118 * returned. For example, the pattern <tt>"\\s+"</tt> will return no empty
119 * tokens since it matches multiple instances of the delimiter. The delimiting
120 * pattern <tt>"\\s"</tt> could return empty tokens since it only passes one
121 * space at a time.
122 *
123 * <p> A scanner can read text from any object which implements the {@link
124 * java.lang.Readable} interface. If an invocation of the underlying
125 * readable's {@link java.lang.Readable#read} method throws an {@link
126 * java.io.IOException} then the scanner assumes that the end of the input
127 * has been reached. The most recent <tt>IOException</tt> thrown by the
128 * underlying readable can be retrieved via the {@link #ioException} method.
129 *
130 * <p>When a <code>Scanner</code> is closed, it will close its input source
131 * if the source implements the {@link java.io.Closeable} interface.
132 *
133 * <p>A <code>Scanner</code> is not safe for multithreaded use without
134 * external synchronization.
135 *
136 * <p>Unless otherwise mentioned, passing a <code>null</code> parameter into
137 * any method of a <code>Scanner</code> will cause a
138 * <code>NullPointerException</code> to be thrown.
139 *
140 * <p>A scanner will default to interpreting numbers as decimal unless a
141 * different radix has been set by using the {@link #useRadix} method. The
142 * {@link #reset} method will reset the value of the scanner's radix to
143 * <code>10</code> regardless of whether it was previously changed.
144 *
145 * <a name="localized-numbers">
146 * <h4> Localized numbers </h4>
147 *
148 * <p> An instance of this class is capable of scanning numbers in the standard
149 * formats as well as in the formats of the scanner's locale. A scanner's
150 * <a name="initial-locale">initial locale </a>is the value returned by the {@link
151 * java.util.Locale#getDefault} method; it may be changed via the {@link
152 * #useLocale} method. The {@link #reset} method will reset the value of the
153 * scanner's locale to the initial locale regardless of whether it was
154 * previously changed.
155 *
156 * <p>The localized formats are defined in terms of the following parameters,
157 * which for a particular locale are taken from that locale's {@link
158 * java.text.DecimalFormat DecimalFormat} object, <tt>df</tt>, and its and
159 * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object,
160 * <tt>dfs</tt>.
161 *
162 * <blockquote><table>
163 * <tr><td valign="top"><i>LocalGroupSeparator&nbsp;&nbsp;</i></td>
164 * <td valign="top">The character used to separate thousands groups,
165 * <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
166 * java.text.DecimalFormatSymbols#getGroupingSeparator
167 * getGroupingSeparator()}</td></tr>
168 * <tr><td valign="top"><i>LocalDecimalSeparator&nbsp;&nbsp;</i></td>
169 * <td valign="top">The character used for the decimal point,
170 * <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
171 * java.text.DecimalFormatSymbols#getDecimalSeparator
172 * getDecimalSeparator()}</td></tr>
173 * <tr><td valign="top"><i>LocalPositivePrefix&nbsp;&nbsp;</i></td>
174 * <td valign="top">The string that appears before a positive number (may
175 * be empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
176 * java.text.DecimalFormat#getPositivePrefix
177 * getPositivePrefix()}</td></tr>
178 * <tr><td valign="top"><i>LocalPositiveSuffix&nbsp;&nbsp;</i></td>
179 * <td valign="top">The string that appears after a positive number (may be
180 * empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
181 * java.text.DecimalFormat#getPositiveSuffix
182 * getPositiveSuffix()}</td></tr>
183 * <tr><td valign="top"><i>LocalNegativePrefix&nbsp;&nbsp;</i></td>
184 * <td valign="top">The string that appears before a negative number (may
185 * be empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
186 * java.text.DecimalFormat#getNegativePrefix
187 * getNegativePrefix()}</td></tr>
188 * <tr><td valign="top"><i>LocalNegativeSuffix&nbsp;&nbsp;</i></td>
189 * <td valign="top">The string that appears after a negative number (may be
190 * empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
191 * java.text.DecimalFormat#getNegativeSuffix
192 * getNegativeSuffix()}</td></tr>
193 * <tr><td valign="top"><i>LocalNaN&nbsp;&nbsp;</i></td>
194 * <td valign="top">The string that represents not-a-number for
195 * floating-point values,
196 * <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
197 * java.text.DecimalFormatSymbols#getNaN
198 * getNaN()}</td></tr>
199 * <tr><td valign="top"><i>LocalInfinity&nbsp;&nbsp;</i></td>
200 * <td valign="top">The string that represents infinity for floating-point
201 * values, <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
202 * java.text.DecimalFormatSymbols#getInfinity
203 * getInfinity()}</td></tr>
204 * </table></blockquote>
205 *
206 * <a name="number-syntax">
207 * <h4> Number syntax </h4>
208 *
209 * <p> The strings that can be parsed as numbers by an instance of this class
210 * are specified in terms of the following regular-expression grammar, where
211 * Rmax is the highest digit in the radix being used (for example, Rmax is 9
212 * in base 10).
213 *
214 * <p>
215 * <table cellspacing=0 cellpadding=0 align=center>
216 *
217 * <tr><td valign=top align=right><i>NonASCIIDigit</i>&nbsp;&nbsp;::</td>
218 * <td valign=top>= A non-ASCII character c for which
219 * {@link java.lang.Character#isDigit Character.isDigit}<tt>(c)</tt>
220 * returns&nbsp;true</td></tr>
221 *
222 * <tr><td>&nbsp;</td></tr>
223 *
224 * <tr><td align=right><i>Non0Digit</i>&nbsp;&nbsp;::</td>
225 * <td><tt>= [1-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr>
226 *
227 * <tr><td>&nbsp;</td></tr>
228 *
229 * <tr><td align=right><i>Digit</i>&nbsp;&nbsp;::</td>
230 * <td><tt>= [0-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr>
231 *
232 * <tr><td>&nbsp;</td></tr>
233 *
234 * <tr><td valign=top align=right><i>GroupedNumeral</i>&nbsp;&nbsp;::</td>
235 * <td valign=top>
236 * <table cellpadding=0 cellspacing=0>
237 * <tr><td><tt>= (&nbsp;</tt></td>
238 * <td><i>Non0Digit</i><tt>
239 * </tt><i>Digit</i><tt>?
240 * </tt><i>Digit</i><tt>?</tt></td></tr>
241 * <tr><td></td>
242 * <td><tt>(&nbsp;</tt><i>LocalGroupSeparator</i><tt>
243 * </tt><i>Digit</i><tt>
244 * </tt><i>Digit</i><tt>
245 * </tt><i>Digit</i><tt> )+ )</tt></td></tr>
246 * </table></td></tr>
247 *
248 * <tr><td>&nbsp;</td></tr>
249 *
250 * <tr><td align=right><i>Numeral</i>&nbsp;&nbsp;::</td>
251 * <td><tt>= ( ( </tt><i>Digit</i><tt>+ )
252 * | </tt><i>GroupedNumeral</i><tt> )</tt></td></tr>
253 *
254 * <tr><td>&nbsp;</td></tr>
255 *
256 * <tr><td valign=top align=right>
257 * <a name="Integer-regex"><i>Integer</i>&nbsp;&nbsp;::</td>
258 * <td valign=top><tt>= ( [-+]? ( </tt><i>Numeral</i><tt>
259 * ) )</tt></td></tr>
260 * <tr><td></td>
261 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> </tt><i>Numeral</i><tt>
262 * </tt><i>LocalPositiveSuffix</i></td></tr>
263 * <tr><td></td>
264 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> </tt><i>Numeral</i><tt>
265 * </tt><i>LocalNegativeSuffix</i></td></tr>
266 *
267 * <tr><td>&nbsp;</td></tr>
268 *
269 * <tr><td align=right><i>DecimalNumeral</i>&nbsp;&nbsp;::</td>
270 * <td><tt>= </tt><i>Numeral</i></td></tr>
271 * <tr><td></td>
272 * <td><tt>| </tt><i>Numeral</i><tt>
273 * </tt><i>LocalDecimalSeparator</i><tt>
274 * </tt><i>Digit</i><tt>*</tt></td></tr>
275 * <tr><td></td>
276 * <td><tt>| </tt><i>LocalDecimalSeparator</i><tt>
277 * </tt><i>Digit</i><tt>+</tt></td></tr>
278 *
279 * <tr><td>&nbsp;</td></tr>
280 *
281 * <tr><td align=right><i>Exponent</i>&nbsp;&nbsp;::</td>
282 * <td><tt>= ( [eE] [+-]? </tt><i>Digit</i><tt>+ )</tt></td></tr>
283 *
284 * <tr><td>&nbsp;</td></tr>
285 *
286 * <tr><td align=right>
287 * <a name="Decimal-regex"><i>Decimal</i>&nbsp;&nbsp;::</td>
288 * <td><tt>= ( [-+]? </tt><i>DecimalNumeral</i><tt>
289 * </tt><i>Exponent</i><tt>? )</tt></td></tr>
290 * <tr><td></td>
291 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt>
292 * </tt><i>DecimalNumeral</i><tt>
293 * </tt><i>LocalPositiveSuffix</i>
294 * </tt><i>Exponent</i><tt>?</td></tr>
295 * <tr><td></td>
296 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt>
297 * </tt><i>DecimalNumeral</i><tt>
298 * </tt><i>LocalNegativeSuffix</i>
299 * </tt><i>Exponent</i><tt>?</td></tr>
300 *
301 * <tr><td>&nbsp;</td></tr>
302 *
303 * <tr><td align=right><i>HexFloat</i>&nbsp;&nbsp;::</td>
304 * <td><tt>= [-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+
305 * ([pP][-+]?[0-9]+)?</tt></td></tr>
306 *
307 * <tr><td>&nbsp;</td></tr>
308 *
309 * <tr><td align=right><i>NonNumber</i>&nbsp;&nbsp;::</td>
310 * <td valign=top><tt>= NaN
311 * | </tt><i>LocalNan</i><tt>
312 * | Infinity
313 * | </tt><i>LocalInfinity</i></td></tr>
314 *
315 * <tr><td>&nbsp;</td></tr>
316 *
317 * <tr><td align=right><i>SignedNonNumber</i>&nbsp;&nbsp;::</td>
318 * <td><tt>= ( [-+]? </tt><i>NonNumber</i><tt> )</tt></td></tr>
319 * <tr><td></td>
320 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt>
321 * </tt><i>NonNumber</i><tt>
322 * </tt><i>LocalPositiveSuffix</i></td></tr>
323 * <tr><td></td>
324 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt>
325 * </tt><i>NonNumber</i><tt>
326 * </tt><i>LocalNegativeSuffix</i></td></tr>
327 *
328 * <tr><td>&nbsp;</td></tr>
329 *
330 * <tr><td valign=top align=right>
331 * <a name="Float-regex"><i>Float</i>&nbsp;&nbsp;::</td>
332 * <td valign=top><tt>= </tt><i>Decimal</i><tt></td></tr>
333 * <tr><td></td>
334 * <td><tt>| </tt><i>HexFloat</i><tt></td></tr>
335 * <tr><td></td>
336 * <td><tt>| </tt><i>SignedNonNumber</i><tt></td></tr>
337 *
338 * </table>
339 * </center>
340 *
341 * <p> Whitespace is not significant in the above regular expressions.
342 *
343 * @since 1.5
344 */
345public final class Scanner implements Iterator<String> {
346
347 // Internal buffer used to hold input
348 private CharBuffer buf;
349
350 // Size of internal character buffer
351 private static final int BUFFER_SIZE = 1024; // change to 1024;
352
353 // The index into the buffer currently held by the Scanner
354 private int position;
355
356 // Internal matcher used for finding delimiters
357 private Matcher matcher;
358
359 // Pattern used to delimit tokens
360 private Pattern delimPattern;
361
362 // Pattern found in last hasNext operation
363 private Pattern hasNextPattern;
364
365 // Position after last hasNext operation
366 private int hasNextPosition;
367
368 // Result after last hasNext operation
369 private String hasNextResult;
370
371 // The input source
372 private Readable source;
373
374 // Boolean is true if source is done
375 private boolean sourceClosed = false;
376
377 // Boolean indicating more input is required
378 private boolean needInput = false;
379
380 // Boolean indicating if a delim has been skipped this operation
381 private boolean skipped = false;
382
383 // A store of a position that the scanner may fall back to
384 private int savedScannerPosition = -1;
385
386 // A cache of the last primitive type scanned
387 private Object typeCache = null;
388
389 // Boolean indicating if a match result is available
390 private boolean matchValid = false;
391
392 // Boolean indicating if this scanner has been closed
393 private boolean closed = false;
394
395 // The current radix used by this scanner
396 private int radix = 10;
397
398 // The default radix for this scanner
399 private int defaultRadix = 10;
400
401 // The locale used by this scanner
402 private Locale locale = null;
403
404 // A cache of the last few recently used Patterns
405 private LRUCache<String,Pattern> patternCache =
406 new LRUCache<String,Pattern>(7) {
407 protected Pattern create(String s) {
408 return Pattern.compile(s);
409 }
410 protected boolean hasName(Pattern p, String s) {
411 return p.pattern().equals(s);
412 }
413 };
414
415 // A holder of the last IOException encountered
416 private IOException lastException;
417
418 // A pattern for java whitespace
419 private static Pattern WHITESPACE_PATTERN = Pattern.compile(
420 "\\p{javaWhitespace}+");
421
422 // A pattern for any token
423 private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
424
425 // A pattern for non-ASCII digits
426 private static Pattern NON_ASCII_DIGIT = Pattern.compile(
427 "[\\p{javaDigit}&&[^0-9]]");
428
429 // Fields and methods to support scanning primitive types
430
431 /**
432 * Locale dependent values used to scan numbers
433 */
434 private String groupSeparator = "\\,";
435 private String decimalSeparator = "\\.";
436 private String nanString = "NaN";
437 private String infinityString = "Infinity";
438 private String positivePrefix = "";
439 private String negativePrefix = "\\-";
440 private String positiveSuffix = "";
441 private String negativeSuffix = "";
442
443 /**
444 * Fields and an accessor method to match booleans
445 */
446 private static volatile Pattern boolPattern;
447 private static final String BOOLEAN_PATTERN = "true|false";
448 private static Pattern boolPattern() {
449 Pattern bp = boolPattern;
450 if (bp == null)
451 boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN,
452 Pattern.CASE_INSENSITIVE);
453 return bp;
454 }
455
456 /**
457 * Fields and methods to match bytes, shorts, ints, and longs
458 */
459 private Pattern integerPattern;
460 private String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
461 private String non0Digit = "[\\p{javaDigit}&&[^0]]";
462 private int SIMPLE_GROUP_INDEX = 5;
463 private String buildIntegerPatternString() {
464 String radixDigits = digits.substring(0, radix);
465 // \\p{javaDigit} is not guaranteed to be appropriate
466 // here but what can we do? The final authority will be
467 // whatever parse method is invoked, so ultimately the
468 // Scanner will do the right thing
469 String digit = "((?i)["+radixDigits+"]|\\p{javaDigit})";
470 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
471 groupSeparator+digit+digit+digit+")+)";
472 // digit++ is the possessive form which is necessary for reducing
473 // backtracking that would otherwise cause unacceptable performance
474 String numeral = "(("+ digit+"++)|"+groupedNumeral+")";
475 String javaStyleInteger = "([-+]?(" + numeral + "))";
476 String negativeInteger = negativePrefix + numeral + negativeSuffix;
477 String positiveInteger = positivePrefix + numeral + positiveSuffix;
478 return "("+ javaStyleInteger + ")|(" +
479 positiveInteger + ")|(" +
480 negativeInteger + ")";
481 }
482 private Pattern integerPattern() {
483 if (integerPattern == null) {
484 integerPattern = patternCache.forName(buildIntegerPatternString());
485 }
486 return integerPattern;
487 }
488
489 /**
490 * Fields and an accessor method to match line separators
491 */
492 private static volatile Pattern separatorPattern;
493 private static volatile Pattern linePattern;
494 private static final String LINE_SEPARATOR_PATTERN =
495 "\r\n|[\n\r\u2028\u2029\u0085]";
496 private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$";
497
498 private static Pattern separatorPattern() {
499 Pattern sp = separatorPattern;
500 if (sp == null)
501 separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
502 return sp;
503 }
504
505 private static Pattern linePattern() {
506 Pattern lp = linePattern;
507 if (lp == null)
508 linePattern = lp = Pattern.compile(LINE_PATTERN);
509 return lp;
510 }
511
512 /**
513 * Fields and methods to match floats and doubles
514 */
515 private Pattern floatPattern;
516 private Pattern decimalPattern;
517 private void buildFloatAndDecimalPattern() {
518 // \\p{javaDigit} may not be perfect, see above
519 String digit = "([0-9]|(\\p{javaDigit}))";
520 String exponent = "([eE][+-]?"+digit+"+)?";
521 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
522 groupSeparator+digit+digit+digit+")+)";
523 // Once again digit++ is used for performance, as above
524 String numeral = "(("+digit+"++)|"+groupedNumeral+")";
525 String decimalNumeral = "("+numeral+"|"+numeral +
526 decimalSeparator + digit + "*+|"+ decimalSeparator +
527 digit + "++)";
528 String nonNumber = "(NaN|"+nanString+"|Infinity|"+
529 infinityString+")";
530 String positiveFloat = "(" + positivePrefix + decimalNumeral +
531 positiveSuffix + exponent + ")";
532 String negativeFloat = "(" + negativePrefix + decimalNumeral +
533 negativeSuffix + exponent + ")";
534 String decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+
535 positiveFloat + "|" + negativeFloat + ")";
536 String hexFloat =
537 "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?";
538 String positiveNonNumber = "(" + positivePrefix + nonNumber +
539 positiveSuffix + ")";
540 String negativeNonNumber = "(" + negativePrefix + nonNumber +
541 negativeSuffix + ")";
542 String signedNonNumber = "(([-+]?"+nonNumber+")|" +
543 positiveNonNumber + "|" +
544 negativeNonNumber + ")";
545 floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" +
546 signedNonNumber);
547 decimalPattern = Pattern.compile(decimal);
548 }
549 private Pattern floatPattern() {
550 if (floatPattern == null) {
551 buildFloatAndDecimalPattern();
552 }
553 return floatPattern;
554 }
555 private Pattern decimalPattern() {
556 if (decimalPattern == null) {
557 buildFloatAndDecimalPattern();
558 }
559 return decimalPattern;
560 }
561
562 // Constructors
563
564 /**
565 * Constructs a <code>Scanner</code> that returns values scanned
566 * from the specified source delimited by the specified pattern.
567 *
568 * @param source A character source implementing the Readable interface
569 * @param pattern A delimiting pattern
570 * @return A scanner with the specified source and pattern
571 */
572 private Scanner(Readable source, Pattern pattern) {
573 if (source == null)
574 throw new NullPointerException("source");
575 if (pattern == null)
576 throw new NullPointerException("pattern");
577 this.source = source;
578 delimPattern = pattern;
579 buf = CharBuffer.allocate(BUFFER_SIZE);
580 buf.limit(0);
581 matcher = delimPattern.matcher(buf);
582 matcher.useTransparentBounds(true);
583 matcher.useAnchoringBounds(false);
584 useLocale(Locale.getDefault());
585 }
586
587 /**
588 * Constructs a new <code>Scanner</code> that produces values scanned
589 * from the specified source.
590 *
591 * @param source A character source implementing the {@link Readable}
592 * interface
593 */
594 public Scanner(Readable source) {
595 this(source, WHITESPACE_PATTERN);
596 }
597
598 /**
599 * Constructs a new <code>Scanner</code> that produces values scanned
600 * from the specified input stream. Bytes from the stream are converted
601 * into characters using the underlying platform's
602 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
603 *
604 * @param source An input stream to be scanned
605 */
606 public Scanner(InputStream source) {
607 this(new InputStreamReader(source), WHITESPACE_PATTERN);
608 }
609
610 /**
611 * Constructs a new <code>Scanner</code> that produces values scanned
612 * from the specified input stream. Bytes from the stream are converted
613 * into characters using the specified charset.
614 *
615 * @param source An input stream to be scanned
616 * @param charsetName The encoding type used to convert bytes from the
617 * stream into characters to be scanned
618 * @throws IllegalArgumentException if the specified character set
619 * does not exist
620 */
621 public Scanner(InputStream source, String charsetName) {
622 this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
623 }
624
625 private static Readable makeReadable(InputStream source,
626 String charsetName)
627 {
628 if (source == null)
629 throw new NullPointerException("source");
630 InputStreamReader isr = null;
631 try {
632 isr = new InputStreamReader(source, charsetName);
633 } catch (UnsupportedEncodingException uee) {
634 IllegalArgumentException iae = new IllegalArgumentException();
635 iae.initCause(uee);
636 throw iae;
637 }
638 return isr;
639 }
640
641 /**
642 * Constructs a new <code>Scanner</code> that produces values scanned
643 * from the specified file. Bytes from the file are converted into
644 * characters using the underlying platform's
645 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
646 *
647 * @param source A file to be scanned
648 * @throws FileNotFoundException if source is not found
649 */
650 public Scanner(File source)
651 throws FileNotFoundException
652 {
653 this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
654 }
655
656 /**
657 * Constructs a new <code>Scanner</code> that produces values scanned
658 * from the specified file. Bytes from the file are converted into
659 * characters using the specified charset.
660 *
661 * @param source A file to be scanned
662 * @param charsetName The encoding type used to convert bytes from the file
663 * into characters to be scanned
664 * @throws FileNotFoundException if source is not found
665 * @throws IllegalArgumentException if the specified encoding is
666 * not found
667 */
668 public Scanner(File source, String charsetName)
669 throws FileNotFoundException
670 {
671 this((ReadableByteChannel)(new FileInputStream(source).getChannel()),
672 charsetName);
673 }
674
675 /**
676 * Constructs a new <code>Scanner</code> that produces values scanned
677 * from the specified string.
678 *
679 * @param source A string to scan
680 */
681 public Scanner(String source) {
682 this(new StringReader(source), WHITESPACE_PATTERN);
683 }
684
685 /**
686 * Constructs a new <code>Scanner</code> that produces values scanned
687 * from the specified channel. Bytes from the source are converted into
688 * characters using the underlying platform's
689 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
690 *
691 * @param source A channel to scan
692 */
693 public Scanner(ReadableByteChannel source) {
694 this(makeReadable(source), WHITESPACE_PATTERN);
695 }
696
697 private static Readable makeReadable(ReadableByteChannel source) {
698 if (source == null)
699 throw new NullPointerException("source");
700 String defaultCharsetName =
701 java.nio.charset.Charset.defaultCharset().name();
702 return Channels.newReader(source,
703 java.nio.charset.Charset.defaultCharset().name());
704 }
705
706 /**
707 * Constructs a new <code>Scanner</code> that produces values scanned
708 * from the specified channel. Bytes from the source are converted into
709 * characters using the specified charset.
710 *
711 * @param source A channel to scan
712 * @param charsetName The encoding type used to convert bytes from the
713 * channel into characters to be scanned
714 * @throws IllegalArgumentException if the specified character set
715 * does not exist
716 */
717 public Scanner(ReadableByteChannel source, String charsetName) {
718 this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
719 }
720
721 private static Readable makeReadable(ReadableByteChannel source,
722 String charsetName)
723 {
724 if (source == null)
725 throw new NullPointerException("source");
726 if (!Charset.isSupported(charsetName))
727 throw new IllegalArgumentException(charsetName);
728 return Channels.newReader(source, charsetName);
729 }
730
731 // Private primitives used to support scanning
732
733 private void saveState() {
734 savedScannerPosition = position;
735 }
736
737 private void revertState() {
738 this.position = savedScannerPosition;
739 savedScannerPosition = -1;
740 skipped = false;
741 }
742
743 private boolean revertState(boolean b) {
744 this.position = savedScannerPosition;
745 savedScannerPosition = -1;
746 skipped = false;
747 return b;
748 }
749
750 private void cacheResult() {
751 hasNextResult = matcher.group();
752 hasNextPosition = matcher.end();
753 hasNextPattern = matcher.pattern();
754 }
755
756 private void cacheResult(String result) {
757 hasNextResult = result;
758 hasNextPosition = matcher.end();
759 hasNextPattern = matcher.pattern();
760 }
761
762 // Clears both regular cache and type cache
763 private void clearCaches() {
764 hasNextPattern = null;
765 typeCache = null;
766 }
767
768 // Also clears both the regular cache and the type cache
769 private String getCachedResult() {
770 position = hasNextPosition;
771 hasNextPattern = null;
772 typeCache = null;
773 return hasNextResult;
774 }
775
776 // Also clears both the regular cache and the type cache
777 private void useTypeCache() {
778 if (closed)
779 throw new IllegalStateException("Scanner closed");
780 position = hasNextPosition;
781 hasNextPattern = null;
782 typeCache = null;
783 }
784
785 // Tries to read more input. May block.
786 private void readInput() {
787 if (buf.limit() == buf.capacity())
788 makeSpace();
789
790 // Prepare to receive data
791 int p = buf.position();
792 buf.position(buf.limit());
793 buf.limit(buf.capacity());
794
795 int n = 0;
796 try {
797 n = source.read(buf);
798 } catch (IOException ioe) {
799 lastException = ioe;
800 n = -1;
801 }
802
803 if (n == -1) {
804 sourceClosed = true;
805 needInput = false;
806 }
807
808 if (n > 0)
809 needInput = false;
810
811 // Restore current position and limit for reading
812 buf.limit(buf.position());
813 buf.position(p);
814 }
815
816 // After this method is called there will either be an exception
817 // or else there will be space in the buffer
818 private boolean makeSpace() {
819 clearCaches();
820 int offset = savedScannerPosition == -1 ?
821 position : savedScannerPosition;
822 buf.position(offset);
823 // Gain space by compacting buffer
824 if (offset > 0) {
825 buf.compact();
826 translateSavedIndexes(offset);
827 position -= offset;
828 buf.flip();
829 return true;
830 }
831 // Gain space by growing buffer
832 int newSize = buf.capacity() * 2;
833 CharBuffer newBuf = CharBuffer.allocate(newSize);
834 newBuf.put(buf);
835 newBuf.flip();
836 translateSavedIndexes(offset);
837 position -= offset;
838 buf = newBuf;
839 matcher.reset(buf);
840 return true;
841 }
842
843 // When a buffer compaction/reallocation occurs the saved indexes must
844 // be modified appropriately
845 private void translateSavedIndexes(int offset) {
846 if (savedScannerPosition != -1)
847 savedScannerPosition -= offset;
848 }
849
850 // If we are at the end of input then NoSuchElement;
851 // If there is still input left then InputMismatch
852 private void throwFor() {
853 skipped = false;
854 if ((sourceClosed) && (position == buf.limit()))
855 throw new NoSuchElementException();
856 else
857 throw new InputMismatchException();
858 }
859
860 // Returns true if a complete token or partial token is in the buffer.
861 // It is not necessary to find a complete token since a partial token
862 // means that there will be another token with or without more input.
863 private boolean hasTokenInBuffer() {
864 matchValid = false;
865 matcher.usePattern(delimPattern);
866 matcher.region(position, buf.limit());
867
868 // Skip delims first
869 if (matcher.lookingAt())
870 position = matcher.end();
871
872 // If we are sitting at the end, no more tokens in buffer
873 if (position == buf.limit())
874 return false;
875
876 return true;
877 }
878
879 /*
880 * Returns a "complete token" that matches the specified pattern
881 *
882 * A token is complete if surrounded by delims; a partial token
883 * is prefixed by delims but not postfixed by them
884 *
885 * The position is advanced to the end of that complete token
886 *
887 * Pattern == null means accept any token at all
888 *
889 * Triple return:
890 * 1. valid string means it was found
891 * 2. null with needInput=false means we won't ever find it
892 * 3. null with needInput=true means try again after readInput
893 */
894 private String getCompleteTokenInBuffer(Pattern pattern) {
895 matchValid = false;
896
897 // Skip delims first
898 matcher.usePattern(delimPattern);
899 if (!skipped) { // Enforcing only one skip of leading delims
900 matcher.region(position, buf.limit());
901 if (matcher.lookingAt()) {
902 // If more input could extend the delimiters then we must wait
903 // for more input
904 if (matcher.hitEnd() && !sourceClosed) {
905 needInput = true;
906 return null;
907 }
908 // The delims were whole and the matcher should skip them
909 skipped = true;
910 position = matcher.end();
911 }
912 }
913
914 // If we are sitting at the end, no more tokens in buffer
915 if (position == buf.limit()) {
916 if (sourceClosed)
917 return null;
918 needInput = true;
919 return null;
920 }
921
922 // Must look for next delims. Simply attempting to match the
923 // pattern at this point may find a match but it might not be
924 // the first longest match because of missing input, or it might
925 // match a partial token instead of the whole thing.
926
927 // Then look for next delims
928 matcher.region(position, buf.limit());
929 boolean foundNextDelim = matcher.find();
930 if (foundNextDelim && (matcher.end() == position)) {
931 // Zero length delimiter match; we should find the next one
932 // using the automatic advance past a zero length match;
933 // Otherwise we have just found the same one we just skipped
934 foundNextDelim = matcher.find();
935 }
936 if (foundNextDelim) {
937 // In the rare case that more input could cause the match
938 // to be lost and there is more input coming we must wait
939 // for more input. Note that hitting the end is okay as long
940 // as the match cannot go away. It is the beginning of the
941 // next delims we want to be sure about, we don't care if
942 // they potentially extend further.
943 if (matcher.requireEnd() && !sourceClosed) {
944 needInput = true;
945 return null;
946 }
947 int tokenEnd = matcher.start();
948 // There is a complete token.
949 if (pattern == null) {
950 // Must continue with match to provide valid MatchResult
951 pattern = FIND_ANY_PATTERN;
952 }
953 // Attempt to match against the desired pattern
954 matcher.usePattern(pattern);
955 matcher.region(position, tokenEnd);
956 if (matcher.matches()) {
957 String s = matcher.group();
958 position = matcher.end();
959 return s;
960 } else { // Complete token but it does not match
961 return null;
962 }
963 }
964
965 // If we can't find the next delims but no more input is coming,
966 // then we can treat the remainder as a whole token
967 if (sourceClosed) {
968 if (pattern == null) {
969 // Must continue with match to provide valid MatchResult
970 pattern = FIND_ANY_PATTERN;
971 }
972 // Last token; Match the pattern here or throw
973 matcher.usePattern(pattern);
974 matcher.region(position, buf.limit());
975 if (matcher.matches()) {
976 String s = matcher.group();
977 position = matcher.end();
978 return s;
979 }
980 // Last piece does not match
981 return null;
982 }
983
984 // There is a partial token in the buffer; must read more
985 // to complete it
986 needInput = true;
987 return null;
988 }
989
990 // Finds the specified pattern in the buffer up to horizon.
991 // Returns a match for the specified input pattern.
992 private String findPatternInBuffer(Pattern pattern, int horizon) {
993 matchValid = false;
994 matcher.usePattern(pattern);
995 int bufferLimit = buf.limit();
996 int horizonLimit = -1;
997 int searchLimit = bufferLimit;
998 if (horizon > 0) {
999 horizonLimit = position + horizon;
1000 if (horizonLimit < bufferLimit)
1001 searchLimit = horizonLimit;
1002 }
1003 matcher.region(position, searchLimit);
1004 if (matcher.find()) {
1005 if (matcher.hitEnd() && (!sourceClosed)) {
1006 // The match may be longer if didn't hit horizon or real end
1007 if (searchLimit != horizonLimit) {
1008 // Hit an artificial end; try to extend the match
1009 needInput = true;
1010 return null;
1011 }
1012 // The match could go away depending on what is next
1013 if ((searchLimit == horizonLimit) && matcher.requireEnd()) {
1014 // Rare case: we hit the end of input and it happens
1015 // that it is at the horizon and the end of input is
1016 // required for the match.
1017 needInput = true;
1018 return null;
1019 }
1020 }
1021 // Did not hit end, or hit real end, or hit horizon
1022 position = matcher.end();
1023 return matcher.group();
1024 }
1025
1026 if (sourceClosed)
1027 return null;
1028
1029 // If there is no specified horizon, or if we have not searched
1030 // to the specified horizon yet, get more input
1031 if ((horizon == 0) || (searchLimit != horizonLimit))
1032 needInput = true;
1033 return null;
1034 }
1035
1036 // Returns a match for the specified input pattern anchored at
1037 // the current position
1038 private String matchPatternInBuffer(Pattern pattern) {
1039 matchValid = false;
1040 matcher.usePattern(pattern);
1041 matcher.region(position, buf.limit());
1042 if (matcher.lookingAt()) {
1043 if (matcher.hitEnd() && (!sourceClosed)) {
1044 // Get more input and try again
1045 needInput = true;
1046 return null;
1047 }
1048 position = matcher.end();
1049 return matcher.group();
1050 }
1051
1052 if (sourceClosed)
1053 return null;
1054
1055 // Read more to find pattern
1056 needInput = true;
1057 return null;
1058 }
1059
1060 // Throws if the scanner is closed
1061 private void ensureOpen() {
1062 if (closed)
1063 throw new IllegalStateException("Scanner closed");
1064 }
1065
1066 // Public methods
1067
1068 /**
1069 * Closes this scanner.
1070 *
1071 * <p> If this scanner has not yet been closed then if its underlying
1072 * {@linkplain java.lang.Readable readable} also implements the {@link
1073 * java.io.Closeable} interface then the readable's <tt>close</tt> method
1074 * will be invoked. If this scanner is already closed then invoking this
1075 * method will have no effect.
1076 *
1077 * <p>Attempting to perform search operations after a scanner has
1078 * been closed will result in an {@link IllegalStateException}.
1079 *
1080 */
1081 public void close() {
1082 if (closed)
1083 return;
1084 if (source instanceof Closeable) {
1085 try {
1086 ((Closeable)source).close();
1087 } catch (IOException ioe) {
1088 lastException = ioe;
1089 }
1090 }
1091 sourceClosed = true;
1092 source = null;
1093 closed = true;
1094 }
1095
1096 /**
1097 * Returns the <code>IOException</code> last thrown by this
1098 * <code>Scanner</code>'s underlying <code>Readable</code>. This method
1099 * returns <code>null</code> if no such exception exists.
1100 *
1101 * @return the last exception thrown by this scanner's readable
1102 */
1103 public IOException ioException() {
1104 return lastException;
1105 }
1106
1107 /**
1108 * Returns the <code>Pattern</code> this <code>Scanner</code> is currently
1109 * using to match delimiters.
1110 *
1111 * @return this scanner's delimiting pattern.
1112 */
1113 public Pattern delimiter() {
1114 return delimPattern;
1115 }
1116
1117 /**
1118 * Sets this scanner's delimiting pattern to the specified pattern.
1119 *
1120 * @param pattern A delimiting pattern
1121 * @return this scanner
1122 */
1123 public Scanner useDelimiter(Pattern pattern) {
1124 delimPattern = pattern;
1125 return this;
1126 }
1127
1128 /**
1129 * Sets this scanner's delimiting pattern to a pattern constructed from
1130 * the specified <code>String</code>.
1131 *
1132 * <p> An invocation of this method of the form
1133 * <tt>useDelimiter(pattern)</tt> behaves in exactly the same way as the
1134 * invocation <tt>useDelimiter(Pattern.compile(pattern))</tt>.
1135 *
1136 * <p> Invoking the {@link #reset} method will set the scanner's delimiter
1137 * to the <a href= "#default-delimiter">default</a>.
1138 *
1139 * @param pattern A string specifying a delimiting pattern
1140 * @return this scanner
1141 */
1142 public Scanner useDelimiter(String pattern) {
1143 delimPattern = patternCache.forName(pattern);
1144 return this;
1145 }
1146
1147 /**
1148 * Returns this scanner's locale.
1149 *
1150 * <p>A scanner's locale affects many elements of its default
1151 * primitive matching regular expressions; see
1152 * <a href= "#localized-numbers">localized numbers</a> above.
1153 *
1154 * @return this scanner's locale
1155 */
1156 public Locale locale() {
1157 return this.locale;
1158 }
1159
1160 /**
1161 * Sets this scanner's locale to the specified locale.
1162 *
1163 * <p>A scanner's locale affects many elements of its default
1164 * primitive matching regular expressions; see
1165 * <a href= "#localized-numbers">localized numbers</a> above.
1166 *
1167 * <p>Invoking the {@link #reset} method will set the scanner's locale to
1168 * the <a href= "#initial-locale">initial locale</a>.
1169 *
1170 * @param locale A string specifying the locale to use
1171 * @return this scanner
1172 */
1173 public Scanner useLocale(Locale locale) {
1174 if (locale.equals(this.locale))
1175 return this;
1176
1177 this.locale = locale;
1178 DecimalFormat df =
1179 (DecimalFormat)NumberFormat.getNumberInstance(locale);
1180 DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
1181
1182 // These must be literalized to avoid collision with regex
1183 // metacharacters such as dot or parenthesis
1184 groupSeparator = "\\" + dfs.getGroupingSeparator();
1185 decimalSeparator = "\\" + dfs.getDecimalSeparator();
1186
1187 // Quoting the nonzero length locale-specific things
1188 // to avoid potential conflict with metacharacters
1189 nanString = "\\Q" + dfs.getNaN() + "\\E";
1190 infinityString = "\\Q" + dfs.getInfinity() + "\\E";
1191 positivePrefix = df.getPositivePrefix();
1192 if (positivePrefix.length() > 0)
1193 positivePrefix = "\\Q" + positivePrefix + "\\E";
1194 negativePrefix = df.getNegativePrefix();
1195 if (negativePrefix.length() > 0)
1196 negativePrefix = "\\Q" + negativePrefix + "\\E";
1197 positiveSuffix = df.getPositiveSuffix();
1198 if (positiveSuffix.length() > 0)
1199 positiveSuffix = "\\Q" + positiveSuffix + "\\E";
1200 negativeSuffix = df.getNegativeSuffix();
1201 if (negativeSuffix.length() > 0)
1202 negativeSuffix = "\\Q" + negativeSuffix + "\\E";
1203
1204 // Force rebuilding and recompilation of locale dependent
1205 // primitive patterns
1206 integerPattern = null;
1207 floatPattern = null;
1208
1209 return this;
1210 }
1211
1212 /**
1213 * Returns this scanner's default radix.
1214 *
1215 * <p>A scanner's radix affects elements of its default
1216 * number matching regular expressions; see
1217 * <a href= "#localized-numbers">localized numbers</a> above.
1218 *
1219 * @return the default radix of this scanner
1220 */
1221 public int radix() {
1222 return this.defaultRadix;
1223 }
1224
1225 /**
1226 * Sets this scanner's default radix to the specified radix.
1227 *
1228 * <p>A scanner's radix affects elements of its default
1229 * number matching regular expressions; see
1230 * <a href= "#localized-numbers">localized numbers</a> above.
1231 *
1232 * <p>If the radix is less than <code>Character.MIN_RADIX</code>
1233 * or greater than <code>Character.MAX_RADIX</code>, then an
1234 * <code>IllegalArgumentException</code> is thrown.
1235 *
1236 * <p>Invoking the {@link #reset} method will set the scanner's radix to
1237 * <code>10</code>.
1238 *
1239 * @param radix The radix to use when scanning numbers
1240 * @return this scanner
1241 * @throws IllegalArgumentException if radix is out of range
1242 */
1243 public Scanner useRadix(int radix) {
1244 if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
1245 throw new IllegalArgumentException("radix:"+radix);
1246
1247 if (this.defaultRadix == radix)
1248 return this;
1249 this.defaultRadix = radix;
1250 // Force rebuilding and recompilation of radix dependent patterns
1251 integerPattern = null;
1252 return this;
1253 }
1254
1255 // The next operation should occur in the specified radix but
1256 // the default is left untouched.
1257 private void setRadix(int radix) {
1258 if (this.radix != radix) {
1259 // Force rebuilding and recompilation of radix dependent patterns
1260 integerPattern = null;
1261 this.radix = radix;
1262 }
1263 }
1264
1265 /**
1266 * Returns the match result of the last scanning operation performed
1267 * by this scanner. This method throws <code>IllegalStateException</code>
1268 * if no match has been performed, or if the last match was
1269 * not successful.
1270 *
1271 * <p>The various <code>next</code>methods of <code>Scanner</code>
1272 * make a match result available if they complete without throwing an
1273 * exception. For instance, after an invocation of the {@link #nextInt}
1274 * method that returned an int, this method returns a
1275 * <code>MatchResult</code> for the search of the
1276 * <a href="#Integer-regex"><i>Integer</i></a> regular expression
1277 * defined above. Similarly the {@link #findInLine},
1278 * {@link #findWithinHorizon}, and {@link #skip} methods will make a
1279 * match available if they succeed.
1280 *
1281 * @return a match result for the last match operation
1282 * @throws IllegalStateException If no match result is available
1283 */
1284 public MatchResult match() {
1285 if (!matchValid)
1286 throw new IllegalStateException("No match result available");
1287 return matcher.toMatchResult();
1288 }
1289
1290 /**
1291 * <p>Returns the string representation of this <code>Scanner</code>. The
1292 * string representation of a <code>Scanner</code> contains information
1293 * that may be useful for debugging. The exact format is unspecified.
1294 *
1295 * @return The string representation of this scanner
1296 */
1297 public String toString() {
1298 StringBuilder sb = new StringBuilder();
1299 sb.append("java.util.Scanner");
1300 sb.append("[delimiters=" + delimPattern + "]");
1301 sb.append("[position=" + position + "]");
1302 sb.append("[match valid=" + matchValid + "]");
1303 sb.append("[need input=" + needInput + "]");
1304 sb.append("[source closed=" + sourceClosed + "]");
1305 sb.append("[skipped=" + skipped + "]");
1306 sb.append("[group separator=" + groupSeparator + "]");
1307 sb.append("[decimal separator=" + decimalSeparator + "]");
1308 sb.append("[positive prefix=" + positivePrefix + "]");
1309 sb.append("[negative prefix=" + negativePrefix + "]");
1310 sb.append("[positive suffix=" + positiveSuffix + "]");
1311 sb.append("[negative suffix=" + negativeSuffix + "]");
1312 sb.append("[NaN string=" + nanString + "]");
1313 sb.append("[infinity string=" + infinityString + "]");
1314 return sb.toString();
1315 }
1316
1317 /**
1318 * Returns true if this scanner has another token in its input.
1319 * This method may block while waiting for input to scan.
1320 * The scanner does not advance past any input.
1321 *
1322 * @return true if and only if this scanner has another token
1323 * @throws IllegalStateException if this scanner is closed
1324 * @see java.util.Iterator
1325 */
1326 public boolean hasNext() {
1327 ensureOpen();
1328 saveState();
1329 while (!sourceClosed) {
1330 if (hasTokenInBuffer())
1331 return revertState(true);
1332 readInput();
1333 }
1334 boolean result = hasTokenInBuffer();
1335 return revertState(result);
1336 }
1337
1338 /**
1339 * Finds and returns the next complete token from this scanner.
1340 * A complete token is preceded and followed by input that matches
1341 * the delimiter pattern. This method may block while waiting for input
1342 * to scan, even if a previous invocation of {@link #hasNext} returned
1343 * <code>true</code>.
1344 *
1345 * @return the next token
1346 * @throws NoSuchElementException if no more tokens are available
1347 * @throws IllegalStateException if this scanner is closed
1348 * @see java.util.Iterator
1349 */
1350 public String next() {
1351 ensureOpen();
1352 clearCaches();
1353
1354 while (true) {
1355 String token = getCompleteTokenInBuffer(null);
1356 if (token != null) {
1357 matchValid = true;
1358 skipped = false;
1359 return token;
1360 }
1361 if (needInput)
1362 readInput();
1363 else
1364 throwFor();
1365 }
1366 }
1367
1368 /**
1369 * The remove operation is not supported by this implementation of
1370 * <code>Iterator</code>.
1371 *
1372 * @throws UnsupportedOperationException if this method is invoked.
1373 * @see java.util.Iterator
1374 */
1375 public void remove() {
1376 throw new UnsupportedOperationException();
1377 }
1378
1379 /**
1380 * Returns true if the next token matches the pattern constructed from the
1381 * specified string. The scanner does not advance past any input.
1382 *
1383 * <p> An invocation of this method of the form <tt>hasNext(pattern)</tt>
1384 * behaves in exactly the same way as the invocation
1385 * <tt>hasNext(Pattern.compile(pattern))</tt>.
1386 *
1387 * @param pattern a string specifying the pattern to scan
1388 * @return true if and only if this scanner has another token matching
1389 * the specified pattern
1390 * @throws IllegalStateException if this scanner is closed
1391 */
1392 public boolean hasNext(String pattern) {
1393 return hasNext(patternCache.forName(pattern));
1394 }
1395
1396 /**
1397 * Returns the next token if it matches the pattern constructed from the
1398 * specified string. If the match is successful, the scanner advances
1399 * past the input that matched the pattern.
1400 *
1401 * <p> An invocation of this method of the form <tt>next(pattern)</tt>
1402 * behaves in exactly the same way as the invocation
1403 * <tt>next(Pattern.compile(pattern))</tt>.
1404 *
1405 * @param pattern a string specifying the pattern to scan
1406 * @return the next token
1407 * @throws NoSuchElementException if no such tokens are available
1408 * @throws IllegalStateException if this scanner is closed
1409 */
1410 public String next(String pattern) {
1411 return next(patternCache.forName(pattern));
1412 }
1413
1414 /**
1415 * Returns true if the next complete token matches the specified pattern.
1416 * A complete token is prefixed and postfixed by input that matches
1417 * the delimiter pattern. This method may block while waiting for input.
1418 * The scanner does not advance past any input.
1419 *
1420 * @param pattern the pattern to scan for
1421 * @return true if and only if this scanner has another token matching
1422 * the specified pattern
1423 * @throws IllegalStateException if this scanner is closed
1424 */
1425 public boolean hasNext(Pattern pattern) {
1426 ensureOpen();
1427 if (pattern == null)
1428 throw new NullPointerException();
1429 hasNextPattern = null;
1430 saveState();
1431
1432 while (true) {
1433 if (getCompleteTokenInBuffer(pattern) != null) {
1434 matchValid = true;
1435 cacheResult();
1436 return revertState(true);
1437 }
1438 if (needInput)
1439 readInput();
1440 else
1441 return revertState(false);
1442 }
1443 }
1444
1445 /**
1446 * Returns the next token if it matches the specified pattern. This
1447 * method may block while waiting for input to scan, even if a previous
1448 * invocation of {@link #hasNext(Pattern)} returned <code>true</code>.
1449 * If the match is successful, the scanner advances past the input that
1450 * matched the pattern.
1451 *
1452 * @param pattern the pattern to scan for
1453 * @return the next token
1454 * @throws NoSuchElementException if no more tokens are available
1455 * @throws IllegalStateException if this scanner is closed
1456 */
1457 public String next(Pattern pattern) {
1458 ensureOpen();
1459 if (pattern == null)
1460 throw new NullPointerException();
1461
1462 // Did we already find this pattern?
1463 if (hasNextPattern == pattern)
1464 return getCachedResult();
1465 clearCaches();
1466
1467 // Search for the pattern
1468 while (true) {
1469 String token = getCompleteTokenInBuffer(pattern);
1470 if (token != null) {
1471 matchValid = true;
1472 skipped = false;
1473 return token;
1474 }
1475 if (needInput)
1476 readInput();
1477 else
1478 throwFor();
1479 }
1480 }
1481
1482 /**
1483 * Returns true if there is another line in the input of this scanner.
1484 * This method may block while waiting for input. The scanner does not
1485 * advance past any input.
1486 *
1487 * @return true if and only if this scanner has another line of input
1488 * @throws IllegalStateException if this scanner is closed
1489 */
1490 public boolean hasNextLine() {
1491 saveState();
1492
1493 String result = findWithinHorizon(linePattern(), 0);
1494 if (result != null) {
1495 MatchResult mr = this.match();
1496 String lineSep = mr.group(1);
1497 if (lineSep != null) {
1498 result = result.substring(0, result.length() -
1499 lineSep.length());
1500 cacheResult(result);
1501
1502 } else {
1503 cacheResult();
1504 }
1505 }
1506 revertState();
1507 return (result != null);
1508 }
1509
1510 /**
1511 * Advances this scanner past the current line and returns the input
1512 * that was skipped.
1513 *
1514 * This method returns the rest of the current line, excluding any line
1515 * separator at the end. The position is set to the beginning of the next
1516 * line.
1517 *
1518 * <p>Since this method continues to search through the input looking
1519 * for a line separator, it may buffer all of the input searching for
1520 * the line to skip if no line separators are present.
1521 *
1522 * @return the line that was skipped
1523 * @throws NoSuchElementException if no line was found
1524 * @throws IllegalStateException if this scanner is closed
1525 */
1526 public String nextLine() {
1527 if (hasNextPattern == linePattern())
1528 return getCachedResult();
1529 clearCaches();
1530
1531 String result = findWithinHorizon(linePattern, 0);
1532 if (result == null)
1533 throw new NoSuchElementException("No line found");
1534 MatchResult mr = this.match();
1535 String lineSep = mr.group(1);
1536 if (lineSep != null)
1537 result = result.substring(0, result.length() - lineSep.length());
1538 if (result == null)
1539 throw new NoSuchElementException();
1540 else
1541 return result;
1542 }
1543
1544 // Public methods that ignore delimiters
1545
1546 /**
1547 * Attempts to find the next occurrence of a pattern constructed from the
1548 * specified string, ignoring delimiters.
1549 *
1550 * <p>An invocation of this method of the form <tt>findInLine(pattern)</tt>
1551 * behaves in exactly the same way as the invocation
1552 * <tt>findInLine(Pattern.compile(pattern))</tt>.
1553 *
1554 * @param pattern a string specifying the pattern to search for
1555 * @return the text that matched the specified pattern
1556 * @throws IllegalStateException if this scanner is closed
1557 */
1558 public String findInLine(String pattern) {
1559 return findInLine(patternCache.forName(pattern));
1560 }
1561
1562 /**
1563 * Attempts to find the next occurrence of the specified pattern ignoring
1564 * delimiters. If the pattern is found before the next line separator, the
1565 * scanner advances past the input that matched and returns the string that
1566 * matched the pattern.
1567 * If no such pattern is detected in the input up to the next line
1568 * separator, then <code>null</code> is returned and the scanner's
1569 * position is unchanged. This method may block waiting for input that
1570 * matches the pattern.
1571 *
1572 * <p>Since this method continues to search through the input looking
1573 * for the specified pattern, it may buffer all of the input searching for
1574 * the desired token if no line separators are present.
1575 *
1576 * @param pattern the pattern to scan for
1577 * @return the text that matched the specified pattern
1578 * @throws IllegalStateException if this scanner is closed
1579 */
1580 public String findInLine(Pattern pattern) {
1581 ensureOpen();
1582 if (pattern == null)
1583 throw new NullPointerException();
1584 clearCaches();
1585 // Expand buffer to include the next newline or end of input
1586 int endPosition = 0;
1587 saveState();
1588 while (true) {
1589 String token = findPatternInBuffer(separatorPattern(), 0);
1590 if (token != null) {
1591 endPosition = matcher.start();
1592 break; // up to next newline
1593 }
1594 if (needInput) {
1595 readInput();
1596 } else {
1597 endPosition = buf.limit();
1598 break; // up to end of input
1599 }
1600 }
1601 revertState();
1602 int horizonForLine = endPosition - position;
1603 // If there is nothing between the current pos and the next
1604 // newline simply return null, invoking findWithinHorizon
1605 // with "horizon=0" will scan beyond the line bound.
1606 if (horizonForLine == 0)
1607 return null;
1608 // Search for the pattern
1609 return findWithinHorizon(pattern, horizonForLine);
1610 }
1611
1612 /**
1613 * Attempts to find the next occurrence of a pattern constructed from the
1614 * specified string, ignoring delimiters.
1615 *
1616 * <p>An invocation of this method of the form
1617 * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as
1618 * the invocation
1619 * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>.
1620 *
1621 * @param pattern a string specifying the pattern to search for
1622 * @return the text that matched the specified pattern
1623 * @throws IllegalStateException if this scanner is closed
1624 * @throws IllegalArgumentException if horizon is negative
1625 */
1626 public String findWithinHorizon(String pattern, int horizon) {
1627 return findWithinHorizon(patternCache.forName(pattern), horizon);
1628 }
1629
1630 /**
1631 * Attempts to find the next occurrence of the specified pattern.
1632 *
1633 * <p>This method searches through the input up to the specified
1634 * search horizon, ignoring delimiters. If the pattern is found the
1635 * scanner advances past the input that matched and returns the string
1636 * that matched the pattern. If no such pattern is detected then the
1637 * null is returned and the scanner's position remains unchanged. This
1638 * method may block waiting for input that matches the pattern.
1639 *
1640 * <p>A scanner will never search more than <code>horizon</code> code
1641 * points beyond its current position. Note that a match may be clipped
1642 * by the horizon; that is, an arbitrary match result may have been
1643 * different if the horizon had been larger. The scanner treats the
1644 * horizon as a transparent, non-anchoring bound (see {@link
1645 * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}).
1646 *
1647 * <p>If horizon is <code>0</code>, then the horizon is ignored and
1648 * this method continues to search through the input looking for the
1649 * specified pattern without bound. In this case it may buffer all of
1650 * the input searching for the pattern.
1651 *
1652 * <p>If horizon is negative, then an IllegalArgumentException is
1653 * thrown.
1654 *
1655 * @param pattern the pattern to scan for
1656 * @return the text that matched the specified pattern
1657 * @throws IllegalStateException if this scanner is closed
1658 * @throws IllegalArgumentException if horizon is negative
1659 */
1660 public String findWithinHorizon(Pattern pattern, int horizon) {
1661 ensureOpen();
1662 if (pattern == null)
1663 throw new NullPointerException();
1664 if (horizon < 0)
1665 throw new IllegalArgumentException("horizon < 0");
1666 clearCaches();
1667
1668 // Search for the pattern
1669 while (true) {
1670 String token = findPatternInBuffer(pattern, horizon);
1671 if (token != null) {
1672 matchValid = true;
1673 return token;
1674 }
1675 if (needInput)
1676 readInput();
1677 else
1678 break; // up to end of input
1679 }
1680 return null;
1681 }
1682
1683 /**
1684 * Skips input that matches the specified pattern, ignoring delimiters.
1685 * This method will skip input if an anchored match of the specified
1686 * pattern succeeds.
1687 *
1688 * <p>If a match to the specified pattern is not found at the
1689 * current position, then no input is skipped and a
1690 * <tt>NoSuchElementException</tt> is thrown.
1691 *
1692 * <p>Since this method seeks to match the specified pattern starting at
1693 * the scanner's current position, patterns that can match a lot of
1694 * input (".*", for example) may cause the scanner to buffer a large
1695 * amount of input.
1696 *
1697 * <p>Note that it is possible to skip something without risking a
1698 * <code>NoSuchElementException</code> by using a pattern that can
1699 * match nothing, e.g., <code>sc.skip("[ \t]*")</code>.
1700 *
1701 * @param pattern a string specifying the pattern to skip over
1702 * @return this scanner
1703 * @throws NoSuchElementException if the specified pattern is not found
1704 * @throws IllegalStateException if this scanner is closed
1705 */
1706 public Scanner skip(Pattern pattern) {
1707 ensureOpen();
1708 if (pattern == null)
1709 throw new NullPointerException();
1710 clearCaches();
1711
1712 // Search for the pattern
1713 while (true) {
1714 String token = matchPatternInBuffer(pattern);
1715 if (token != null) {
1716 matchValid = true;
1717 position = matcher.end();
1718 return this;
1719 }
1720 if (needInput)
1721 readInput();
1722 else
1723 throw new NoSuchElementException();
1724 }
1725 }
1726
1727 /**
1728 * Skips input that matches a pattern constructed from the specified
1729 * string.
1730 *
1731 * <p> An invocation of this method of the form <tt>skip(pattern)</tt>
1732 * behaves in exactly the same way as the invocation
1733 * <tt>skip(Pattern.compile(pattern))</tt>.
1734 *
1735 * @param pattern a string specifying the pattern to skip over
1736 * @return this scanner
1737 * @throws IllegalStateException if this scanner is closed
1738 */
1739 public Scanner skip(String pattern) {
1740 return skip(patternCache.forName(pattern));
1741 }
1742
1743 // Convenience methods for scanning primitives
1744
1745 /**
1746 * Returns true if the next token in this scanner's input can be
1747 * interpreted as a boolean value using a case insensitive pattern
1748 * created from the string "true|false". The scanner does not
1749 * advance past the input that matched.
1750 *
1751 * @return true if and only if this scanner's next token is a valid
1752 * boolean value
1753 * @throws IllegalStateException if this scanner is closed
1754 */
1755 public boolean hasNextBoolean() {
1756 return hasNext(boolPattern());
1757 }
1758
1759 /**
1760 * Scans the next token of the input into a boolean value and returns
1761 * that value. This method will throw <code>InputMismatchException</code>
1762 * if the next token cannot be translated into a valid boolean value.
1763 * If the match is successful, the scanner advances past the input that
1764 * matched.
1765 *
1766 * @return the boolean scanned from the input
1767 * @throws InputMismatchException if the next token is not a valid boolean
1768 * @throws NoSuchElementException if input is exhausted
1769 * @throws IllegalStateException if this scanner is closed
1770 */
1771 public boolean nextBoolean() {
1772 clearCaches();
1773 return Boolean.parseBoolean(next(boolPattern()));
1774 }
1775
1776 /**
1777 * Returns true if the next token in this scanner's input can be
1778 * interpreted as a byte value in the default radix using the
1779 * {@link #nextByte} method. The scanner does not advance past any input.
1780 *
1781 * @return true if and only if this scanner's next token is a valid
1782 * byte value
1783 * @throws IllegalStateException if this scanner is closed
1784 */
1785 public boolean hasNextByte() {
1786 return hasNextByte(defaultRadix);
1787 }
1788
1789 /**
1790 * Returns true if the next token in this scanner's input can be
1791 * interpreted as a byte value in the specified radix using the
1792 * {@link #nextByte} method. The scanner does not advance past any input.
1793 *
1794 * @param radix the radix used to interpret the token as a byte value
1795 * @return true if and only if this scanner's next token is a valid
1796 * byte value
1797 * @throws IllegalStateException if this scanner is closed
1798 */
1799 public boolean hasNextByte(int radix) {
1800 setRadix(radix);
1801 boolean result = hasNext(integerPattern());
1802 if (result) { // Cache it
1803 try {
1804 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1805 processIntegerToken(hasNextResult) :
1806 hasNextResult;
1807 typeCache = Byte.parseByte(s, radix);
1808 } catch (NumberFormatException nfe) {
1809 result = false;
1810 }
1811 }
1812 return result;
1813 }
1814
1815 /**
1816 * Scans the next token of the input as a <tt>byte</tt>.
1817 *
1818 * <p> An invocation of this method of the form
1819 * <tt>nextByte()</tt> behaves in exactly the same way as the
1820 * invocation <tt>nextByte(radix)</tt>, where <code>radix</code>
1821 * is the default radix of this scanner.
1822 *
1823 * @return the <tt>byte</tt> scanned from the input
1824 * @throws InputMismatchException
1825 * if the next token does not match the <i>Integer</i>
1826 * regular expression, or is out of range
1827 * @throws NoSuchElementException if input is exhausted
1828 * @throws IllegalStateException if this scanner is closed
1829 */
1830 public byte nextByte() {
1831 return nextByte(defaultRadix);
1832 }
1833
1834 /**
1835 * Scans the next token of the input as a <tt>byte</tt>.
1836 * This method will throw <code>InputMismatchException</code>
1837 * if the next token cannot be translated into a valid byte value as
1838 * described below. If the translation is successful, the scanner advances
1839 * past the input that matched.
1840 *
1841 * <p> If the next token matches the <a
1842 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
1843 * above then the token is converted into a <tt>byte</tt> value as if by
1844 * removing all locale specific prefixes, group separators, and locale
1845 * specific suffixes, then mapping non-ASCII digits into ASCII
1846 * digits via {@link Character#digit Character.digit}, prepending a
1847 * negative sign (-) if the locale specific negative prefixes and suffixes
1848 * were present, and passing the resulting string to
1849 * {@link Byte#parseByte(String, int) Byte.parseByte} with the
1850 * specified radix.
1851 *
1852 * @param radix the radix used to interpret the token as a byte value
1853 * @return the <tt>byte</tt> scanned from the input
1854 * @throws InputMismatchException
1855 * if the next token does not match the <i>Integer</i>
1856 * regular expression, or is out of range
1857 * @throws NoSuchElementException if input is exhausted
1858 * @throws IllegalStateException if this scanner is closed
1859 */
1860 public byte nextByte(int radix) {
1861 // Check cached result
1862 if ((typeCache != null) && (typeCache instanceof Byte)
1863 && this.radix == radix) {
1864 byte val = ((Byte)typeCache).byteValue();
1865 useTypeCache();
1866 return val;
1867 }
1868 setRadix(radix);
1869 clearCaches();
1870 // Search for next byte
1871 try {
1872 String s = next(integerPattern());
1873 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
1874 s = processIntegerToken(s);
1875 return Byte.parseByte(s, radix);
1876 } catch (NumberFormatException nfe) {
1877 position = matcher.start(); // don't skip bad token
1878 throw new InputMismatchException(nfe.getMessage());
1879 }
1880 }
1881
1882 /**
1883 * Returns true if the next token in this scanner's input can be
1884 * interpreted as a short value in the default radix using the
1885 * {@link #nextShort} method. The scanner does not advance past any input.
1886 *
1887 * @return true if and only if this scanner's next token is a valid
1888 * short value in the default radix
1889 * @throws IllegalStateException if this scanner is closed
1890 */
1891 public boolean hasNextShort() {
1892 return hasNextShort(defaultRadix);
1893 }
1894
1895 /**
1896 * Returns true if the next token in this scanner's input can be
1897 * interpreted as a short value in the specified radix using the
1898 * {@link #nextShort} method. The scanner does not advance past any input.
1899 *
1900 * @param radix the radix used to interpret the token as a short value
1901 * @return true if and only if this scanner's next token is a valid
1902 * short value in the specified radix
1903 * @throws IllegalStateException if this scanner is closed
1904 */
1905 public boolean hasNextShort(int radix) {
1906 setRadix(radix);
1907 boolean result = hasNext(integerPattern());
1908 if (result) { // Cache it
1909 try {
1910 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1911 processIntegerToken(hasNextResult) :
1912 hasNextResult;
1913 typeCache = Short.parseShort(s, radix);
1914 } catch (NumberFormatException nfe) {
1915 result = false;
1916 }
1917 }
1918 return result;
1919 }
1920
1921 /**
1922 * Scans the next token of the input as a <tt>short</tt>.
1923 *
1924 * <p> An invocation of this method of the form
1925 * <tt>nextShort()</tt> behaves in exactly the same way as the
1926 * invocation <tt>nextShort(radix)</tt>, where <code>radix</code>
1927 * is the default radix of this scanner.
1928 *
1929 * @return the <tt>short</tt> scanned from the input
1930 * @throws InputMismatchException
1931 * if the next token does not match the <i>Integer</i>
1932 * regular expression, or is out of range
1933 * @throws NoSuchElementException if input is exhausted
1934 * @throws IllegalStateException if this scanner is closed
1935 */
1936 public short nextShort() {
1937 return nextShort(defaultRadix);
1938 }
1939
1940 /**
1941 * Scans the next token of the input as a <tt>short</tt>.
1942 * This method will throw <code>InputMismatchException</code>
1943 * if the next token cannot be translated into a valid short value as
1944 * described below. If the translation is successful, the scanner advances
1945 * past the input that matched.
1946 *
1947 * <p> If the next token matches the <a
1948 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
1949 * above then the token is converted into a <tt>short</tt> value as if by
1950 * removing all locale specific prefixes, group separators, and locale
1951 * specific suffixes, then mapping non-ASCII digits into ASCII
1952 * digits via {@link Character#digit Character.digit}, prepending a
1953 * negative sign (-) if the locale specific negative prefixes and suffixes
1954 * were present, and passing the resulting string to
1955 * {@link Short#parseShort(String, int) Short.parseShort} with the
1956 * specified radix.
1957 *
1958 * @param radix the radix used to interpret the token as a short value
1959 * @return the <tt>short</tt> scanned from the input
1960 * @throws InputMismatchException
1961 * if the next token does not match the <i>Integer</i>
1962 * regular expression, or is out of range
1963 * @throws NoSuchElementException if input is exhausted
1964 * @throws IllegalStateException if this scanner is closed
1965 */
1966 public short nextShort(int radix) {
1967 // Check cached result
1968 if ((typeCache != null) && (typeCache instanceof Short)
1969 && this.radix == radix) {
1970 short val = ((Short)typeCache).shortValue();
1971 useTypeCache();
1972 return val;
1973 }
1974 setRadix(radix);
1975 clearCaches();
1976 // Search for next short
1977 try {
1978 String s = next(integerPattern());
1979 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
1980 s = processIntegerToken(s);
1981 return Short.parseShort(s, radix);
1982 } catch (NumberFormatException nfe) {
1983 position = matcher.start(); // don't skip bad token
1984 throw new InputMismatchException(nfe.getMessage());
1985 }
1986 }
1987
1988 /**
1989 * Returns true if the next token in this scanner's input can be
1990 * interpreted as an int value in the default radix using the
1991 * {@link #nextInt} method. The scanner does not advance past any input.
1992 *
1993 * @return true if and only if this scanner's next token is a valid
1994 * int value
1995 * @throws IllegalStateException if this scanner is closed
1996 */
1997 public boolean hasNextInt() {
1998 return hasNextInt(defaultRadix);
1999 }
2000
2001 /**
2002 * Returns true if the next token in this scanner's input can be
2003 * interpreted as an int value in the specified radix using the
2004 * {@link #nextInt} method. The scanner does not advance past any input.
2005 *
2006 * @param radix the radix used to interpret the token as an int value
2007 * @return true if and only if this scanner's next token is a valid
2008 * int value
2009 * @throws IllegalStateException if this scanner is closed
2010 */
2011 public boolean hasNextInt(int radix) {
2012 setRadix(radix);
2013 boolean result = hasNext(integerPattern());
2014 if (result) { // Cache it
2015 try {
2016 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2017 processIntegerToken(hasNextResult) :
2018 hasNextResult;
2019 typeCache = Integer.parseInt(s, radix);
2020 } catch (NumberFormatException nfe) {
2021 result = false;
2022 }
2023 }
2024 return result;
2025 }
2026
2027 /**
2028 * The integer token must be stripped of prefixes, group separators,
2029 * and suffixes, non ascii digits must be converted into ascii digits
2030 * before parse will accept it.
2031 */
2032 private String processIntegerToken(String token) {
2033 String result = token.replaceAll(""+groupSeparator, "");
2034 boolean isNegative = false;
2035 int preLen = negativePrefix.length();
2036 if ((preLen > 0) && result.startsWith(negativePrefix)) {
2037 isNegative = true;
2038 result = result.substring(preLen);
2039 }
2040 int sufLen = negativeSuffix.length();
2041 if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
2042 isNegative = true;
2043 result = result.substring(result.length() - sufLen,
2044 result.length());
2045 }
2046 if (isNegative)
2047 result = "-" + result;
2048 return result;
2049 }
2050
2051 /**
2052 * Scans the next token of the input as an <tt>int</tt>.
2053 *
2054 * <p> An invocation of this method of the form
2055 * <tt>nextInt()</tt> behaves in exactly the same way as the
2056 * invocation <tt>nextInt(radix)</tt>, where <code>radix</code>
2057 * is the default radix of this scanner.
2058 *
2059 * @return the <tt>int</tt> scanned from the input
2060 * @throws InputMismatchException
2061 * if the next token does not match the <i>Integer</i>
2062 * regular expression, or is out of range
2063 * @throws NoSuchElementException if input is exhausted
2064 * @throws IllegalStateException if this scanner is closed
2065 */
2066 public int nextInt() {
2067 return nextInt(defaultRadix);
2068 }
2069
2070 /**
2071 * Scans the next token of the input as an <tt>int</tt>.
2072 * This method will throw <code>InputMismatchException</code>
2073 * if the next token cannot be translated into a valid int value as
2074 * described below. If the translation is successful, the scanner advances
2075 * past the input that matched.
2076 *
2077 * <p> If the next token matches the <a
2078 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2079 * above then the token is converted into an <tt>int</tt> value as if by
2080 * removing all locale specific prefixes, group separators, and locale
2081 * specific suffixes, then mapping non-ASCII digits into ASCII
2082 * digits via {@link Character#digit Character.digit}, prepending a
2083 * negative sign (-) if the locale specific negative prefixes and suffixes
2084 * were present, and passing the resulting string to
2085 * {@link Integer#parseInt(String, int) Integer.parseInt} with the
2086 * specified radix.
2087 *
2088 * @param radix the radix used to interpret the token as an int value
2089 * @return the <tt>int</tt> scanned from the input
2090 * @throws InputMismatchException
2091 * if the next token does not match the <i>Integer</i>
2092 * regular expression, or is out of range
2093 * @throws NoSuchElementException if input is exhausted
2094 * @throws IllegalStateException if this scanner is closed
2095 */
2096 public int nextInt(int radix) {
2097 // Check cached result
2098 if ((typeCache != null) && (typeCache instanceof Integer)
2099 && this.radix == radix) {
2100 int val = ((Integer)typeCache).intValue();
2101 useTypeCache();
2102 return val;
2103 }
2104 setRadix(radix);
2105 clearCaches();
2106 // Search for next int
2107 try {
2108 String s = next(integerPattern());
2109 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2110 s = processIntegerToken(s);
2111 return Integer.parseInt(s, radix);
2112 } catch (NumberFormatException nfe) {
2113 position = matcher.start(); // don't skip bad token
2114 throw new InputMismatchException(nfe.getMessage());
2115 }
2116 }
2117
2118 /**
2119 * Returns true if the next token in this scanner's input can be
2120 * interpreted as a long value in the default radix using the
2121 * {@link #nextLong} method. The scanner does not advance past any input.
2122 *
2123 * @return true if and only if this scanner's next token is a valid
2124 * long value
2125 * @throws IllegalStateException if this scanner is closed
2126 */
2127 public boolean hasNextLong() {
2128 return hasNextLong(defaultRadix);
2129 }
2130
2131 /**
2132 * Returns true if the next token in this scanner's input can be
2133 * interpreted as a long value in the specified radix using the
2134 * {@link #nextLong} method. The scanner does not advance past any input.
2135 *
2136 * @param radix the radix used to interpret the token as a long value
2137 * @return true if and only if this scanner's next token is a valid
2138 * long value
2139 * @throws IllegalStateException if this scanner is closed
2140 */
2141 public boolean hasNextLong(int radix) {
2142 setRadix(radix);
2143 boolean result = hasNext(integerPattern());
2144 if (result) { // Cache it
2145 try {
2146 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2147 processIntegerToken(hasNextResult) :
2148 hasNextResult;
2149 typeCache = Long.parseLong(s, radix);
2150 } catch (NumberFormatException nfe) {
2151 result = false;
2152 }
2153 }
2154 return result;
2155 }
2156
2157 /**
2158 * Scans the next token of the input as a <tt>long</tt>.
2159 *
2160 * <p> An invocation of this method of the form
2161 * <tt>nextLong()</tt> behaves in exactly the same way as the
2162 * invocation <tt>nextLong(radix)</tt>, where <code>radix</code>
2163 * is the default radix of this scanner.
2164 *
2165 * @return the <tt>long</tt> scanned from the input
2166 * @throws InputMismatchException
2167 * if the next token does not match the <i>Integer</i>
2168 * regular expression, or is out of range
2169 * @throws NoSuchElementException if input is exhausted
2170 * @throws IllegalStateException if this scanner is closed
2171 */
2172 public long nextLong() {
2173 return nextLong(defaultRadix);
2174 }
2175
2176 /**
2177 * Scans the next token of the input as a <tt>long</tt>.
2178 * This method will throw <code>InputMismatchException</code>
2179 * if the next token cannot be translated into a valid long value as
2180 * described below. If the translation is successful, the scanner advances
2181 * past the input that matched.
2182 *
2183 * <p> If the next token matches the <a
2184 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2185 * above then the token is converted into a <tt>long</tt> value as if by
2186 * removing all locale specific prefixes, group separators, and locale
2187 * specific suffixes, then mapping non-ASCII digits into ASCII
2188 * digits via {@link Character#digit Character.digit}, prepending a
2189 * negative sign (-) if the locale specific negative prefixes and suffixes
2190 * were present, and passing the resulting string to
2191 * {@link Long#parseLong(String, int) Long.parseLong} with the
2192 * specified radix.
2193 *
2194 * @param radix the radix used to interpret the token as an int value
2195 * @return the <tt>long</tt> scanned from the input
2196 * @throws InputMismatchException
2197 * if the next token does not match the <i>Integer</i>
2198 * regular expression, or is out of range
2199 * @throws NoSuchElementException if input is exhausted
2200 * @throws IllegalStateException if this scanner is closed
2201 */
2202 public long nextLong(int radix) {
2203 // Check cached result
2204 if ((typeCache != null) && (typeCache instanceof Long)
2205 && this.radix == radix) {
2206 long val = ((Long)typeCache).longValue();
2207 useTypeCache();
2208 return val;
2209 }
2210 setRadix(radix);
2211 clearCaches();
2212 try {
2213 String s = next(integerPattern());
2214 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2215 s = processIntegerToken(s);
2216 return Long.parseLong(s, radix);
2217 } catch (NumberFormatException nfe) {
2218 position = matcher.start(); // don't skip bad token
2219 throw new InputMismatchException(nfe.getMessage());
2220 }
2221 }
2222
2223 /**
2224 * The float token must be stripped of prefixes, group separators,
2225 * and suffixes, non ascii digits must be converted into ascii digits
2226 * before parseFloat will accept it.
2227 *
2228 * If there are non-ascii digits in the token these digits must
2229 * be processed before the token is passed to parseFloat.
2230 */
2231 private String processFloatToken(String token) {
2232 String result = token.replaceAll(groupSeparator, "");
2233 if (!decimalSeparator.equals("\\."))
2234 result = result.replaceAll(decimalSeparator, ".");
2235 boolean isNegative = false;
2236 int preLen = negativePrefix.length();
2237 if ((preLen > 0) && result.startsWith(negativePrefix)) {
2238 isNegative = true;
2239 result = result.substring(preLen);
2240 }
2241 int sufLen = negativeSuffix.length();
2242 if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
2243 isNegative = true;
2244 result = result.substring(result.length() - sufLen,
2245 result.length());
2246 }
2247 if (result.equals(nanString))
2248 result = "NaN";
2249 if (result.equals(infinityString))
2250 result = "Infinity";
2251 if (isNegative)
2252 result = "-" + result;
2253
2254 // Translate non-ASCII digits
2255 Matcher m = NON_ASCII_DIGIT.matcher(result);
2256 if (m.find()) {
2257 StringBuilder inASCII = new StringBuilder();
2258 for (int i=0; i<result.length(); i++) {
2259 char nextChar = result.charAt(i);
2260 if (Character.isDigit(nextChar)) {
2261 int d = Character.digit(nextChar, 10);
2262 if (d != -1)
2263 inASCII.append(d);
2264 else
2265 inASCII.append(nextChar);
2266 } else {
2267 inASCII.append(nextChar);
2268 }
2269 }
2270 result = inASCII.toString();
2271 }
2272
2273 return result;
2274 }
2275
2276 /**
2277 * Returns true if the next token in this scanner's input can be
2278 * interpreted as a float value using the {@link #nextFloat}
2279 * method. The scanner does not advance past any input.
2280 *
2281 * @return true if and only if this scanner's next token is a valid
2282 * float value
2283 * @throws IllegalStateException if this scanner is closed
2284 */
2285 public boolean hasNextFloat() {
2286 setRadix(10);
2287 boolean result = hasNext(floatPattern());
2288 if (result) { // Cache it
2289 try {
2290 String s = processFloatToken(hasNextResult);
2291 typeCache = Float.valueOf(Float.parseFloat(s));
2292 } catch (NumberFormatException nfe) {
2293 result = false;
2294 }
2295 }
2296 return result;
2297 }
2298
2299 /**
2300 * Scans the next token of the input as a <tt>float</tt>.
2301 * This method will throw <code>InputMismatchException</code>
2302 * if the next token cannot be translated into a valid float value as
2303 * described below. If the translation is successful, the scanner advances
2304 * past the input that matched.
2305 *
2306 * <p> If the next token matches the <a
2307 * href="#Float-regex"><i>Float</i></a> regular expression defined above
2308 * then the token is converted into a <tt>float</tt> value as if by
2309 * removing all locale specific prefixes, group separators, and locale
2310 * specific suffixes, then mapping non-ASCII digits into ASCII
2311 * digits via {@link Character#digit Character.digit}, prepending a
2312 * negative sign (-) if the locale specific negative prefixes and suffixes
2313 * were present, and passing the resulting string to
2314 * {@link Float#parseFloat Float.parseFloat}. If the token matches
2315 * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2316 * is passed to {@link Float#parseFloat(String) Float.parseFloat} as
2317 * appropriate.
2318 *
2319 * @return the <tt>float</tt> scanned from the input
2320 * @throws InputMismatchException
2321 * if the next token does not match the <i>Float</i>
2322 * regular expression, or is out of range
2323 * @throws NoSuchElementException if input is exhausted
2324 * @throws IllegalStateException if this scanner is closed
2325 */
2326 public float nextFloat() {
2327 // Check cached result
2328 if ((typeCache != null) && (typeCache instanceof Float)) {
2329 float val = ((Float)typeCache).floatValue();
2330 useTypeCache();
2331 return val;
2332 }
2333 setRadix(10);
2334 clearCaches();
2335 try {
2336 return Float.parseFloat(processFloatToken(next(floatPattern())));
2337 } catch (NumberFormatException nfe) {
2338 position = matcher.start(); // don't skip bad token
2339 throw new InputMismatchException(nfe.getMessage());
2340 }
2341 }
2342
2343 /**
2344 * Returns true if the next token in this scanner's input can be
2345 * interpreted as a double value using the {@link #nextDouble}
2346 * method. The scanner does not advance past any input.
2347 *
2348 * @return true if and only if this scanner's next token is a valid
2349 * double value
2350 * @throws IllegalStateException if this scanner is closed
2351 */
2352 public boolean hasNextDouble() {
2353 setRadix(10);
2354 boolean result = hasNext(floatPattern());
2355 if (result) { // Cache it
2356 try {
2357 String s = processFloatToken(hasNextResult);
2358 typeCache = Double.valueOf(Double.parseDouble(s));
2359 } catch (NumberFormatException nfe) {
2360 result = false;
2361 }
2362 }
2363 return result;
2364 }
2365
2366 /**
2367 * Scans the next token of the input as a <tt>double</tt>.
2368 * This method will throw <code>InputMismatchException</code>
2369 * if the next token cannot be translated into a valid double value.
2370 * If the translation is successful, the scanner advances past the input
2371 * that matched.
2372 *
2373 * <p> If the next token matches the <a
2374 * href="#Float-regex"><i>Float</i></a> regular expression defined above
2375 * then the token is converted into a <tt>double</tt> value as if by
2376 * removing all locale specific prefixes, group separators, and locale
2377 * specific suffixes, then mapping non-ASCII digits into ASCII
2378 * digits via {@link Character#digit Character.digit}, prepending a
2379 * negative sign (-) if the locale specific negative prefixes and suffixes
2380 * were present, and passing the resulting string to
2381 * {@link Double#parseDouble Double.parseDouble}. If the token matches
2382 * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2383 * is passed to {@link Double#parseDouble(String) Double.parseDouble} as
2384 * appropriate.
2385 *
2386 * @return the <tt>double</tt> scanned from the input
2387 * @throws InputMismatchException
2388 * if the next token does not match the <i>Float</i>
2389 * regular expression, or is out of range
2390 * @throws NoSuchElementException if the input is exhausted
2391 * @throws IllegalStateException if this scanner is closed
2392 */
2393 public double nextDouble() {
2394 // Check cached result
2395 if ((typeCache != null) && (typeCache instanceof Double)) {
2396 double val = ((Double)typeCache).doubleValue();
2397 useTypeCache();
2398 return val;
2399 }
2400 setRadix(10);
2401 clearCaches();
2402 // Search for next float
2403 try {
2404 return Double.parseDouble(processFloatToken(next(floatPattern())));
2405 } catch (NumberFormatException nfe) {
2406 position = matcher.start(); // don't skip bad token
2407 throw new InputMismatchException(nfe.getMessage());
2408 }
2409 }
2410
2411 // Convenience methods for scanning multi precision numbers
2412
2413 /**
2414 * Returns true if the next token in this scanner's input can be
2415 * interpreted as a <code>BigInteger</code> in the default radix using the
2416 * {@link #nextBigInteger} method. The scanner does not advance past any
2417 * input.
2418 *
2419 * @return true if and only if this scanner's next token is a valid
2420 * <code>BigInteger</code>
2421 * @throws IllegalStateException if this scanner is closed
2422 */
2423 public boolean hasNextBigInteger() {
2424 return hasNextBigInteger(defaultRadix);
2425 }
2426
2427 /**
2428 * Returns true if the next token in this scanner's input can be
2429 * interpreted as a <code>BigInteger</code> in the specified radix using
2430 * the {@link #nextBigInteger} method. The scanner does not advance past
2431 * any input.
2432 *
2433 * @param radix the radix used to interpret the token as an integer
2434 * @return true if and only if this scanner's next token is a valid
2435 * <code>BigInteger</code>
2436 * @throws IllegalStateException if this scanner is closed
2437 */
2438 public boolean hasNextBigInteger(int radix) {
2439 setRadix(radix);
2440 boolean result = hasNext(integerPattern());
2441 if (result) { // Cache it
2442 try {
2443 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2444 processIntegerToken(hasNextResult) :
2445 hasNextResult;
2446 typeCache = new BigInteger(s, radix);
2447 } catch (NumberFormatException nfe) {
2448 result = false;
2449 }
2450 }
2451 return result;
2452 }
2453
2454 /**
2455 * Scans the next token of the input as a {@link java.math.BigInteger
2456 * BigInteger}.
2457 *
2458 * <p> An invocation of this method of the form
2459 * <tt>nextBigInteger()</tt> behaves in exactly the same way as the
2460 * invocation <tt>nextBigInteger(radix)</tt>, where <code>radix</code>
2461 * is the default radix of this scanner.
2462 *
2463 * @return the <tt>BigInteger</tt> scanned from the input
2464 * @throws InputMismatchException
2465 * if the next token does not match the <i>Integer</i>
2466 * regular expression, or is out of range
2467 * @throws NoSuchElementException if the input is exhausted
2468 * @throws IllegalStateException if this scanner is closed
2469 */
2470 public BigInteger nextBigInteger() {
2471 return nextBigInteger(defaultRadix);
2472 }
2473
2474 /**
2475 * Scans the next token of the input as a {@link java.math.BigInteger
2476 * BigInteger}.
2477 *
2478 * <p> If the next token matches the <a
2479 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2480 * above then the token is converted into a <tt>BigInteger</tt> value as if
2481 * by removing all group separators, mapping non-ASCII digits into ASCII
2482 * digits via the {@link Character#digit Character.digit}, and passing the
2483 * resulting string to the {@link
2484 * java.math.BigInteger#BigInteger(java.lang.String)
2485 * BigInteger(String, int)} constructor with the specified radix.
2486 *
2487 * @param radix the radix used to interpret the token
2488 * @return the <tt>BigInteger</tt> scanned from the input
2489 * @throws InputMismatchException
2490 * if the next token does not match the <i>Integer</i>
2491 * regular expression, or is out of range
2492 * @throws NoSuchElementException if the input is exhausted
2493 * @throws IllegalStateException if this scanner is closed
2494 */
2495 public BigInteger nextBigInteger(int radix) {
2496 // Check cached result
2497 if ((typeCache != null) && (typeCache instanceof BigInteger)
2498 && this.radix == radix) {
2499 BigInteger val = (BigInteger)typeCache;
2500 useTypeCache();
2501 return val;
2502 }
2503 setRadix(radix);
2504 clearCaches();
2505 // Search for next int
2506 try {
2507 String s = next(integerPattern());
2508 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2509 s = processIntegerToken(s);
2510 return new BigInteger(s, radix);
2511 } catch (NumberFormatException nfe) {
2512 position = matcher.start(); // don't skip bad token
2513 throw new InputMismatchException(nfe.getMessage());
2514 }
2515 }
2516
2517 /**
2518 * Returns true if the next token in this scanner's input can be
2519 * interpreted as a <code>BigDecimal</code> using the
2520 * {@link #nextBigDecimal} method. The scanner does not advance past any
2521 * input.
2522 *
2523 * @return true if and only if this scanner's next token is a valid
2524 * <code>BigDecimal</code>
2525 * @throws IllegalStateException if this scanner is closed
2526 */
2527 public boolean hasNextBigDecimal() {
2528 setRadix(10);
2529 boolean result = hasNext(decimalPattern());
2530 if (result) { // Cache it
2531 try {
2532 String s = processFloatToken(hasNextResult);
2533 typeCache = new BigDecimal(s);
2534 } catch (NumberFormatException nfe) {
2535 result = false;
2536 }
2537 }
2538 return result;
2539 }
2540
2541 /**
2542 * Scans the next token of the input as a {@link java.math.BigDecimal
2543 * BigDecimal}.
2544 *
2545 * <p> If the next token matches the <a
2546 * href="#Decimal-regex"><i>Decimal</i></a> regular expression defined
2547 * above then the token is converted into a <tt>BigDecimal</tt> value as if
2548 * by removing all group separators, mapping non-ASCII digits into ASCII
2549 * digits via the {@link Character#digit Character.digit}, and passing the
2550 * resulting string to the {@link
2551 * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)}
2552 * constructor.
2553 *
2554 * @return the <tt>BigDecimal</tt> scanned from the input
2555 * @throws InputMismatchException
2556 * if the next token does not match the <i>Decimal</i>
2557 * regular expression, or is out of range
2558 * @throws NoSuchElementException if the input is exhausted
2559 * @throws IllegalStateException if this scanner is closed
2560 */
2561 public BigDecimal nextBigDecimal() {
2562 // Check cached result
2563 if ((typeCache != null) && (typeCache instanceof BigDecimal)) {
2564 BigDecimal val = (BigDecimal)typeCache;
2565 useTypeCache();
2566 return val;
2567 }
2568 setRadix(10);
2569 clearCaches();
2570 // Search for next float
2571 try {
2572 String s = processFloatToken(next(decimalPattern()));
2573 return new BigDecimal(s);
2574 } catch (NumberFormatException nfe) {
2575 position = matcher.start(); // don't skip bad token
2576 throw new InputMismatchException(nfe.getMessage());
2577 }
2578 }
2579
2580 /**
2581 * Resets this scanner.
2582 *
2583 * <p> Resetting a scanner discards all of its explicit state
2584 * information which may have been changed by invocations of {@link
2585 * #useDelimiter}, {@link #useLocale}, or {@link #useRadix}.
2586 *
2587 * <p> An invocation of this method of the form
2588 * <tt>scanner.reset()</tt> behaves in exactly the same way as the
2589 * invocation
2590 *
2591 * <blockquote><pre>
2592 * scanner.useDelimiter("\\p{javaWhitespace}+")
2593 * .useLocale(Locale.getDefault())
2594 * .useRadix(10);
2595 * </pre></blockquote>
2596 *
2597 * @return this scanner
2598 *
2599 * @since 1.6
2600 */
2601 public Scanner reset() {
2602 delimPattern = WHITESPACE_PATTERN;
2603 useLocale(Locale.getDefault());
2604 useRadix(10);
2605 clearCaches();
2606 return this;
2607 }
2608}