KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > Scanner


1 /*
2  * @(#)Scanner.java 1.15 04/07/15
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util;
9
10 import java.util.regex.*;
11 import java.io.*;
12 import java.math.*;
13 import java.nio.*;
14 import java.nio.channels.*;
15 import java.nio.charset.*;
16 import java.text.*;
17 import java.util.Locale JavaDoc;
18 import sun.io.Converters;
19 import sun.misc.LRUCache;
20
21 /**
22  * A simple text scanner which can parse primitive types and strings using
23  * regular expressions.
24  *
25  * <p>A <code>Scanner</code> breaks its input into tokens using a
26  * delimiter pattern, which by default matches whitespace. The resulting
27  * tokens may then be converted into values of different types using the
28  * various <tt>next</tt> methods.
29  *
30  * <p>For example, this code allows a user to read a number from
31  * <tt>System.in</tt>:
32  * <blockquote><pre>
33  * Scanner sc = new Scanner(System.in);
34  * int i = sc.nextInt();
35  * </pre></blockquote>
36  *
37  * <p>As another example, this code allows <code>long</code> types to be
38  * assigned from entries in a file <code>myNumbers</code>:
39  * <blockquote><pre>
40  * Scanner sc = new Scanner(new File("myNumbers"));
41  * while (sc.hasNextLong()) {
42  * long aLong = sc.nextLong();
43  * }</pre></blockquote>
44  *
45  * <p>The scanner can also use delimiters other than whitespace. This
46  * example reads several items in from a string:
47  *<blockquote><pre>
48  * String input = "1 fish 2 fish red fish blue fish";
49  * Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
50  * System.out.println(s.nextInt());
51  * System.out.println(s.nextInt());
52  * System.out.println(s.next());
53  * System.out.println(s.next());
54  * s.close(); </pre></blockquote>
55  * <p>
56  * prints the following output:
57  * <blockquote><pre>
58  * 1
59  * 2
60  * red
61  * blue </pre></blockquote>
62  *
63  * <p>The same output can be generated with this code, which uses a regular
64  * expression to parse all four tokens at once:
65  *<blockquote><pre>
66  * String input = "1 fish 2 fish red fish blue fish";
67  * Scanner s = new Scanner(input);
68  * s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
69  * MatchResult result = s.match();
70  * for (int i=1; i<=result.groupCount(); i++)
71  * System.out.println(result.group(i);
72  * s.close(); </pre></blockquote>
73  *
74  * <p>The default whitespace delimiter used by a scanner is as
75  * recognized by {@link java.lang.Character}.{@link
76  * java.lang.Character#isWhitespace(char) isWhitespace}.
77  *
78  * <p>A scanning operation may block waiting for input.
79  *
80  * <p>The {@link #next} and {@link #hasNext} methods and their
81  * primitive-type companion methods (such as {@link #nextInt} and
82  * {@link #hasNextInt}) first skip any input that matches the delimiter
83  * pattern, and then attempt to return the next token. Both <tt>hasNext</tt>
84  * and <tt>next</tt> methods may block waiting for further input. Whether a
85  * <tt>hasNext</tt> method blocks has no connection to whether or not its
86  * associated <tt>next</tt> method will block.
87  *
88  * <p> The {@link #findInLine}, {@link #findWithinHorizon}, and {@link #skip}
89  * methods operate independently of the delimiter pattern. These methods will
90  * attempt to match the specified pattern with no regard to delimiters in the
91  * input and thus can be used in special circumstances where delimiters are
92  * not relevant. These methods may block waiting for more input.
93  *
94  * <p>When a scanner throws an {@link InputMismatchException}, the scanner
95  * will not pass the token that caused the exception, so that it may be
96  * retrieved or skipped via some other method.
97  *
98  * <p>Depending upon the type of delimiting pattern, empty tokens may be
99  * returned. For example, the pattern <tt>"\\s+"</tt> will return no empty
100  * tokens since it matches multiple instances of the delimiter. The delimiting
101  * pattern <tt>"\\s"</tt> could return empty tokens since it only passes one
102  * space at a time.
103  *
104  * <p> A scanner can read text from any object which implements the {@link
105  * java.lang.Readable} interface. If an invocation of the underlying
106  * readable's {@link java.lang.Readable#read} method throws an {@link
107  * java.io.IOException} then the scanner assumes that the end of the input
108  * has been reached. The most recent <tt>IOException</tt> thrown by the
109  * underlying readable can be retrieved via the {@link #ioException} method.
110  *
111  * <p>When a <code>Scanner</code> is closed, it will close its input source
112  * if the source implements the {@link java.io.Closeable} interface.
113  *
114  * <p>A <code>Scanner</code> is not safe for multithreaded use without
115  * external synchronization.
116  *
117  * <p>Unless otherwise mentioned, passing a <code>null</code> parameter into
118  * any method of a <code>Scanner</code> will cause a
119  * <code>NullPointerException</code> to be thrown.
120  *
121  * <p>A scanner will default to interpreting numbers as decimal unless a
122  * different radix has been set by using the {@link #useRadix} method.
123  *
124  * <a name="localized-numbers">
125  * <h4> Localized numbers </h4>
126  *
127  * <p> An instance of this class is capable of scanning numbers in the standard
128  * formats as well as in the formats of the scanner's locale. A scanner's
129  * initial locale is the value returned by the {@link
130  * java.util.Locale#getDefault} method; it may be changed via the {@link
131  * #useLocale} method.
132  *
133  * <p>The localized formats are defined in terms of the following parameters,
134  * which for a particular locale are taken from that locale's {@link
135  * java.text.DecimalFormat DecimalFormat} object, <tt>df</tt>, and its and
136  * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object,
137  * <tt>dfs</tt>.
138  *
139  * <blockquote><table>
140  * <tr><td valign="top"><i>LocalGroupSeparator&nbsp;&nbsp;</i></td>
141  * <td valign="top">The character used to separate thousands groups,
142  * <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
143  * java.text.DecimalFormatSymbols#getGroupingSeparator
144  * getGroupingSeparator()}</td></tr>
145  * <tr><td valign="top"><i>LocalDecimalSeparator&nbsp;&nbsp;</i></td>
146  * <td valign="top">The character used for the decimal point,
147  * <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
148  * java.text.DecimalFormatSymbols#getDecimalSeparator
149  * getDecimalSeparator()}</td></tr>
150  * <tr><td valign="top"><i>LocalPositivePrefix&nbsp;&nbsp;</i></td>
151  * <td valign="top">The string that appears before a positive number (may
152  * be empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
153  * java.text.DecimalFormat#getPositivePrefix
154  * getPositivePrefix()}</td></tr>
155  * <tr><td valign="top"><i>LocalPositiveSuffix&nbsp;&nbsp;</i></td>
156  * <td valign="top">The string that appears after a positive number (may be
157  * empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
158  * java.text.DecimalFormat#getPositiveSuffix
159  * getPositiveSuffix()}</td></tr>
160  * <tr><td valign="top"><i>LocalNegativePrefix&nbsp;&nbsp;</i></td>
161  * <td valign="top">The string that appears before a negative number (may
162  * be empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
163  * java.text.DecimalFormat#getNegativePrefix
164  * getNegativePrefix()}</td></tr>
165  * <tr><td valign="top"><i>LocalNegativeSuffix&nbsp;&nbsp;</i></td>
166  * <td valign="top">The string that appears after a negative number (may be
167  * empty), <i>i.e.,</i>&nbsp;<tt>df.</tt>{@link
168  * java.text.DecimalFormat#getNegativeSuffix
169  * getNegativeSuffix()}</td></tr>
170  * <tr><td valign="top"><i>LocalNaN&nbsp;&nbsp;</i></td>
171  * <td valign="top">The string that represents not-a-number for
172  * floating-point values,
173  * <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
174  * java.text.DecimalFormatSymbols#getInfinity
175  * getInfinity()}</td></tr>
176  * <tr><td valign="top"><i>LocalInfinity&nbsp;&nbsp;</i></td>
177  * <td valign="top">The string that represents infinity for floating-point
178  * values, <i>i.e.,</i>&nbsp;<tt>dfs.</tt>{@link
179  * java.text.DecimalFormatSymbols#getInfinity
180  * getInfinity()}</td></tr>
181  * </table></blockquote>
182  *
183  * <a name="number-syntax">
184  * <h4> Number syntax </h4>
185  *
186  * <p> The strings that can be parsed as numbers by an instance of this class
187  * are specified in terms of the following regular-expression grammar, where
188  * Rmax is the highest digit in the radix being used (for example, Rmax is 9
189  * in base 10).
190  *
191  * <p>
192  * <table cellspacing=0 cellpadding=0 align=center>
193  *
194  * <tr><td valign=top align=right><i>NonASCIIDigit</i>&nbsp;&nbsp;::</td>
195  * <td valign=top>= A non-ASCII character c for which
196  * {@link java.lang.Character#isDigit Character.isDigit}<tt>(c)</tt>
197  * returns&nbsp;true</td></tr>
198  *
199  * <tr><td>&nbsp;</td></tr>
200  *
201  * <tr><td align=right><i>Non0Digit</i>&nbsp;&nbsp;::</td>
202  * <td><tt>= [1-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr>
203  *
204  * <tr><td>&nbsp;</td></tr>
205  *
206  * <tr><td align=right><i>Digit</i>&nbsp;&nbsp;::</td>
207  * <td><tt>= [0-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr>
208  *
209  * <tr><td>&nbsp;</td></tr>
210  *
211  * <tr><td valign=top align=right><i>GroupedNumeral</i>&nbsp;&nbsp;::</td>
212  * <td valign=top>
213  * <table cellpadding=0 cellspacing=0>
214  * <tr><td><tt>= (&nbsp;</tt></td>
215  * <td><i>Non0Digit</i><tt>
216  * </tt><i>Digit</i><tt>?
217  * </tt><i>Digit</i><tt>?</tt></td></tr>
218  * <tr><td></td>
219  * <td><tt>(&nbsp;</tt><i>LocalGroupSeparator</i><tt>
220  * </tt><i>Digit</i><tt>
221  * </tt><i>Digit</i><tt>
222  * </tt><i>Digit</i><tt> )+ )</tt></td></tr>
223  * </table></td></tr>
224  *
225  * <tr><td>&nbsp;</td></tr>
226  *
227  * <tr><td align=right><i>Numeral</i>&nbsp;&nbsp;::</td>
228  * <td><tt>= ( ( </tt><i>Digit</i><tt>+ )
229  * | </tt><i>GroupedNumeral</i><tt> )</tt></td></tr>
230  *
231  * <tr><td>&nbsp;</td></tr>
232  *
233  * <tr><td valign=top align=right>
234  * <a name="Integer-regex"><i>Integer</i>&nbsp;&nbsp;::</td>
235  * <td valign=top><tt>= ( [-+]? ( </tt><i>Numeral</i><tt>
236  * ) )</tt></td></tr>
237  * <tr><td></td>
238  * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> </tt><i>Numeral</i><tt>
239  * </tt><i>LocalPositiveSuffix</i></td></tr>
240  * <tr><td></td>
241  * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> </tt><i>Numeral</i><tt>
242  * </tt><i>LocalNegativeSuffix</i></td></tr>
243  *
244  * <tr><td>&nbsp;</td></tr>
245  *
246  * <tr><td align=right><i>DecimalNumeral</i>&nbsp;&nbsp;::</td>
247  * <td><tt>= </tt><i>Numeral</i></td></tr>
248  * <tr><td></td>
249  * <td><tt>| </tt><i>Numeral</i><tt>
250  * </tt><i>LocalDecimalSeparator</i><tt>
251  * </tt><i>Digit</i><tt>*</tt></td></tr>
252  * <tr><td></td>
253  * <td><tt>| </tt><i>LocalDecimalSeparator</i><tt>
254  * </tt><i>Digit</i><tt>+</tt></td></tr>
255  *
256  * <tr><td>&nbsp;</td></tr>
257  *
258  * <tr><td align=right><i>Exponent</i>&nbsp;&nbsp;::</td>
259  * <td><tt>= ( [eE] [+-]? </tt><i>Digit</i><tt>+ )</tt></td></tr>
260  *
261  * <tr><td>&nbsp;</td></tr>
262  *
263  * <tr><td align=right>
264  * <a name="Decimal-regex"><i>Decimal</i>&nbsp;&nbsp;::</td>
265  * <td><tt>= ( [-+]? </tt><i>DecimalNumeral</i><tt>
266  * </tt><i>Exponent</i><tt>? )</tt></td></tr>
267  * <tr><td></td>
268  * <td><tt>| </tt><i>LocalPositivePrefix</i><tt>
269  * </tt><i>DecimalNumeral</i><tt>
270  * </tt><i>LocalPositiveSuffix</i>
271  * </tt><i>Exponent</i><tt>?</td></tr>
272  * <tr><td></td>
273  * <td><tt>| </tt><i>LocalNegativePrefix</i><tt>
274  * </tt><i>DecimalNumeral</i><tt>
275  * </tt><i>LocalNegativeSuffix</i>
276  * </tt><i>Exponent</i><tt>?</td></tr>
277  *
278  * <tr><td>&nbsp;</td></tr>
279  *
280  * <tr><td align=right><i>HexFloat</i>&nbsp;&nbsp;::</td>
281  * <td><tt>= [-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+
282  * ([pP][-+]?[0-9]+)?</tt></td></tr>
283  *
284  * <tr><td>&nbsp;</td></tr>
285  *
286  * <tr><td align=right><i>NonNumber</i>&nbsp;&nbsp;::</td>
287  * <td valign=top><tt>= NaN
288  * | </tt><i>LocalNan</i><tt>
289  * | Infinity
290  * | </tt><i>LocalInfinity</i></td></tr>
291  *
292  * <tr><td>&nbsp;</td></tr>
293  *
294  * <tr><td align=right><i>SignedNonNumber</i>&nbsp;&nbsp;::</td>
295  * <td><tt>= ( [-+]? </tt><i>NonNumber</i><tt> )</tt></td></tr>
296  * <tr><td></td>
297  * <td><tt>| </tt><i>LocalPositivePrefix</i><tt>
298  * </tt><i>NonNumber</i><tt>
299  * </tt><i>LocalPositiveSuffix</i></td></tr>
300  * <tr><td></td>
301  * <td><tt>| </tt><i>LocalNegativePrefix</i><tt>
302  * </tt><i>NonNumber</i><tt>
303  * </tt><i>LocalNegativeSuffix</i></td></tr>
304  *
305  * <tr><td>&nbsp;</td></tr>
306  *
307  * <tr><td valign=top align=right>
308  * <a name="Float-regex"><i>Float</i>&nbsp;&nbsp;::</td>
309  * <td valign=top><tt>= </tt><i>Decimal</i><tt></td></tr>
310  * <tr><td></td>
311  * <td><tt>| </tt><i>HexFloat</i><tt></td></tr>
312  * <tr><td></td>
313  * <td><tt>| </tt><i>SignedNonNumber</i><tt></td></tr>
314  *
315  * </table>
316  * </center>
317  *
318  * <p> Whitespace is not significant in the above regular expressions.
319  *
320  * @version 1.15, 07/15/04
321  * @since 1.5
322  */

323 public final class Scanner implements Iterator JavaDoc<String JavaDoc> {
324
325     // Internal buffer used to hold input
326
private CharBuffer buf;
327
328     // Size of internal character buffer
329
private static final int BUFFER_SIZE = 1024; // change to 1024;
330

331     // The index into the buffer currently held by the Scanner
332
private int position;
333
334     // Internal matcher used for finding delimiters
335
private Matcher matcher;
336
337     // Pattern used to delimit tokens
338
private Pattern delimPattern;
339
340     // Pattern found in last hasNext operation
341
private Pattern hasNextPattern;
342
343     // Position after last hasNext operation
344
private int hasNextPosition;
345
346     // Result after last hasNext operation
347
private String JavaDoc hasNextResult;
348
349     // The input source
350
private Readable JavaDoc source;
351
352     // Boolean is true if source is done
353
private boolean sourceClosed = false;
354
355     // Boolean indicating more input is required
356
private boolean needInput = false;
357
358     // Boolean indicating if a delim has been skipped this operation
359
private boolean skipped = false;
360
361     // A store of a position that the scanner may fall back to
362
private int savedScannerPosition = -1;
363
364     // A cache of the last primitive type scanned
365
private Object JavaDoc typeCache = null;
366
367     // Boolean indicating if a match result is available
368
private boolean matchValid = false;
369
370     // Boolean indicating if this scanner has been closed
371
private boolean closed = false;
372
373     // The current radix used by this scanner
374
private int radix = 10;
375
376     // The default radix for this scanner
377
private int defaultRadix = 10;
378
379     // The locale used by this scanner
380
private Locale JavaDoc locale = null;
381
382     // A cache of the last few recently used Patterns
383
private LRUCache<String JavaDoc,Pattern> patternCache =
384     new LRUCache<String JavaDoc,Pattern>(7) {
385         protected Pattern create(String JavaDoc s) {
386             return Pattern.compile(s);
387         }
388         protected boolean hasName(Pattern p, String JavaDoc s) {
389             return p.pattern().equals(s);
390         }
391     };
392
393     // A holder of the last IOException encountered
394
private IOException lastException;
395
396     // A pattern for java whitespace
397
private static Pattern WHITESPACE_PATTERN = Pattern.compile(
398                                                 "\\p{javaWhitespace}+");
399
400     // A pattern for any token
401
private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
402
403     // A pattern for non-ASCII digits
404
private static Pattern NON_ASCII_DIGIT = Pattern.compile(
405         "[\\p{javaDigit}&&[^0-9]]");
406
407     // Fields and methods to support scanning primitive types
408

409     /**
410      * Locale dependent values used to scan numbers
411      */

412     private String JavaDoc groupSeparator = "\\,";
413     private String JavaDoc decimalSeparator = "\\.";
414     private String JavaDoc nanString = "NaN";
415     private String JavaDoc infinityString = "Infinity";
416     private String JavaDoc positivePrefix = "";
417     private String JavaDoc negativePrefix = "\\-";
418     private String JavaDoc positiveSuffix = "";
419     private String JavaDoc negativeSuffix = "";
420
421     /**
422      * Fields and an accessor method to match booleans
423      */

424     private static volatile Pattern boolPattern;
425     private static final String JavaDoc BOOLEAN_PATTERN = "true|false";
426     private static Pattern boolPattern() {
427         Pattern bp = boolPattern;
428         if (bp == null)
429             boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN,
430                                           Pattern.CASE_INSENSITIVE);
431         return bp;
432     }
433
434     /**
435      * Fields and methods to match bytes, shorts, ints, and longs
436      */

437     private Pattern integerPattern;
438     private String JavaDoc digits = "0123456789abcdefghijklmnopqrstuvwxyz";
439     private String JavaDoc non0Digit = "[\\p{javaDigit}&&[^0]]";
440     private int SIMPLE_GROUP_INDEX = 5;
441     private String JavaDoc buildIntegerPatternString() {
442         String JavaDoc radixDigits = digits.substring(0, radix);
443         // \\p{javaDigit} is not guaranteed to be appropriate
444
// here but what can we do? The final authority will be
445
// whatever parse method is invoked, so ultimately the
446
// Scanner will do the right thing
447
String JavaDoc digit = "((?i)["+radixDigits+"]|\\p{javaDigit})";
448         String JavaDoc groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
449                                 groupSeparator+digit+digit+digit+")+)";
450         // digit++ is the possessive form which is necessary for reducing
451
// backtracking that would otherwise cause unacceptable performance
452
String JavaDoc numeral = "(("+ digit+"++)|"+groupedNumeral+")";
453         String JavaDoc javaStyleInteger = "([-+]?(" + numeral + "))";
454         String JavaDoc negativeInteger = negativePrefix + numeral + negativeSuffix;
455         String JavaDoc positiveInteger = positivePrefix + numeral + positiveSuffix;
456         return "("+ javaStyleInteger + ")|(" +
457             positiveInteger + ")|(" +
458             negativeInteger + ")";
459     }
460     private Pattern integerPattern() {
461         if (integerPattern == null) {
462             integerPattern = patternCache.forName(buildIntegerPatternString());
463         }
464         return integerPattern;
465     }
466
467     /**
468      * Fields and an accessor method to match line separators
469      */

470     private static volatile Pattern separatorPattern;
471     private static final String JavaDoc LINE_SEPARATOR_PATTERN =
472                                            "\r\n|[\n\r\u2028\u2029\u0085]";
473     private static Pattern separatorPattern() {
474         Pattern sp = separatorPattern;
475         if (sp == null)
476             separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
477         return sp;
478     }
479
480     /**
481      * Fields and methods to match floats and doubles
482      */

483     private Pattern floatPattern;
484     private Pattern decimalPattern;
485     private void buildFloatAndDecimalPattern() {
486         // \\p{javaDigit} may not be perfect, see above
487
String JavaDoc digit = "([0-9]|(\\p{javaDigit}))";
488         String JavaDoc exponent = "([eE][+-]?"+digit+"+)?";
489         String JavaDoc groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
490                                 groupSeparator+digit+digit+digit+")+)";
491         // Once again digit++ is used for performance, as above
492
String JavaDoc numeral = "(("+digit+"++)|"+groupedNumeral+")";
493         String JavaDoc decimalNumeral = "("+numeral+"|"+numeral +
494             decimalSeparator + digit + "*+|"+ decimalSeparator +
495             digit + "++)";
496         String JavaDoc nonNumber = "(NaN|"+nanString+"|Infinity|"+
497                                infinityString+")";
498         String JavaDoc positiveFloat = "(" + positivePrefix + decimalNumeral +
499                             positiveSuffix + exponent + ")";
500         String JavaDoc negativeFloat = "(" + negativePrefix + decimalNumeral +
501                             negativeSuffix + exponent + ")";
502         String JavaDoc decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+
503             positiveFloat + "|" + negativeFloat + ")";
504         String JavaDoc hexFloat =
505             "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?";
506         String JavaDoc positiveNonNumber = "(" + positivePrefix + nonNumber +
507                             positiveSuffix + ")";
508         String JavaDoc negativeNonNumber = "(" + negativePrefix + nonNumber +
509                             negativeSuffix + ")";
510         String JavaDoc signedNonNumber = "(([-+]?"+nonNumber+")|" +
511                                  positiveNonNumber + "|" +
512                                  negativeNonNumber + ")";
513         floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" +
514                                        signedNonNumber);
515         decimalPattern = Pattern.compile(decimal);
516     }
517     private Pattern floatPattern() {
518         if (floatPattern == null) {
519             buildFloatAndDecimalPattern();
520         }
521         return floatPattern;
522     }
523     private Pattern decimalPattern() {
524         if (decimalPattern == null) {
525             buildFloatAndDecimalPattern();
526         }
527         return decimalPattern;
528     }
529
530     // Constructors
531

532     /**
533      * Constructs a <code>Scanner</code> that returns values scanned
534      * from the specified source delimited by the specified pattern.
535      *
536      * @param source A character source implementing the Readable interface
537      * @param pattern A delimiting pattern
538      * @return A scanner with the specified source and pattern
539      */

540     private Scanner(Readable JavaDoc source, Pattern pattern) {
541         if (source == null)
542             throw new NullPointerException JavaDoc("source");
543         if (pattern == null)
544             throw new NullPointerException JavaDoc("pattern");
545         this.source = source;
546         delimPattern = pattern;
547         buf = CharBuffer.allocate(BUFFER_SIZE);
548         buf.limit(0);
549         matcher = delimPattern.matcher(buf);
550         matcher.useTransparentBounds(true);
551         matcher.useAnchoringBounds(false);
552         useLocale(Locale.getDefault());
553     }
554
555     /**
556      * Constructs a new <code>Scanner</code> that produces values scanned
557      * from the specified source.
558      *
559      * @param source A character source implementing the {@link Readable}
560      * interface
561      */

562     public Scanner(Readable JavaDoc source) {
563         this(source, WHITESPACE_PATTERN);
564     }
565
566     /**
567      * Constructs a new <code>Scanner</code> that produces values scanned
568      * from the specified input stream. Bytes from the stream are converted
569      * into characters using the underlying platform's
570      * {@linkplain java.nio.charset.Charset#defaultCharset default charset}.
571      *
572      * @param source An input stream to be scanned
573      */

574     public Scanner(InputStream source) {
575         this(new InputStreamReader(source), WHITESPACE_PATTERN);
576     }
577
578     /**
579      * Constructs a new <code>Scanner</code> that produces values scanned
580      * from the specified input stream. Bytes from the stream are converted
581      * into characters using the specified charset.
582      *
583      * @param source An input stream to be scanned
584      * @param charsetName The encoding type used to convert bytes from the
585      * stream into characters to be scanned
586      * @throws IllegalArgumentException if the specified character set
587      * does not exist
588      */

589     public Scanner(InputStream source, String JavaDoc charsetName) {
590         this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
591     }
592
593     private static Readable JavaDoc makeReadable(InputStream source,
594                                          String JavaDoc charsetName)
595     {
596         if (source == null)
597             throw new NullPointerException JavaDoc("source");
598         InputStreamReader isr = null;
599         try {
600             isr = new InputStreamReader(source, charsetName);
601         } catch (UnsupportedEncodingException uee) {
602             IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc();
603             iae.initCause(uee);
604             throw iae;
605         }
606         return isr;
607     }
608
609     /**
610      * Constructs a new <code>Scanner</code> that produces values scanned
611      * from the specified file. Bytes from the file are converted into
612      * characters using the underlying platform's
613      * {@linkplain java.nio.charset.Charset#defaultCharset default charset}.
614      *
615      * @param source A file to be scanned
616      * @throws FileNotFoundException if source is not found
617      */

618     public Scanner(File source)
619         throws FileNotFoundException
620     {
621         this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
622     }
623
624     /**
625      * Constructs a new <code>Scanner</code> that produces values scanned
626      * from the specified file. Bytes from the file are converted into
627      * characters using the specified charset.
628      *
629      * @param source A file to be scanned
630      * @param charsetName The encoding type used to convert bytes from the file
631      * into characters to be scanned
632      * @throws FileNotFoundException if source is not found
633      * @throws IllegalArgumentException if the specified encoding is
634      * not found
635      */

636     public Scanner(File source, String JavaDoc charsetName)
637         throws FileNotFoundException
638     {
639         this((ReadableByteChannel)(new FileInputStream(source).getChannel()),
640              charsetName);
641     }
642
643     /**
644      * Constructs a new <code>Scanner</code> that produces values scanned
645      * from the specified string.
646      *
647      * @param source A string to scan
648      */

649     public Scanner(String JavaDoc source) {
650         this(new StringReader(source), WHITESPACE_PATTERN);
651     }
652
653     /**
654      * Constructs a new <code>Scanner</code> that produces values scanned
655      * from the specified channel. Bytes from the source are converted into
656      * characters using the underlying platform's
657      * {@linkplain java.nio.charset.Charset#defaultCharset default charset}.
658      *
659      * @param source A channel to scan
660      */

661     public Scanner(ReadableByteChannel source) {
662         this(makeReadable(source), WHITESPACE_PATTERN);
663     }
664
665     private static Readable JavaDoc makeReadable(ReadableByteChannel source) {
666         if (source == null)
667             throw new NullPointerException JavaDoc("source");
668         String JavaDoc defaultCharsetName =
669             java.nio.charset.Charset.defaultCharset().name();
670         return Channels.newReader(source,
671                            java.nio.charset.Charset.defaultCharset().name());
672     }
673
674     /**
675      * Constructs a new <code>Scanner</code> that produces values scanned
676      * from the specified channel. Bytes from the source are converted into
677      * characters using the specified charset.
678      *
679      * @param source A channel to scan
680      * @param charsetName The encoding type used to convert bytes from the
681      * channel into characters to be scanned
682      * @throws IllegalArgumentException if the specified character set
683      * does not exist
684      */

685     public Scanner(ReadableByteChannel source, String JavaDoc charsetName) {
686         this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
687     }
688
689     private static Readable JavaDoc makeReadable(ReadableByteChannel source,
690                                   String JavaDoc charsetName)
691     {
692         if (source == null)
693             throw new NullPointerException JavaDoc("source");
694         if (!Charset.isSupported(charsetName))
695             throw new IllegalArgumentException JavaDoc(charsetName);
696         return Channels.newReader(source, charsetName);
697     }
698
699     // Private primitives used to support scanning
700

701     private void saveState() {
702         savedScannerPosition = position;
703     }
704
705     private void revertState() {
706         this.position = savedScannerPosition;
707         savedScannerPosition = -1;
708         skipped = false;
709     }
710
711     private boolean revertState(boolean b) {
712         this.position = savedScannerPosition;
713         savedScannerPosition = -1;
714         skipped = false;
715         return b;
716     }
717
718     private void cacheResult(Pattern p) {
719         hasNextPattern = p;
720         hasNextResult = matcher.group();
721         hasNextPosition = matcher.end();
722     }
723
724     // Clears both regular cache and type cache
725
private void clearCaches() {
726         hasNextPattern = null;
727         typeCache = null;
728     }
729
730     // Also clears the both the regular cache and the type cache
731
private String JavaDoc getCachedResult() {
732         position = hasNextPosition;
733         hasNextPattern = null;
734         typeCache = null;
735         return hasNextResult;
736     }
737
738     // Also clears the both the regular cache and the type cache
739
private void useTypeCache() {
740         if (closed)
741             throw new IllegalStateException JavaDoc("Scanner closed");
742         position = hasNextPosition;
743         hasNextPattern = null;
744         typeCache = null;
745     }
746
747     // Tries to read more input. May block.
748
private void readInput() {
749         if (buf.limit() == buf.capacity())
750             makeSpace();
751
752         // Prepare to receive data
753
int p = buf.position();
754         buf.position(buf.limit());
755         buf.limit(buf.capacity());
756
757         int n = 0;
758         try {
759             n = source.read(buf);
760         } catch (IOException ioe) {
761             lastException = ioe;
762             n = -1;
763         }
764
765         if (n == -1) {
766             sourceClosed = true;
767             needInput = false;
768         }
769
770         if (n > 0)
771             needInput = false;
772
773         // Restore current position and limit for reading
774
buf.limit(buf.position());
775         buf.position(p);
776     }
777
778     // After this method is called there will either be an exception
779
// or else there will be space in the buffer
780
private boolean makeSpace() {
781         clearCaches();
782         int offset = savedScannerPosition == -1 ?
783             position : savedScannerPosition;
784         buf.position(offset);
785         // Gain space by compacting buffer
786
if (offset > 0) {
787             buf.compact();
788             translateSavedIndexes(offset);
789             position -= offset;
790             buf.flip();
791             return true;
792         }
793         // Gain space by growing buffer
794
int newSize = buf.capacity() * 2;
795         CharBuffer newBuf = CharBuffer.allocate(newSize);
796         newBuf.put(buf);
797         newBuf.flip();
798         translateSavedIndexes(offset);
799         position -= offset;
800         buf = newBuf;
801         matcher.reset(buf);
802         return true;
803     }
804
805     // When a buffer compaction/reallocation occurs the saved indexes must
806
// be modified appropriately
807
private void translateSavedIndexes(int offset) {
808         if (savedScannerPosition != -1)
809             savedScannerPosition -= offset;
810     }
811
812     // If we are at the end of input then NoSuchElement;
813
// If there is still input left then InputMismatch
814
private void throwFor() {
815         skipped = false;
816         if ((sourceClosed) && (position == buf.limit()))
817             throw new NoSuchElementException JavaDoc();
818         else
819             throw new InputMismatchException JavaDoc();
820     }
821
822     // Returns true if a complete token or partial token is in the buffer.
823
// It is not necessary to find a complete token since a partial token
824
// means that there will be another token with or without more input.
825
private boolean hasTokenInBuffer() {
826         matchValid = false;
827         matcher.usePattern(delimPattern);
828         matcher.region(position, buf.limit());
829
830         // Skip delims first
831
if (matcher.lookingAt())
832             position = matcher.end();
833
834         // If we are sitting at the end, no more tokens in buffer
835
if (position == buf.limit())
836             return false;
837
838         return true;
839     }
840
841     /*
842      * Returns a "complete token" that matches the specified pattern
843      *
844      * A token is complete if surrounded by delims; a partial token
845      * is prefixed by delims but not postfixed by them
846      *
847      * The position is advanced to the end of that complete token
848      *
849      * Pattern == null means accept any token at all
850      *
851      * Triple return:
852      * 1. valid string means it was found
853      * 2. null with needInput=false means we won't ever find it
854      * 3. null with needInput=true means try again after readInput
855      */

856     private String JavaDoc getCompleteTokenInBuffer(Pattern pattern) {
857         matchValid = false;
858
859         // Skip delims first
860
matcher.usePattern(delimPattern);
861         if (!skipped) { // Enforcing only one skip of leading delims
862
matcher.region(position, buf.limit());
863             if (matcher.lookingAt()) {
864                 // If more input could extend the delimiters then we must wait
865
// for more input
866
if (matcher.hitEnd() && !sourceClosed) {
867                     needInput = true;
868                     return null;
869                 }
870                 // The delims were whole and the matcher should skip them
871
skipped = true;
872                 position = matcher.end();
873             }
874         }
875
876         // If we are sitting at the end, no more tokens in buffer
877
if (position == buf.limit()) {
878             if (sourceClosed)
879                 return null;
880             needInput = true;
881             return null;
882         }
883
884         // Must look for next delims. Simply attempting to match the
885
// pattern at this point may find a match but it might not be
886
// the first longest match because of missing input, or it might
887
// match a partial token instead of the whole thing.
888

889         // Then look for next delims
890
matcher.region(position, buf.limit());
891         boolean foundNextDelim = matcher.find();
892         if (foundNextDelim && (matcher.end() == position)) {
893             // Zero length delimiter match; we should find the next one
894
// using the automatic advance past a zero length match;
895
// Otherwise we have just found the same one we just skipped
896
foundNextDelim = matcher.find();
897         }
898         if (foundNextDelim) {
899             // In the rare case that more input could cause the match
900
// to be lost and there is more input coming we must wait
901
// for more input. Note that hitting the end is okay as long
902
// as the match cannot go away. It is the beginning of the
903
// next delims we want to be sure about, we don't care if
904
// they potentially extend further.
905
if (matcher.requireEnd() && !sourceClosed) {
906                 needInput = true;
907                 return null;
908             }
909             int tokenEnd = matcher.start();
910             // There is a complete token.
911
if (pattern == null) {
912                 // Must continue with match to provide valid MatchResult
913
pattern = FIND_ANY_PATTERN;
914             }
915             // Attempt to match against the desired pattern
916
matcher.usePattern(pattern);
917             matcher.region(position, tokenEnd);
918             if (matcher.matches()) {
919                 String JavaDoc s = matcher.group();
920                 position = matcher.end();
921                 return s;
922             } else { // Complete token but it does not match
923
return null;
924             }
925         }
926
927         // If we can't find the next delims but no more input is coming,
928
// then we can treat the remainder as a whole token
929
if (sourceClosed) {
930             if (pattern == null) {
931                 // Must continue with match to provide valid MatchResult
932
pattern = FIND_ANY_PATTERN;
933             }
934             // Last token; Match the pattern here or throw
935
matcher.usePattern(pattern);
936             matcher.region(position, buf.limit());
937             if (matcher.matches()) {
938                 String JavaDoc s = matcher.group();
939                 position = matcher.end();
940                 return s;
941             }
942             // Last piece does not match
943
return null;
944         }
945
946         // There is a partial token in the buffer; must read more
947
// to complete it
948
needInput = true;
949         return null;
950     }
951
952     // Finds the specified pattern in the buffer up to horizon.
953
// Returns a match for the specified input pattern.
954
private String JavaDoc findPatternInBuffer(Pattern pattern, int horizon) {
955         matchValid = false;
956         matcher.usePattern(pattern);
957         int bufferLimit = buf.limit();
958         int horizonLimit = -1;
959         int searchLimit = bufferLimit;
960         if (horizon > 0) {
961             horizonLimit = position + horizon;
962             if (horizonLimit < bufferLimit)
963                 searchLimit = horizonLimit;
964         }
965         matcher.region(position, searchLimit);
966         if (matcher.find()) {
967             if (matcher.hitEnd() && (!sourceClosed)) {
968                 // The match may be longer if didn't hit horizon or real end
969
if (searchLimit != horizonLimit) {
970                      // Hit an artificial end; try to extend the match
971
needInput = true;
972                     return null;
973                 }
974                 // The match could go away depending on what is next
975
if ((searchLimit == horizonLimit) && matcher.requireEnd()) {
976                     // Rare case: we hit the end of input and it happens
977
// that it is at the horizon and the end of input is
978
// required for the match.
979
needInput = true;
980                     return null;
981                 }
982             }
983             // Did not hit end, or hit real end, or hit horizon
984
position = matcher.end();
985             return matcher.group();
986         }
987
988         if (sourceClosed)
989             return null;
990
991         // If there is no specified horizon, or if we have not searched
992
// to the specified horizon yet, get more input
993
if ((horizon == 0) || (searchLimit != horizonLimit))
994             needInput = true;
995         return null;
996     }
997
998     // Returns a match for the specified input pattern anchored at
999
// the current position
1000
private String JavaDoc matchPatternInBuffer(Pattern pattern) {
1001        matchValid = false;
1002        matcher.usePattern(pattern);
1003        matcher.region(position, buf.limit());
1004        if (matcher.lookingAt()) {
1005            if (matcher.hitEnd() && (!sourceClosed)) {
1006                // Get more input and try again
1007
needInput = true;
1008                return null;
1009            }
1010            position = matcher.end();
1011            return matcher.group();
1012        }
1013
1014        if (sourceClosed)
1015            return null;
1016
1017        // Read more to find pattern
1018
needInput = true;
1019        return null;
1020    }
1021
1022    // Throws if the scanner is closed
1023
private void ensureOpen() {
1024        if (closed)
1025            throw new IllegalStateException JavaDoc("Scanner closed");
1026    }
1027
1028    // Public methods
1029

1030    /**
1031     * Closes this scanner.
1032     *
1033     * <p> If this scanner has not yet been closed then if its underlying
1034     * {@linkplain java.lang.Readable readable} also implements the {@link
1035     * java.io.Closeable} interface then the readable's <tt>close</tt> method
1036     * will be invoked. If this scanner is already closed then invoking this
1037     * method will have no effect.
1038     *
1039     * <p>Attempting to perform search operations after a scanner has
1040     * been closed will result in an {@link IllegalStateException}.
1041     *
1042     */

1043    public void close() {
1044        if (closed)
1045            return;
1046        if (source instanceof Closeable) {
1047            try {
1048                ((Closeable)source).close();
1049            } catch (IOException ioe) {
1050                lastException = ioe;
1051            }
1052        }
1053        sourceClosed = true;
1054        source = null;
1055        closed = true;
1056    }
1057
1058    /**
1059     * Returns the <code>IOException</code> last thrown by this
1060     * <code>Scanner</code>'s underlying <code>Readable</code>. This method
1061     * returns <code>null</code> if no such exception exists.
1062     *
1063     * @return the last exception thrown by this scanner's readable
1064     */

1065    public IOException ioException() {
1066        return lastException;
1067    }
1068
1069    /**
1070     * Returns the <code>Pattern</code> this <code>Scanner</code> is currently
1071     * using to match delimiters.
1072     *
1073     * @return this scanner's delimiting pattern.
1074     */

1075    public Pattern delimiter() {
1076        return delimPattern;
1077    }
1078
1079    /**
1080     * Sets this scanner's delimiting pattern to the specified pattern.
1081     *
1082     * @param pattern A delimiting pattern
1083     * @return this scanner
1084     */

1085    public Scanner JavaDoc useDelimiter(Pattern pattern) {
1086        delimPattern = pattern;
1087        return this;
1088    }
1089
1090    /**
1091     * Sets this scanner's delimiting pattern to a pattern constructed from
1092     * the specified <code>String</code>.
1093     *
1094     * <p> An invocation of this method of the form
1095     * <tt>useDelimiter(pattern)</tt> behaves in exactly the same way as the
1096     * invocation <tt>hasDelimiter(Pattern.compile(pattern))</tt>.
1097     *
1098     * @param pattern A string specifying a delimiting pattern
1099     * @return this scanner
1100     */

1101    public Scanner JavaDoc useDelimiter(String JavaDoc pattern) {
1102        delimPattern = patternCache.forName(pattern);
1103        return this;
1104    }
1105
1106    /**
1107     * Returns this scanner's locale.
1108     *
1109     * <p>A scanner's locale affects many elements of its default
1110     * primitive matching regular expressions; see
1111     * <a HREF= "#localized-numbers">localized numbers</a> above.
1112     *
1113     * @return this scanner's locale
1114     */

1115    public Locale JavaDoc locale() {
1116        return this.locale;
1117    }
1118
1119    /**
1120     * Sets this scanner's locale to the specified locale.
1121     *
1122     * <p>A scanner's locale affects many elements of its default
1123     * primitive matching regular expressions; see
1124     * <a HREF= "#localized-numbers">localized numbers</a> above.
1125     *
1126     * @param locale A string specifying the locale to use
1127     * @return this scanner
1128     */

1129    public Scanner JavaDoc useLocale(Locale JavaDoc locale) {
1130        if (locale.equals(this.locale))
1131            return this;
1132
1133        this.locale = locale;
1134        DecimalFormat df =
1135            (DecimalFormat)NumberFormat.getNumberInstance(locale);
1136        DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale);
1137
1138        // These must be literalized to avoid collision with regex
1139
// metacharacters such as dot or parenthesis
1140
groupSeparator = "\\" + dfs.getGroupingSeparator();
1141        decimalSeparator = "\\" + dfs.getDecimalSeparator();
1142
1143        // Quoting the nonzero length locale-specific things
1144
// to avoid potential conflict with metacharacters
1145
nanString = "\\Q" + dfs.getNaN() + "\\E";
1146        infinityString = "\\Q" + dfs.getInfinity() + "\\E";
1147        positivePrefix = df.getPositivePrefix();
1148        if (positivePrefix.length() > 0)
1149            positivePrefix = "\\Q" + positivePrefix + "\\E";
1150        negativePrefix = df.getNegativePrefix();
1151        if (negativePrefix.length() > 0)
1152            negativePrefix = "\\Q" + negativePrefix + "\\E";
1153        positiveSuffix = df.getPositiveSuffix();
1154        if (positiveSuffix.length() > 0)
1155            positiveSuffix = "\\Q" + positiveSuffix + "\\E";
1156        negativeSuffix = df.getNegativeSuffix();
1157        if (negativeSuffix.length() > 0)
1158            negativeSuffix = "\\Q" + negativeSuffix + "\\E";
1159
1160        // Force rebuilding and recompilation of locale dependent
1161
// primitive patterns
1162
integerPattern = null;
1163        floatPattern = null;
1164
1165        return this;
1166    }
1167
1168    /**
1169     * Returns this scanner's default radix.
1170     *
1171     * <p>A scanner's radix affects elements of its default
1172     * number matching regular expressions; see
1173     * <a HREF= "#localized-numbers">localized numbers</a> above.
1174     *
1175     * @return the default radix of this scanner
1176     */

1177    public int radix() {
1178        return this.defaultRadix;
1179    }
1180
1181    /**
1182     * Sets this scanner's default radix to the specified radix.
1183     *
1184     * <p>A scanner's radix affects elements of its default
1185     * number matching regular expressions; see
1186     * <a HREF= "#localized-numbers">localized numbers</a> above.
1187     *
1188     * <p>If the radix is less than <code>Character.MIN_RADIX</code>
1189     * or greater than <code>Character.MAX_RADIX</code>, then an
1190     * <code>IllegalArgumentException</code> is thrown.
1191     *
1192     * @param radix The radix to use when scanning numbers
1193     * @return this scanner
1194     * @throws IllegalArgumentException if radix is out of range
1195     */

1196    public Scanner JavaDoc useRadix(int radix) {
1197        if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
1198            throw new IllegalArgumentException JavaDoc("radix:"+radix);
1199
1200        if (this.defaultRadix == radix)
1201            return this;
1202        this.defaultRadix = radix;
1203        // Force rebuilding and recompilation of radix dependent patterns
1204
integerPattern = null;
1205        return this;
1206    }
1207
1208    // The next operation should occur in the specified radix but
1209
// the default is left untouched.
1210
private void setRadix(int radix) {
1211        if (this.radix != radix) {
1212            // Force rebuilding and recompilation of radix dependent patterns
1213
integerPattern = null;
1214            this.radix = radix;
1215        }
1216    }
1217
1218    /**
1219     * Returns the match result of the last scanning operation performed
1220     * by this scanner. This method throws <code>IllegalStateException</code>
1221     * if no match has been performed, or if the last match was
1222     * not successful.
1223     *
1224     * <p>The various <code>next</code>methods of <code>Scanner</code>
1225     * make a match result available if they complete without throwing an
1226     * exception. For instance, after an invocation of the {@link #nextInt}
1227     * method that returned an int, this method returns a
1228     * <code>MatchResult</code> for the search of the
1229     * <a HREF="#Integer-regex"><i>Integer</i></a> regular expression
1230     * defined above. Similarly the {@link #findInLine},
1231     * {@link #findWithinHorizon}, and {@link #skip} methods will make a
1232     * match available if they succeed.
1233     *
1234     * @return a match result for the last match operation
1235     * @throws IllegalStateException If no match result is available
1236     */

1237    public MatchResult match() {
1238        if (!matchValid)
1239            throw new IllegalStateException JavaDoc("No match result available");
1240        return matcher.toMatchResult();
1241    }
1242
1243    /**
1244     * <p>Returns the string representation of this <code>Scanner</code>. The
1245     * string representation of a <code>Scanner</code> contains information
1246     * that may be useful for debugging. The exact format is unspecified.
1247     *
1248     * @return The string representation of this scanner
1249     */

1250    public String JavaDoc toString() {
1251        StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
1252    sb.append("java.util.Scanner");
1253    sb.append("[delimiters=" + delimPattern + "]");
1254    sb.append("[position=" + position + "]");
1255    sb.append("[match valid=" + matchValid + "]");
1256    sb.append("[need input=" + needInput + "]");
1257    sb.append("[source closed=" + sourceClosed + "]");
1258        sb.append("[skipped=" + skipped + "]");
1259        sb.append("[group separator=" + groupSeparator + "]");
1260        sb.append("[decimal separator=" + decimalSeparator + "]");
1261        sb.append("[positive prefix=" + positivePrefix + "]");
1262    sb.append("[negative prefix=" + negativePrefix + "]");
1263    sb.append("[positive suffix=" + positiveSuffix + "]");
1264    sb.append("[negative suffix=" + negativeSuffix + "]");
1265    sb.append("[NaN string=" + nanString + "]");
1266    sb.append("[infinity string=" + infinityString + "]");
1267    return sb.toString();
1268    }
1269
1270    /**
1271     * Returns true if this scanner has another token in its input.
1272     * This method may block while waiting for input to scan.
1273     * The scanner does not advance past any input.
1274     *
1275     * @return true if and only if this scanner has another token
1276     * @throws IllegalStateException if this scanner is closed
1277     * @see java.util.Iterator
1278     */

1279    public boolean hasNext() {
1280        ensureOpen();
1281        saveState();
1282        while (!sourceClosed) {
1283            if (hasTokenInBuffer())
1284                return revertState(true);
1285            readInput();
1286        }
1287        boolean result = hasTokenInBuffer();
1288        return revertState(result);
1289    }
1290
1291    /**
1292     * Finds and returns the next complete token from this scanner.
1293     * A complete token is preceded and followed by input that matches
1294     * the delimiter pattern. This method may block while waiting for input
1295     * to scan, even if a previous invocation of {@link #hasNext} returned
1296     * <code>true</code>.
1297     *
1298     * @return the next token
1299     * @throws NoSuchElementException if no more tokens are available
1300     * @throws IllegalStateException if this scanner is closed
1301     * @see java.util.Iterator
1302     */

1303    public String JavaDoc next() {
1304        ensureOpen();
1305        clearCaches();
1306        
1307        while (true) {
1308            String JavaDoc token = getCompleteTokenInBuffer(null);
1309            if (token != null) {
1310                matchValid = true;
1311                skipped = false;
1312                return token;
1313            }
1314            if (needInput)
1315                readInput();
1316            else
1317                throwFor();
1318        }
1319    }
1320
1321    /**
1322     * The remove operation is not supported by this implementation of
1323     * <code>Iterator</code>.
1324     *
1325     * @throws UnsupportedOperationException if this method is invoked.
1326     * @see java.util.Iterator
1327     */

1328    public void remove() {
1329        throw new UnsupportedOperationException JavaDoc();
1330    }
1331
1332    /**
1333     * Returns true if the next token matches the pattern constructed from the
1334     * specified string. The scanner does not advance past any input.
1335     *
1336     * <p> An invocation of this method of the form <tt>hasNext(pattern)</tt>
1337     * behaves in exactly the same way as the invocation
1338     * <tt>hasNext(Pattern.compile(pattern))</tt>.
1339     *
1340     * @param pattern a string specifying the pattern to scan
1341     * @return true if and only if this scanner has another token matching
1342     * the specified pattern
1343     * @throws IllegalStateException if this scanner is closed
1344     */

1345    public boolean hasNext(String JavaDoc pattern) {
1346        return hasNext(patternCache.forName(pattern));
1347    }
1348
1349    /**
1350     * Returns the next token if it matches the pattern constructed from the
1351     * specified string. If the match is successful, the scanner advances
1352     * past the input that matched the pattern.
1353     *
1354     * <p> An invocation of this method of the form <tt>next(pattern)</tt>
1355     * behaves in exactly the same way as the invocation
1356     * <tt>next(Pattern.compile(pattern))</tt>.
1357     *
1358     * @param pattern a string specifying the pattern to scan
1359     * @return the next token
1360     * @throws NoSuchElementException if no such tokens are available
1361     * @throws IllegalStateException if this scanner is closed
1362     */

1363    public String JavaDoc next(String JavaDoc pattern) {
1364        return next(patternCache.forName(pattern));
1365    }
1366
1367    /**
1368     * Returns true if the next complete token matches the specified pattern.
1369     * A complete token is prefixed and postfixed by input that matches
1370     * the delimiter pattern. This method may block while waiting for input.
1371     * The scanner does not advance past any input.
1372     *
1373     * @param pattern the pattern to scan for
1374     * @return true if and only if this scanner has another token matching
1375     * the specified pattern
1376     * @throws IllegalStateException if this scanner is closed
1377     */

1378    public boolean hasNext(Pattern pattern) {
1379        ensureOpen();
1380        if (pattern == null)
1381            throw new NullPointerException JavaDoc();
1382        hasNextPattern = null;
1383        saveState();
1384
1385        while (true) {
1386            if (getCompleteTokenInBuffer(pattern) != null) {
1387                matchValid = true;
1388                cacheResult(pattern);
1389                return revertState(true);
1390            }
1391            if (needInput)
1392                readInput();
1393            else
1394                return revertState(false);
1395        }
1396    }
1397
1398    /**
1399     * Returns the next token if it matches the specified pattern. This
1400     * method may block while waiting for input to scan, even if a previous
1401     * invocation of {@link #hasNext(Pattern)} returned <code>true</code>.
1402     * If the match is successful, the scanner advances past the input that
1403     * matched the pattern.
1404     *
1405     * @param pattern the pattern to scan for
1406     * @return the next token
1407     * @throws NoSuchElementException if no more tokens are available
1408     * @throws IllegalStateException if this scanner is closed
1409     */

1410    public String JavaDoc next(Pattern pattern) {
1411        ensureOpen();
1412        if (pattern == null)
1413            throw new NullPointerException JavaDoc();
1414
1415        // Did we already find this pattern?
1416
if (hasNextPattern == pattern)
1417            return getCachedResult();
1418        clearCaches();
1419
1420        // Search for the pattern
1421
while (true) {
1422            String JavaDoc token = getCompleteTokenInBuffer(pattern);
1423            if (token != null) {
1424                matchValid = true;
1425                skipped = false;
1426                return token;
1427            }
1428            if (needInput)
1429                readInput();
1430            else
1431                throwFor();
1432        }
1433    }
1434
1435    /**
1436     * Returns true if there is another line in the input of this scanner.
1437     * This method may block while waiting for input. The scanner does not
1438     * advance past any input.
1439     *
1440     * @return true if and only if this scanner has another line of input
1441     * @throws IllegalStateException if this scanner is closed
1442     */

1443    public boolean hasNextLine() {
1444        saveState();
1445        String JavaDoc result = findWithinHorizon(
1446            ".*("+LINE_SEPARATOR_PATTERN+")|.+$", 0);
1447        revertState();
1448        return (result != null);
1449    }
1450
1451    /**
1452     * Advances this scanner past the current line and returns the input
1453     * that was skipped.
1454     *
1455     * This method returns the rest of the current line, excluding any line
1456     * separator at the end. The position is set to the beginning of the next
1457     * line.
1458     *
1459     * <p>Since this method continues to search through the input looking
1460     * for a line separator, it may buffer all of the input searching for
1461     * the line to skip if no line separators are present.
1462     *
1463     * @return the line that was skipped
1464     * @throws NoSuchElementException if no line was found
1465     * @throws IllegalStateException if this scanner is closed
1466     */

1467    public String JavaDoc nextLine() {
1468        String JavaDoc result = findWithinHorizon(
1469            ".*("+LINE_SEPARATOR_PATTERN+")|.+$", 0);
1470        if (result == null)
1471            throw new NoSuchElementException JavaDoc("No line found");
1472        MatchResult mr = this.match();
1473        String JavaDoc lineSep = mr.group(1);
1474        if (lineSep != null)
1475            result = result.substring(0, result.length() - lineSep.length());
1476        if (result == null)
1477            throw new NoSuchElementException JavaDoc();
1478        else
1479            return result;
1480    }
1481
1482    // Public methods that ignore delimiters
1483

1484    /**
1485     * Attempts to find the next occurrence of a pattern constructed from the
1486     * specified string, ignoring delimiters.
1487     *
1488     * <p>An invocation of this method of the form <tt>findInLine(pattern)</tt>
1489     * behaves in exactly the same way as the invocation
1490     * <tt>findInLine(Pattern.compile(pattern))</tt>.
1491     *
1492     * @param pattern a string specifying the pattern to search for
1493     * @return the text that matched the specified pattern
1494     * @throws IllegalStateException if this scanner is closed
1495     */

1496    public String JavaDoc findInLine(String JavaDoc pattern) {
1497        return findInLine(patternCache.forName(pattern));
1498    }
1499
1500    /**
1501     * Attempts to find the next occurrence of the specified pattern ignoring
1502     * delimiters. If the pattern is found before the next line separator, the
1503     * scanner advances past the input that matched and returns the string that
1504     * matched the pattern.
1505     * If no such pattern is detected in the input up to the next line
1506     * separator, then <code>null</code> is returned and the scanner's
1507     * position is unchanged. This method may block waiting for input that
1508     * matches the pattern.
1509     *
1510     * <p>Since this method continues to search through the input looking
1511     * for the specified pattern, it may buffer all of the input searching for
1512     * the desired token if no line separators are present.
1513     *
1514     * @param pattern the pattern to scan for
1515     * @return the text that matched the specified pattern
1516     * @throws IllegalStateException if this scanner is closed
1517     */

1518    public String JavaDoc findInLine(Pattern pattern) {
1519        ensureOpen();
1520        if (pattern == null)
1521            throw new NullPointerException JavaDoc();
1522        clearCaches();
1523
1524        // Expand buffer to include the next newline or end of input
1525
int endPosition = 0;
1526        saveState();
1527        while (true) {
1528            String JavaDoc token = findPatternInBuffer(separatorPattern(), 0);
1529            if (token != null) {
1530                endPosition = matcher.start();
1531                break; // up to next newline
1532
}
1533            if (needInput) {
1534                readInput();
1535            } else {
1536                endPosition = buf.limit();
1537                break; // up to end of input
1538
}
1539        }
1540        revertState();
1541        int horizonForLine = endPosition - position;
1542
1543        // Search for the pattern
1544
return findWithinHorizon(pattern, horizonForLine);
1545    }
1546
1547    /**
1548     * Attempts to find the next occurrence of a pattern constructed from the
1549     * specified string, ignoring delimiters.
1550     *
1551     * <p>An invocation of this method of the form
1552     * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as
1553     * the invocation
1554     * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>.
1555     *
1556     * @param pattern a string specifying the pattern to search for
1557     * @return the text that matched the specified pattern
1558     * @throws IllegalStateException if this scanner is closed
1559     * @throws IllegalArgumentException if horizon is negative
1560     */

1561    public String JavaDoc findWithinHorizon(String JavaDoc pattern, int horizon) {
1562        return findWithinHorizon(patternCache.forName(pattern), horizon);
1563    }
1564
1565    /**
1566     * Attempts to find the next occurrence of the specified pattern.
1567     *
1568     * <p>This method searches through the input up to the specified
1569     * search horizon, ignoring delimiters. If the pattern is found the
1570     * scanner advances past the input that matched and returns the string
1571     * that matched the pattern. If no such pattern is detected then the
1572     * null is returned and the scanner's position remains unchanged. This
1573     * method may block waiting for input that matches the pattern.
1574     *
1575     * <p>A scanner will never search more than <code>horizon</code> code
1576     * points beyond its current position. Note that a match may be clipped
1577     * by the horizon; that is, an arbitrary match result may have been
1578     * different if the horizon had been larger. The scanner treats the
1579     * horizon as a transparent, non-anchoring bound (see {@link
1580     * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}).
1581     *
1582     * <p>If horizon is <code>0</code>, then the horizon is ignored and
1583     * this method continues to search through the input looking for the
1584     * specified pattern without bound. In this case it may buffer all of
1585     * the input searching for the pattern.
1586     *
1587     * <p>If horizon is negative, then an IllegalArgumentException is
1588     * thrown.
1589     *
1590     * @param pattern the pattern to scan for
1591     * @return the text that matched the specified pattern
1592     * @throws IllegalStateException if this scanner is closed
1593     * @throws IllegalArgumentException if horizon is negative
1594     */

1595    public String JavaDoc findWithinHorizon(Pattern pattern, int horizon) {
1596        ensureOpen();
1597        if (pattern == null)
1598            throw new NullPointerException JavaDoc();
1599        if (horizon < 0)
1600            throw new IllegalArgumentException JavaDoc("horizon < 0");
1601        clearCaches();
1602
1603        // Search for the pattern
1604
while (true) {
1605            String JavaDoc token = findPatternInBuffer(pattern, horizon);
1606            if (token != null) {
1607                matchValid = true;
1608                return token;
1609            }
1610            if (needInput)
1611                readInput();
1612            else
1613                break; // up to end of input
1614
}
1615        return null;
1616    }
1617
1618    /**
1619     * Skips input that matches the specified pattern, ignoring delimiters.
1620     * This method will skip input if an anchored match of the specified
1621     * pattern succeeds.
1622     *
1623     * <p>If a match to the specified pattern is not found at the
1624     * current position, then no input is skipped and a
1625     * <tt>NoSuchElementException</tt> is thrown.
1626     *
1627     * <p>Since this method seeks to match the specified pattern starting at
1628     * the scanner's current position, patterns that can match a lot of
1629     * input (".*", for example) may cause the scanner to buffer a large
1630     * amount of input.
1631     *
1632     * <p>Note that it is possible to skip something without risking a
1633     * <code>NoSuchElementException</code> by using a pattern that can
1634     * match nothing, e.g., <code>sc.skip("[ \t]*")</code>.
1635     *
1636     * @param pattern a string specifying the pattern to skip over
1637     * @return this scanner
1638     * @throws NoSuchElementException if the specified pattern is not found
1639     * @throws IllegalStateException if this scanner is closed
1640     */

1641    public Scanner JavaDoc skip(Pattern pattern) {
1642        ensureOpen();
1643        if (pattern == null)
1644            throw new NullPointerException JavaDoc();
1645        clearCaches();
1646
1647        // Search for the pattern
1648
while (true) {
1649            String JavaDoc token = matchPatternInBuffer(pattern);
1650            if (token != null) {
1651                matchValid = true;
1652                position = matcher.end();
1653                return this;
1654            }
1655            if (needInput)
1656                readInput();
1657            else
1658                throw new NoSuchElementException JavaDoc();
1659        }
1660    }
1661
1662    /**
1663     * Skips input that matches a pattern constructed from the specified
1664     * string.
1665     *
1666     * <p> An invocation of this method of the form <tt>skip(pattern)</tt>
1667     * behaves in exactly the same way as the invocation
1668     * <tt>skip(Pattern.compile(pattern))</tt>.
1669     *
1670     * @param pattern a string specifying the pattern to skip over
1671     * @return this scanner
1672     * @throws IllegalStateException if this scanner is closed
1673     */

1674    public Scanner JavaDoc skip(String JavaDoc pattern) {
1675        return skip(patternCache.forName(pattern));
1676    }
1677
1678    // Convenience methods for scanning primitives
1679

1680    /**
1681     * Returns true if the next token in this scanner's input can be
1682     * interpreted as a boolean value using a case insensitive pattern
1683     * created from the string "true|false". The scanner does not
1684     * advance past the input that matched.
1685     *
1686     * @return true if and only if this scanner's next token is a valid
1687     * boolean value
1688     * @throws IllegalStateException if this scanner is closed
1689     */

1690    public boolean hasNextBoolean() {
1691        return hasNext(boolPattern());
1692    }
1693
1694    /**
1695     * Scans the next token of the input into a boolean value and returns
1696     * that value. This method will throw <code>InputMismatchException</code>
1697     * if the next token cannot be translated into a valid boolean value.
1698     * If the match is successful, the scanner advances past the input that
1699     * matched.
1700     *
1701     * @return the boolean scanned from the input
1702     * @throws InputMismatchException if the next token is not a valid boolean
1703     * @throws NoSuchElementException if input is exhausted
1704     * @throws IllegalStateException if this scanner is closed
1705     */

1706    public boolean nextBoolean() {
1707        clearCaches();
1708        return Boolean.parseBoolean(next(boolPattern()));
1709    }
1710
1711    /**
1712     * Returns true if the next token in this scanner's input can be
1713     * interpreted as a byte value in the default radix using the
1714     * {@link #nextByte} method. The scanner does not advance past any input.
1715     *
1716     * @return true if and only if this scanner's next token is a valid
1717     * byte value
1718     * @throws IllegalStateException if this scanner is closed
1719     */

1720    public boolean hasNextByte() {
1721        return hasNextByte(defaultRadix);
1722    }
1723
1724    /**
1725     * Returns true if the next token in this scanner's input can be
1726     * interpreted as a byte value in the specified radix using the
1727     * {@link #nextByte} method. The scanner does not advance past any input.
1728     *
1729     * @param radix the radix used to interpret the token as a byte value
1730     * @return true if and only if this scanner's next token is a valid
1731     * byte value
1732     * @throws IllegalStateException if this scanner is closed
1733     */

1734    public boolean hasNextByte(int radix) {
1735        setRadix(radix);
1736        boolean result = hasNext(integerPattern());
1737        if (result) { // Cache it
1738
try {
1739                String JavaDoc s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1740                    processIntegerToken(hasNextResult) :
1741                    hasNextResult;
1742                typeCache = Byte.parseByte(s, radix);
1743            } catch (NumberFormatException JavaDoc nfe) {
1744                result = false;
1745            }
1746        }
1747        return result;
1748    }
1749
1750    /**
1751     * Scans the next token of the input as a <tt>byte</tt>.
1752     *
1753     * <p> An invocation of this method of the form
1754     * <tt>nextByte()</tt> behaves in exactly the same way as the
1755     * invocation <tt>nextByte(radix)</tt>, where <code>radix</code>
1756     * is the default radix of this scanner.
1757     *
1758     * @return the <tt>byte</tt> scanned from the input
1759     * @throws InputMismatchException
1760     * if the next token does not match the <i>Integer</i>
1761     * regular expression, or is out of range
1762     * @throws NoSuchElementException if input is exhausted
1763     * @throws IllegalStateException if this scanner is closed
1764     */

1765    public byte nextByte() {
1766         return nextByte(defaultRadix);
1767    }
1768
1769    /**
1770     * Scans the next token of the input as a <tt>byte</tt>.
1771     * This method will throw <code>InputMismatchException</code>
1772     * if the next token cannot be translated into a valid byte value as
1773     * described below. If the translation is successful, the scanner advances
1774     * past the input that matched.
1775     *
1776     * <p> If the next token matches the <a
1777     * HREF="#Integer-regex"><i>Integer</i></a> regular expression defined
1778     * above then the token is converted into a <tt>byte</tt> value as if by
1779     * removing all locale specific prefixes, group separators, and locale
1780     * specific suffixes, then mapping non-ASCII digits into ASCII
1781     * digits via {@link Character#digit Character.digit}, prepending a
1782     * negative sign (-) if the locale specific negative prefixes and suffixes
1783     * were present, and passing the resulting string to
1784     * {@link Byte#parseByte(String, int) Byte.parseByte} with the
1785     * specified radix.
1786     *
1787     * @param radix the radix used to interpret the token as a byte value
1788     * @return the <tt>byte</tt> scanned from the input
1789     * @throws InputMismatchException
1790     * if the next token does not match the <i>Integer</i>
1791     * regular expression, or is out of range
1792     * @throws NoSuchElementException if input is exhausted
1793     * @throws IllegalStateException if this scanner is closed
1794     */

1795    public byte nextByte(int radix) {
1796        // Check cached result
1797
if ((typeCache != null) && (typeCache instanceof Byte JavaDoc)) {
1798            byte val = ((Byte JavaDoc)typeCache).byteValue();
1799            useTypeCache();
1800            return val;
1801        }
1802        setRadix(radix);
1803        clearCaches();
1804        // Search for next byte
1805
try {
1806            String JavaDoc s = next(integerPattern());
1807            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
1808                s = processIntegerToken(s);
1809            return Byte.parseByte(s, radix);
1810        } catch (NumberFormatException JavaDoc nfe) {
1811            position = matcher.start(); // don't skip bad token
1812
throw new InputMismatchException JavaDoc(nfe.getMessage());
1813        }
1814    }
1815
1816    /**
1817     * Returns true if the next token in this scanner's input can be
1818     * interpreted as a short value in the default radix using the
1819     * {@link #nextShort} method. The scanner does not advance past any input.
1820     *
1821     * @return true if and only if this scanner's next token is a valid
1822     * short value in the default radix
1823     * @throws IllegalStateException if this scanner is closed
1824     */

1825    public boolean hasNextShort() {
1826        return hasNextShort(defaultRadix);
1827    }
1828
1829    /**
1830     * Returns true if the next token in this scanner's input can be
1831     * interpreted as a short value in the specified radix using the
1832     * {@link #nextShort} method. The scanner does not advance past any input.
1833     *
1834     * @param radix the radix used to interpret the token as a short value
1835     * @return true if and only if this scanner's next token is a valid
1836     * short value in the specified radix
1837     * @throws IllegalStateException if this scanner is closed
1838     */

1839    public boolean hasNextShort(int radix) {
1840        setRadix(radix);
1841        boolean result = hasNext(integerPattern());
1842        if (result) { // Cache it
1843
try {
1844                String JavaDoc s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1845                    processIntegerToken(hasNextResult) :
1846                    hasNextResult;
1847                typeCache = Short.parseShort(s, radix);
1848            } catch (NumberFormatException JavaDoc nfe) {
1849                result = false;
1850            }
1851        }
1852        return result;
1853    }
1854
1855    /**
1856     * Scans the next token of the input as a <tt>short</tt>.
1857     *
1858     * <p> An invocation of this method of the form
1859     * <tt>nextShort()</tt> behaves in exactly the same way as the
1860     * invocation <tt>nextShort(radix)</tt>, where <code>radix</code>
1861     * is the default radix of this scanner.
1862     *
1863     * @return the <tt>short</tt> scanned from the input
1864     * @throws InputMismatchException
1865     * if the next token does not match the <i>Integer</i>
1866     * regular expression, or is out of range
1867     * @throws NoSuchElementException if input is exhausted
1868     * @throws IllegalStateException if this scanner is closed
1869     */

1870    public short nextShort() {
1871        return nextShort(defaultRadix);
1872    }
1873
1874    /**
1875     * Scans the next token of the input as a <tt>short</tt>.
1876     * This method will throw <code>InputMismatchException</code>
1877     * if the next token cannot be translated into a valid short value as
1878     * described below. If the translation is successful, the scanner advances
1879     * past the input that matched.
1880     *
1881     * <p> If the next token matches the <a
1882     * HREF="#Integer-regex"><i>Integer</i></a> regular expression defined
1883     * above then the token is converted into a <tt>short</tt> value as if by
1884     * removing all locale specific prefixes, group separators, and locale
1885     * specific suffixes, then mapping non-ASCII digits into ASCII
1886     * digits via {@link Character#digit Character.digit}, prepending a
1887     * negative sign (-) if the locale specific negative prefixes and suffixes
1888     * were present, and passing the resulting string to
1889     * {@link Short#parseShort(String, int) Short.parseShort} with the
1890     * specified radix.
1891     *
1892     * @param radix the radix used to interpret the token as a short value
1893     * @return the <tt>short</tt> scanned from the input
1894     * @throws InputMismatchException
1895     * if the next token does not match the <i>Integer</i>
1896     * regular expression, or is out of range
1897     * @throws NoSuchElementException if input is exhausted
1898     * @throws IllegalStateException if this scanner is closed
1899     */

1900    public short nextShort(int radix) {
1901        // Check cached result
1902
if ((typeCache != null) && (typeCache instanceof Short JavaDoc)) {
1903            short val = ((Short JavaDoc)typeCache).shortValue();
1904            useTypeCache();
1905            return val;
1906        }
1907        setRadix(radix);
1908        clearCaches();
1909        // Search for next short
1910
try {
1911            String JavaDoc s = next(integerPattern());
1912            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
1913                s = processIntegerToken(s);
1914            return Short.parseShort(s, radix);
1915        } catch (NumberFormatException JavaDoc nfe) {
1916            position = matcher.start(); // don't skip bad token
1917
throw new InputMismatchException JavaDoc(nfe.getMessage());
1918        }
1919    }
1920
1921    /**
1922     * Returns true if the next token in this scanner's input can be
1923     * interpreted as an int value in the default radix using the
1924     * {@link #nextInt} method. The scanner does not advance past any input.
1925     *
1926     * @return true if and only if this scanner's next token is a valid
1927     * int value
1928     * @throws IllegalStateException if this scanner is closed
1929     */

1930    public boolean hasNextInt() {
1931        return hasNextInt(defaultRadix);
1932    }
1933
1934    /**
1935     * Returns true if the next token in this scanner's input can be
1936     * interpreted as an int value in the specified radix using the
1937     * {@link #nextInt} method. The scanner does not advance past any input.
1938     *
1939     * @param radix the radix used to interpret the token as an int value
1940     * @return true if and only if this scanner's next token is a valid
1941     * int value
1942     * @throws IllegalStateException if this scanner is closed
1943     */

1944    public boolean hasNextInt(int radix) {
1945        setRadix(radix);
1946        boolean result = hasNext(integerPattern());
1947        if (result) { // Cache it
1948
try {
1949                String JavaDoc s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1950                    processIntegerToken(hasNextResult) :
1951                    hasNextResult;
1952                typeCache = Integer.parseInt(s, radix);
1953            } catch (NumberFormatException JavaDoc nfe) {
1954                result = false;
1955            }
1956        }
1957        return result;
1958    }
1959
1960    /**
1961     * The integer token must be stripped of prefixes, group separators,
1962     * and suffixes, non ascii digits must be converted into ascii digits
1963     * before parse will accept it.
1964     */

1965    private String JavaDoc processIntegerToken(String JavaDoc token) {
1966        String JavaDoc result = token.replaceAll(""+groupSeparator, "");
1967        boolean isNegative = false;
1968        int preLen = negativePrefix.length();
1969        if ((preLen > 0) && result.startsWith(negativePrefix)) {
1970            isNegative = true;
1971            result = result.substring(preLen);
1972        }
1973        int sufLen = negativeSuffix.length();
1974        if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
1975            isNegative = true;
1976            result = result.substring(result.length() - sufLen,
1977                                      result.length());
1978        }
1979        if (isNegative)
1980            result = "-" + result;
1981        return result;
1982    }
1983
1984    /**
1985     * Scans the next token of the input as an <tt>int</tt>.
1986     *
1987     * <p> An invocation of this method of the form
1988     * <tt>nextInt()</tt> behaves in exactly the same way as the
1989     * invocation <tt>nextInt(radix)</tt>, where <code>radix</code>
1990     * is the default radix of this scanner.
1991     *
1992     * @return the <tt>int</tt> scanned from the input
1993     * @throws InputMismatchException
1994     * if the next token does not match the <i>Integer</i>
1995     * regular expression, or is out of range
1996     * @throws NoSuchElementException if input is exhausted
1997     * @throws IllegalStateException if this scanner is closed
1998     */

1999    public int nextInt() {
2000        return nextInt(defaultRadix);
2001    }
2002
2003    /**
2004     * Scans the next token of the input as an <tt>int</tt>.
2005     * This method will throw <code>InputMismatchException</code>
2006     * if the next token cannot be translated into a valid int value as
2007     * described below. If the translation is successful, the scanner advances
2008     * past the input that matched.
2009     *
2010     * <p> If the next token matches the <a
2011     * HREF="#Integer-regex"><i>Integer</i></a> regular expression defined
2012     * above then the token is converted into an <tt>int</tt> value as if by
2013     * removing all locale specific prefixes, group separators, and locale
2014     * specific suffixes, then mapping non-ASCII digits into ASCII
2015     * digits via {@link Character#digit Character.digit}, prepending a
2016     * negative sign (-) if the locale specific negative prefixes and suffixes
2017     * were present, and passing the resulting string to
2018     * {@link Integer#parseInt(String, int) Integer.parseInt} with the
2019     * specified radix.
2020     *
2021     * @param radix the radix used to interpret the token as an int value
2022     * @return the <tt>int</tt> scanned from the input
2023     * @throws InputMismatchException
2024     * if the next token does not match the <i>Integer</i>
2025     * regular expression, or is out of range
2026     * @throws NoSuchElementException if input is exhausted
2027     * @throws IllegalStateException if this scanner is closed
2028     */

2029    public int nextInt(int radix) {
2030        // Check cached result
2031
if ((typeCache != null) && (typeCache instanceof Integer JavaDoc)) {
2032            int val = ((Integer JavaDoc)typeCache).intValue();
2033            useTypeCache();
2034            return val;
2035        }
2036        setRadix(radix);
2037        clearCaches();
2038        // Search for next int
2039
try {
2040            String JavaDoc s = next(integerPattern());
2041            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2042                s = processIntegerToken(s);
2043            return Integer.parseInt(s, radix);
2044        } catch (NumberFormatException JavaDoc nfe) {
2045            position = matcher.start(); // don't skip bad token
2046
throw new InputMismatchException JavaDoc(nfe.getMessage());
2047        }
2048    }
2049
2050    /**
2051     * Returns true if the next token in this scanner's input can be
2052     * interpreted as a long value in the default radix using the
2053     * {@link #nextLong} method. The scanner does not advance past any input.
2054     *
2055     * @return true if and only if this scanner's next token is a valid
2056     * long value
2057     * @throws IllegalStateException if this scanner is closed
2058     */

2059    public boolean hasNextLong() {
2060        return hasNextLong(defaultRadix);
2061    }
2062
2063    /**
2064     * Returns true if the next token in this scanner's input can be
2065     * interpreted as a long value in the specified radix using the
2066     * {@link #nextLong} method. The scanner does not advance past any input.
2067     *
2068     * @param radix the radix used to interpret the token as a long value
2069     * @return true if and only if this scanner's next token is a valid
2070     * long value
2071     * @throws IllegalStateException if this scanner is closed
2072     */

2073    public boolean hasNextLong(int radix) {
2074        setRadix(radix);
2075        boolean result = hasNext(integerPattern());
2076        if (result) { // Cache it
2077
try {
2078                String JavaDoc s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2079                    processIntegerToken(hasNextResult) :
2080                    hasNextResult;
2081                typeCache = Long.parseLong(s, radix);
2082            } catch (NumberFormatException JavaDoc nfe) {
2083                result = false;
2084            }
2085        }
2086        return result;
2087    }
2088
2089    /**
2090     * Scans the next token of the input as a <tt>long</tt>.
2091     *
2092     * <p> An invocation of this method of the form
2093     * <tt>nextLong()</tt> behaves in exactly the same way as the
2094     * invocation <tt>nextLong(radix)</tt>, where <code>radix</code>
2095     * is the default radix of this scanner.
2096     *
2097     * @return the <tt>long</tt> scanned from the input
2098     * @throws InputMismatchException
2099     * if the next token does not match the <i>Integer</i>
2100     * regular expression, or is out of range
2101     * @throws NoSuchElementException if input is exhausted
2102     * @throws IllegalStateException if this scanner is closed
2103     */

2104    public long nextLong() {
2105        return nextLong(defaultRadix);
2106    }
2107
2108    /**
2109     * Scans the next token of the input as a <tt>long</tt>.
2110     * This method will throw <code>InputMismatchException</code>
2111     * if the next token cannot be translated into a valid long value as
2112     * described below. If the translation is successful, the scanner advances
2113     * past the input that matched.
2114     *
2115     * <p> If the next token matches the <a
2116     * HREF="#Integer-regex"><i>Integer</i></a> regular expression defined
2117     * above then the token is converted into an <tt>long</tt> value as if by
2118     * removing all locale specific prefixes, group separators, and locale
2119     * specific suffixes, then mapping non-ASCII digits into ASCII
2120     * digits via {@link Character#digit Character.digit}, prepending a
2121     * negative sign (-) if the locale specific negative prefixes and suffixes
2122     * were present, and passing the resulting string to
2123     * {@link Long#parseLong(String, int) Long.parseLong} with the
2124     * specified radix.
2125     *
2126     * @param radix the radix used to interpret the token as an int value
2127     * @return the <tt>long</tt> scanned from the input
2128     * @throws InputMismatchException
2129     * if the next token does not match the <i>Integer</i>
2130     * regular expression, or is out of range
2131     * @throws NoSuchElementException if input is exhausted
2132     * @throws IllegalStateException if this scanner is closed
2133     */

2134    public long nextLong(int radix) {
2135        // Check cached result
2136
if ((typeCache != null) && (typeCache instanceof Long JavaDoc)) {
2137            long val = ((Long JavaDoc)typeCache).longValue();
2138            useTypeCache();
2139            return val;
2140        }
2141        setRadix(radix);
2142        clearCaches();
2143        try {
2144            String JavaDoc s = next(integerPattern());
2145            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2146                s = processIntegerToken(s);
2147            return Long.parseLong(s, radix);
2148        } catch (NumberFormatException JavaDoc nfe) {
2149            position = matcher.start(); // don't skip bad token
2150
throw new InputMismatchException JavaDoc(nfe.getMessage());
2151        }
2152    }
2153
2154    /**
2155     * The float token must be stripped of prefixes, group separators,
2156     * and suffixes, non ascii digits must be converted into ascii digits
2157     * before parseFloat will accept it.
2158     *
2159     * If there are non-ascii digits in the token these digits must
2160     * be processed before the token is passed to parseFloat.
2161     */

2162    private String JavaDoc processFloatToken(String JavaDoc token) {
2163        String JavaDoc result = token.replaceAll(groupSeparator, "");
2164        if (!decimalSeparator.equals("\\."))
2165            result = result.replaceAll(decimalSeparator, ".");
2166        boolean isNegative = false;
2167        int preLen = negativePrefix.length();
2168        if ((preLen > 0) && result.startsWith(negativePrefix)) {
2169            isNegative = true;
2170            result = result.substring(preLen);
2171        }
2172        int sufLen = negativeSuffix.length();
2173        if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
2174            isNegative = true;
2175            result = result.substring(result.length() - sufLen,
2176                                      result.length());
2177        }
2178        if (result.equals(nanString))
2179            result = "NaN";
2180        if (result.equals(infinityString))
2181            result = "Infinity";
2182        if (isNegative)
2183            result = "-" + result;
2184
2185        // Translate non-ASCII digits
2186
Matcher m = NON_ASCII_DIGIT.matcher(result);
2187        if (m.find()) {
2188            StringBuilder JavaDoc inASCII = new StringBuilder JavaDoc();
2189            for (int i=0; i<result.length(); i++) {
2190                char nextChar = result.charAt(i);
2191                if (Character.isDigit(nextChar)) {
2192                    int d = Character.digit(nextChar, 10);
2193                    if (d != -1)
2194                        inASCII.append(d);
2195                    else
2196                        inASCII.append(nextChar);
2197                } else {
2198                    inASCII.append(nextChar);
2199                }
2200            }
2201            result = inASCII.toString();
2202        }
2203
2204        return result;
2205    }
2206
2207    /**
2208     * Returns true if the next token in this scanner's input can be
2209     * interpreted as a float value using the {@link #nextFloat}
2210     * method. The scanner does not advance past any input.
2211     *
2212     * @return true if and only if this scanner's next token is a valid
2213     * float value
2214     * @throws IllegalStateException if this scanner is closed
2215     */

2216    public boolean hasNextFloat() {
2217        setRadix(10);
2218        boolean result = hasNext(floatPattern());
2219        if (result) { // Cache it
2220
try {
2221                String JavaDoc s = processFloatToken(hasNextResult);
2222                typeCache = Float.valueOf(Float.parseFloat(s));
2223            } catch (NumberFormatException JavaDoc nfe) {
2224                result = false;
2225            }
2226        }
2227        return result;
2228    }
2229
2230    /**
2231     * Scans the next token of the input as a <tt>float</tt>.
2232     * This method will throw <code>InputMismatchException</code>
2233     * if the next token cannot be translated into a valid float value as
2234     * described below. If the translation is successful, the scanner advances
2235     * past the input that matched.
2236     *
2237     * <p> If the next token matches the <a
2238     * HREF="#Float-regex"><i>Float</i></a> regular expression defined above
2239     * then the token is converted into a <tt>float</tt> value as if by
2240     * removing all locale specific prefixes, group separators, and locale
2241     * specific suffixes, then mapping non-ASCII digits into ASCII
2242     * digits via {@link Character#digit Character.digit}, prepending a
2243     * negative sign (-) if the locale specific negative prefixes and suffixes
2244     * were present, and passing the resulting string to
2245     * {@link Float#parseFloat Float.parseFloat}. If the token matches
2246     * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2247     * is passed to {@link Float#parseFloat(String) Float.parseFloat} as
2248     * appropriate.
2249     *
2250     * @return the <tt>float</tt> scanned from the input
2251     * @throws InputMismatchException
2252     * if the next token does not match the <i>Float</i>
2253     * regular expression, or is out of range
2254     * @throws NoSuchElementException if input is exhausted
2255     * @throws IllegalStateException if this scanner is closed
2256     */

2257    public float nextFloat() {
2258        // Check cached result
2259
if ((typeCache != null) && (typeCache instanceof Float JavaDoc)) {
2260            float val = ((Float JavaDoc)typeCache).floatValue();
2261            useTypeCache();
2262            return val;
2263        }
2264        setRadix(10);
2265        clearCaches();
2266        try {
2267            return Float.parseFloat(processFloatToken(next(floatPattern())));
2268        } catch (NumberFormatException JavaDoc nfe) {
2269            position = matcher.start(); // don't skip bad token
2270
throw new InputMismatchException JavaDoc(nfe.getMessage());
2271        }
2272    }
2273
2274    /**
2275     * Returns true if the next token in this scanner's input can be
2276     * interpreted as a double value using the {@link #nextDouble}
2277     * method. The scanner does not advance past any input.
2278     *
2279     * @return true if and only if this scanner's next token is a valid
2280     * double value
2281     * @throws IllegalStateException if this scanner is closed
2282     */

2283    public boolean hasNextDouble() {
2284        setRadix(10);
2285        boolean result = hasNext(floatPattern());
2286        if (result) { // Cache it
2287
try {
2288                String JavaDoc s = processFloatToken(hasNextResult);
2289                typeCache = Double.valueOf(Double.parseDouble(s));
2290            } catch (NumberFormatException JavaDoc nfe) {
2291                result = false;
2292            }
2293        }
2294        return result;
2295    }
2296
2297    /**
2298     * Scans the next token of the input as a <tt>double</tt>.
2299     * This method will throw <code>InputMismatchException</code>
2300     * if the next token cannot be translated into a valid double value.
2301     * If the translation is successful, the scanner advances past the input
2302     * that matched.
2303     *
2304     * <p> If the next token matches the <a
2305     * HREF="#Float-regex"><i>Float</i></a> regular expression defined above
2306     * then the token is converted into a <tt>double</tt> value as if by
2307     * removing all locale specific prefixes, group separators, and locale
2308     * specific suffixes, then mapping non-ASCII digits into ASCII
2309     * digits via {@link Character#digit Character.digit}, prepending a
2310     * negative sign (-) if the locale specific negative prefixes and suffixes
2311     * were present, and passing the resulting string to
2312     * {@link Double#parseDouble Double.parseDouble}. If the token matches
2313     * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2314     * is passed to {@link Double#parseDouble(String) Double.parseDouble} as
2315     * appropriate.
2316     *
2317     * @return the <tt>double</tt> scanned from the input
2318     * @throws InputMismatchException
2319     * if the next token does not match the <i>Float</i>
2320     * regular expression, or is out of range
2321     * @throws NoSuchElementException if the input is exhausted
2322     * @throws IllegalStateException if this scanner is closed
2323     */

2324    public double nextDouble() {
2325        // Check cached result
2326
if ((typeCache != null) && (typeCache instanceof Double JavaDoc)) {
2327            double val = ((Double JavaDoc)typeCache).doubleValue();
2328            useTypeCache();
2329            return val;
2330        }
2331        setRadix(10);
2332        clearCaches();
2333        // Search for next float
2334
try {
2335            return Double.parseDouble(processFloatToken(next(floatPattern())));
2336        } catch (NumberFormatException JavaDoc nfe) {
2337            position = matcher.start(); // don't skip bad token
2338
throw new InputMismatchException JavaDoc(nfe.getMessage());
2339        }
2340    }
2341
2342    // Convenience methods for scanning multi precision numbers
2343

2344    /**
2345     * Returns true if the next token in this scanner's input can be
2346     * interpreted as a <code>BigInteger</code> in the default radix using the
2347     * {@link #nextBigInteger} method. The scanner does not advance past any
2348     * input.
2349     *
2350     * @return true if and only if this scanner's next token is a valid
2351     * <code>BigInteger</code>
2352     * @throws IllegalStateException if this scanner is closed
2353     */

2354    public boolean hasNextBigInteger() {
2355        return hasNextBigInteger(defaultRadix);
2356    }
2357
2358    /**
2359     * Returns true if the next token in this scanner's input can be
2360     * interpreted as a <code>BigInteger</code> in the specified radix using
2361     * the {@link #nextBigInteger} method. The scanner does not advance past
2362     * any input.
2363     *
2364     * @param radix the radix used to interpret the token as an integer
2365     * @return true if and only if this scanner's next token is a valid
2366     * <code>BigInteger</code>
2367     * @throws IllegalStateException if this scanner is closed
2368     */

2369    public boolean hasNextBigInteger(int radix) {
2370        setRadix(radix);
2371        boolean result = hasNext(integerPattern());
2372        if (result) { // Cache it
2373
try {
2374                String JavaDoc s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2375                    processIntegerToken(hasNextResult) :
2376                    hasNextResult;
2377                typeCache = new BigInteger(s, radix);
2378            } catch (NumberFormatException JavaDoc nfe) {
2379                result = false;
2380            }
2381        }
2382        return result;
2383    }
2384
2385    /**
2386     * Scans the next token of the input as a {@link java.math.BigInteger
2387     * BigInteger}.
2388     *
2389     * <p> An invocation of this method of the form
2390     * <tt>nextBigInteger()</tt> behaves in exactly the same way as the
2391     * invocation <tt>nextBigInteger(radix)</tt>, where <code>radix</code>
2392     * is the default radix of this scanner.
2393     *
2394     * @return the <tt>BigInteger</tt> scanned from the input
2395     * @throws InputMismatchException
2396     * if the next token does not match the <i>Integer</i>
2397     * regular expression, or is out of range
2398     * @throws NoSuchElementException if the input is exhausted
2399     * @throws IllegalStateException if this scanner is closed
2400     */

2401    public BigInteger nextBigInteger() {
2402        return nextBigInteger(defaultRadix);
2403    }
2404
2405    /**
2406     * Scans the next token of the input as a {@link java.math.BigInteger
2407     * BigInteger}.
2408     *
2409     * <p> If the next token matches the <a
2410     * HREF="#Integer-regex"><i>Integer</i></a> regular expression defined
2411     * above then the token is converted into a <tt>BigInteger</tt> value as if
2412     * by removing all group separators, mapping non-ASCII digits into ASCII
2413     * digits via the {@link Character#digit Character.digit}, and passing the
2414     * resulting string to the {@link
2415     * java.math.BigInteger#BigInteger(java.lang.String)
2416     * BigInteger(String, int)} constructor with the specified radix.
2417     *
2418     * @param radix the radix used to interpret the token
2419     * @return the <tt>BigInteger</tt> scanned from the input
2420     * @throws InputMismatchException
2421     * if the next token does not match the <i>Integer</i>
2422     * regular expression, or is out of range
2423     * @throws NoSuchElementException if the input is exhausted
2424     * @throws IllegalStateException if this scanner is closed
2425     */

2426    public BigInteger nextBigInteger(int radix) {
2427        // Check cached result
2428
if ((typeCache != null) && (typeCache instanceof BigInteger)) {
2429            BigInteger val = (BigInteger)typeCache;
2430            useTypeCache();
2431            return val;
2432        }
2433        setRadix(radix);
2434        clearCaches();
2435        // Search for next int
2436
try {
2437            String JavaDoc s = next(integerPattern());
2438            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2439                s = processIntegerToken(s);
2440            return new BigInteger(s, radix);
2441        } catch (NumberFormatException JavaDoc nfe) {
2442            position = matcher.start(); // don't skip bad token
2443
throw new InputMismatchException JavaDoc(nfe.getMessage());
2444        }
2445    }
2446
2447    /**
2448     * Returns true if the next token in this scanner's input can be
2449     * interpreted as a <code>BigDecimal</code> using the
2450     * {@link #nextBigDecimal} method. The scanner does not advance past any
2451     * input.
2452     *
2453     * @return true if and only if this scanner's next token is a valid
2454     * <code>BigDecimal</code>
2455     * @throws IllegalStateException if this scanner is closed
2456     */

2457    public boolean hasNextBigDecimal() {
2458        setRadix(10);
2459        boolean result = hasNext(decimalPattern());
2460        if (result) { // Cache it
2461
try {
2462                String JavaDoc s = processFloatToken(hasNextResult);
2463                typeCache = new BigDecimal(s);
2464            } catch (NumberFormatException JavaDoc nfe) {
2465                result = false;
2466            }
2467        }
2468        return result;
2469    }
2470
2471    /**
2472     * Scans the next token of the input as a {@link java.math.BigDecimal
2473     * BigDecimal}.
2474     *
2475     * <p> If the next token matches the <a
2476     * HREF="#Decimal-regex"><i>Decimal</i></a> regular expression defined
2477     * above then the token is converted into a <tt>BigDecimal</tt> value as if
2478     * by removing all group separators, mapping non-ASCII digits into ASCII
2479     * digits via the {@link Character#digit Character.digit}, and passing the
2480     * resulting string to the {@link
2481     * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)}
2482     * constructor.
2483     *
2484     * @return the <tt>BigDecimal</tt> scanned from the input
2485     * @throws InputMismatchException
2486     * if the next token does not match the <i>Decimal</i>
2487     * regular expression, or is out of range
2488     * @throws NoSuchElementException if the input is exhausted
2489     * @throws IllegalStateException if this scanner is closed
2490     */

2491    public BigDecimal nextBigDecimal() {
2492        // Check cached result
2493
if ((typeCache != null) && (typeCache instanceof BigDecimal)) {
2494            BigDecimal val = (BigDecimal)typeCache;
2495            useTypeCache();
2496            return val;
2497        }
2498        setRadix(10);
2499        clearCaches();
2500        // Search for next float
2501
try {
2502            String JavaDoc s = processFloatToken(next(decimalPattern()));
2503            return new BigDecimal(s);
2504        } catch (NumberFormatException JavaDoc nfe) {
2505            position = matcher.start(); // don't skip bad token
2506
throw new InputMismatchException JavaDoc(nfe.getMessage());
2507        }
2508    }
2509}
2510
2511
Popular Tags