001 /* java.util.Scanner -- Parses primitive types and strings using regexps
002 Copyright (C) 2007 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038 package java.util;
039
040 import java.io.BufferedInputStream;
041 import java.io.File;
042 import java.io.FileInputStream;
043 import java.io.FileNotFoundException;
044 import java.io.IOException;
045 import java.io.InputStream;
046
047 import java.math.BigDecimal;
048 import java.math.BigInteger;
049
050 import java.nio.ByteBuffer;
051 import java.nio.CharBuffer;
052 import java.nio.channels.ReadableByteChannel;
053
054 import java.text.DecimalFormat;
055 import java.text.DecimalFormatSymbols;
056 import java.text.NumberFormat;
057 import java.text.ParseException;
058
059 import java.util.Iterator;
060 import java.util.Locale;
061 import java.util.regex.MatchResult;
062 import java.util.regex.Matcher;
063 import java.util.regex.Pattern;
064
065 /**
066 * @author E0327023 Hernadi Laszlo
067 */
068 public class Scanner
069 implements Iterator <String>
070 {
071 private static final String NOT_LONG = "\" is not a long"; //$NON-NLS-1$
072
073 private static final String ERR_PREFIX = "\""; //$NON-NLS-1$
074
075 private static final String NOT_INT = "\" is not an integer"; //$NON-NLS-1$
076
077 private static final String NOT_DOUBLE = "\" is not a double"; //$NON-NLS-1$
078
079 private static final String NOT_BYTE = "\" is not a byte"; //$NON-NLS-1$
080
081 private static final String NOT_BOOLEAN = "\" is not a boolean"; //$NON-NLS-1$
082
083 private static final String IS_NOT = "\" is not "; //$NON-NLS-1$
084
085 private static final String DEFAULT_PATTERN_S = "\\p{javaWhitespace}+"; //$NON-NLS-1$
086
087 private static final Pattern DEFAULT_PATTERN =
088 Pattern.compile (DEFAULT_PATTERN_S);
089
090 private static final String BIG_INTEGER = "BigInteger"; //$NON-NLS-1$
091
092 private final static String NEW_LINE =
093 System.getProperty ("line.separator");
094
095 private IOException lastIOException = null;
096
097 /**
098 * An InputStream source if a Constructor with an InputStream source is called, otherwise it
099 * stays <source> null </source>.
100 */
101 private InputStream bIS = null;
102
103 /**
104 * Length of the input Buffer, which is the maximum bytes to be read at once.
105 */
106 private final int MaxBufferLen = 1000000;
107
108 /**
109 * Minimum buffer length. If there are less chars in the Buffer than this value reading from
110 * source is tried.
111 */
112 private final int MIN_BUF_LEN = 100;
113
114 /**
115 * Maximum number of processed chars in the Buffer. If exeeded, all processed chars from the
116 * beginning of the Buffer will be discarded to save space. The bytes left are copyed into a new
117 * Buffer.
118 */
119 private final int MAX_PREFIX = 10000;
120
121 /**
122 * The Buffer which is used by the Matcher to find given patterns. It is filled up when matcher
123 * hits end or <code> MIN_BUF_LEN </code> is reached.
124 */
125 private String actBuffer = new String ();
126
127 /**
128 * The current radix to use by the methods getNextXXX and hasNextXXX.
129 */
130 private int currentRadix = 10;
131
132 /**
133 * The current locale.
134 *
135 * @see #useLocale(Locale)
136 * @see #locale()
137 */
138 private Locale actLocale = Locale.getDefault ();
139
140 /**
141 * The current pattern for the matcher.
142 */
143 private Pattern p = DEFAULT_PATTERN;
144
145 /**
146 * The current position in the Buffer, at which the next match should start.
147 */
148 private int actPos = 0;
149
150 /**
151 * A global buffer to save new allocations by reading from source.
152 */
153 private final byte[] tmpBuffer = new byte[this.MaxBufferLen];
154
155 /**
156 * The charsetName to use with the source.
157 */
158 private String charsetName = null;
159
160 /**
161 * The Matcher which is used.
162 */
163 private Matcher myMatcher = this.p.matcher (this.actBuffer);
164
165 /**
166 * The MatchResult is generated at each match, even if match() isn't called.
167 */
168 private MatchResult actResult = null;
169
170 /**
171 * A Readable source if a Constructor with a Readable source is called, otherwise it stays
172 * <source> null </source>.
173 */
174 private Readable readableSource = null;
175
176 /**
177 * A ReadableByteChannel source if a Constructor with a ReadableByteChannel source is called,
178 * otherwise it stays <source> null </source>.
179 */
180 private ReadableByteChannel rbcSource = null;
181
182 /**
183 * Indicates if the close() method was called.
184 */
185 private boolean isClosed = false;
186
187 /**
188 * For performance reasons the last Found is saved, if a hasNextXXX method was called.
189 */
190 private String lastFound = null;
191
192 private boolean lastFoundPresent = false;
193
194 private int lastNextPos = 0;
195
196 private int lastPatternHash = 0;
197
198 private int last_RegionStart = 0;
199
200 private int last_RegionEnd = 0;
201
202 private boolean last_anchor = false;
203
204 private boolean last_transparent = false;
205
206 private MatchResult lastResult = null;
207
208 /**
209 * To keep track of the current position in the stream for the toString method, each time
210 * processed chars are removed the amount is added to processedChars.
211 */
212 private int procesedChars = 0;
213
214 /**
215 * needInput is set <code> true </code> before a read method, and if there is no input it blocks
216 * and stays <code>true</code>. Right after a read it is set to <code>false</code>.
217 */
218 private boolean needInput = false;
219
220 private boolean skipped = false;
221
222 /**
223 * <code> {@link #doSkipp} </code> indicates that the found pattern belongs to the result. If
224 * <code> {@link #doSkipp} </code> is false the match result ends at the beginning of the match.
225 * In both cases the current position is set after the pattern, if the found pattern has to be
226 * removed, a nextXXX method is called.
227 */
228 private boolean doSkipp = false;
229
230 /**
231 * Indicates if the last match was valid or not.
232 */
233 private boolean matchValid = false;
234
235 private NumberFormat actFormat = NumberFormat.getInstance (this.actLocale);
236
237 private DecimalFormat df = (DecimalFormat) this.actFormat;
238
239 /**
240 * Indicates if current Locale should be used at the input.
241 */
242 private boolean useLocale = true;
243
244 private DecimalFormatSymbols dfs =
245 new DecimalFormatSymbols (this.actLocale);
246
247 /**
248 * Constructs a new Scanner with the given File as source.
249 * {@link #Scanner(InputStream, String)} is called with <code> null </code> as charsetName.
250 *
251 * @param source
252 * The File to use as source.
253 * @throws FileNotFoundException
254 * If the file is not found an Exception is thrown.
255 */
256 public Scanner (final File source) throws FileNotFoundException // TESTED
257 {
258 this (source, null);
259 }
260
261 /**
262 * Constructs a new Scanner with the given File as source. <br>
263 * {@link #Scanner(InputStream, String)} is called with the given charsetName.
264 *
265 * @param source
266 * The File to use as source.
267 * @param charsetName
268 * Current charset name of the file. If charsetName is null it behaves if it was not
269 * set.
270 * @throws FileNotFoundException
271 * If the file is not found an Exception is thrown.
272 */
273 public Scanner (final File source,
274 final String charsetName) throws FileNotFoundException
275 {
276 this (new FileInputStream (source), charsetName);
277 }
278
279 /**
280 * Constructs a new Scanner with the given inputStream. <br>
281 * {@link #Scanner(InputStream, String)} is called with <code> null </code> as charsetName.
282 *
283 * @param source
284 * The InputStream to use as source.
285 */
286 public Scanner (final InputStream source) // TESTED
287 {
288 this (source, null);
289 }
290
291 /**
292 * Constructs a new Scanner with the InputSream and a charsetName. Afterwards the Buffer is
293 * filled.
294 *
295 * @param source
296 * The InputStream to use as source.
297 * @param charsetName
298 * The charsetName to apply on the source's data.
299 */
300 public Scanner (final InputStream source, final String charsetName)
301 {
302 this.bIS = (new BufferedInputStream (source));
303 this.charsetName = charsetName;
304 myFillBuffer ();
305 }
306
307 /**
308 * Constructs a new Scanner with a Readable input as source.
309 *
310 * @param source
311 * The Readable to use as source.
312 */
313 public Scanner (final Readable source)
314 {
315 this.readableSource = source;
316 myFillBuffer ();
317 }
318
319 /**
320 * Constructs a new Scanner with a ReadableByteChannel as
321 * source. Therfore the {@link #Scanner(ReadableByteChannel,
322 * String)} is called with <code> null </code> as charsetName.
323 *
324 * @param source
325 * The ReadableByteChannel to use as source.
326 */
327 public Scanner (final ReadableByteChannel source)
328 {
329 this (source, null);
330 }
331
332 /**
333 * Constructs a new Scanner with a ReadableByteChannel as source and
334 * a given charsetName, which is to be applied on it. <br> It also
335 * initiates the main Buffer.
336 *
337 * @param source
338 * The ReadableByteChannel to use as source.
339 * @param charsetName
340 * The charsetName to be applied on the source.
341 */
342 public Scanner (final ReadableByteChannel source, final String charsetName)
343 {
344 this.charsetName = charsetName;
345 this.rbcSource = source;
346 myFillBuffer ();
347 }
348
349 /**
350 * Constructs a new Scanner using the given String as input only.
351 *
352 * @param source
353 * The whole String to be used as source.
354 */
355 public Scanner (final String source) // TESTED
356 {
357 this.actBuffer = new String (source);
358 this.myMatcher.reset (this.actBuffer);
359 }
360
361 /**
362 * Closes this Scanner. If an {@link IOException} occurs it is
363 * catched and is available under {@link #ioException()}.<br> After
364 * the Scanner is closed, all searches will lead to a {@link
365 * IllegalStateException}.
366 */
367 public void close ()
368 {
369 try
370 {
371 if (this.bIS != null)
372 this.bIS.close ();
373 if (this.rbcSource != null)
374 this.rbcSource.close ();
375 this.isClosed = true;
376 }
377 catch (IOException ioe)
378 {
379 this.lastIOException = ioe;
380 }
381 }
382
383 /**
384 * Returns the current delimiter.
385 *
386 * @return the current delimiter.
387 */
388 public Pattern delimiter () // TESTED
389 {
390 return this.p;
391 }
392
393 /**
394 * Tries to find the pattern in the current line.
395 *
396 * @param pattern The pattern which should be searched in the
397 * current line of the input.
398 * @throws NoSuchElementException
399 * If the pattern was not found.
400 * @return If the search was successful, the result or otherwise a
401 * {@link NoSuchElementException} is thrown.
402 */
403 public String findInLine (final Pattern pattern) throws NoSuchElementException // TESTED
404 {
405 String tmpStr = myNextLine (false);
406 return myFindPInStr (pattern, tmpStr, 0);
407 }
408
409 /**
410 * Compiles the given pattern into a {@link Pattern} and calls
411 * {@link #findInLine(Pattern)} with the compiled pattern and
412 * returns whatever it returns.
413 *
414 * @param pattern
415 * The pattern which should be matched in the input.
416 * @throws NoSuchElementException
417 * If the pattern was not found.
418 * @return The match in the current line.
419 */
420 public String findInLine (final String pattern) // TESTED
421 {
422 return findInLine (Pattern.compile (pattern));
423 }
424
425 /**
426 * Trys to match the pattern within the given horizon.
427 *
428 * @param pattern
429 * Pattern to search.
430 * @param horizon
431 * @return The result of the match.
432 * @throws IllegalArgumentException
433 * if the horizon is negative.
434 * @throws IllegalStateException
435 * if the Scanner is closed.
436 */
437 public String findWithinHorizon (final Pattern pattern, final int horizon)
438 throws IllegalArgumentException, IllegalStateException
439 {
440 if (horizon < 0)
441 {
442 throw new IllegalArgumentException (horizon + " is negative");
443 }
444
445 if (this.isClosed)
446 {
447 throw new IllegalStateException ("Scanner is closed");
448 }
449
450 // doSkipp is set true to get the matching patern together with the found String
451 this.doSkipp = true;
452 String rc = myFindPInStr (pattern, this.actBuffer, horizon);
453
454 if (rc != null)
455 {
456 this.actPos += rc.length ();
457 }
458
459 return rc;
460 }
461
462 /**
463 * Compile the pattern and call {@link #findWithinHorizon(Pattern,
464 * int)}.
465 *
466 * @param pattern
467 * Pattern to search.
468 * @param horizon
469 * @return The result of the match.
470 * @throws IllegalArgumentException
471 * if the horizon is negative.
472 * @throws IllegalStateException
473 * if the Scanner is closed.
474 */
475 public String findWithinHorizon (final String pattern, final int horizon)
476 throws IllegalArgumentException, IllegalStateException
477 {
478 return findWithinHorizon (Pattern.compile (pattern), horizon);
479 }
480
481 /**
482 * Checks if there is any next String using the current
483 * delimiter. Therefore the string must not be <code> null </code>
484 * and the length must be greater then 0. If a {@link
485 * NoSuchElementException} is thrown by the search method, it is
486 * catched and false is returned.
487 *
488 * @return <code> true </code> if there is any result using the current delimiter. This wouldn't
489 * lead to a {@link NoSuchElementException}.
490 * @throws IllegalStateException
491 * if the Scanner is closed.
492 */
493 public boolean hasNext () throws IllegalStateException // TESTED
494 {
495 String tmpStr = null;
496
497 try
498 {
499 tmpStr = myCoreNext (false, this.p);
500 }
501 catch (NoSuchElementException nf)
502 {
503 }
504
505 if (tmpStr == null || tmpStr.length () <= 0)
506 {
507 return false;
508 }
509 return true;
510 }
511
512 /**
513 * Searches the pattern in the next subString before the next
514 * current delimiter.
515 *
516 * @param pattern
517 * The pattern to search for.
518 * @return <code> true </code> if the pattern is found before the current delimiter.
519 * @throws IllegalStateException
520 * if the Scanner is closed.
521 */
522 public boolean hasNext (final Pattern pattern) throws IllegalStateException // TESTED
523 {
524 String tmpStr;
525
526 tmpStr = myNext (pattern, false);
527
528 if (tmpStr == null || tmpStr.length () <= 0)
529 {
530 return false;
531 }
532 return true;
533 }
534
535 /**
536 * Compiles the pattern to a {@link Pattern} and calls {@link
537 * #hasNext(Pattern)}.
538 *
539 * @see #hasNext(Pattern)
540 * @param pattern
541 * The pattern as string to search for.
542 * @return <code> true </code> if the pattern is found before the current delimiter.
543 * @throws IllegalStateException
544 * if the Scanner is closed.
545 */
546 public boolean hasNext (final String pattern) throws IllegalStateException // TESTED
547 {
548 return hasNext (Pattern.compile (pattern));
549 }
550
551 /**
552 * Checks if the string to the next delimiter can be interpreted as
553 * a BigDecimal number. <br> BigDecimal numbers are always tryed
554 * with radix 10.
555 *
556 * @see #nextBigDecimal()
557 * @return <code> true </code> if the next string is a BigDecimal number.
558 * @throws IllegalStateException
559 * if the Scanner is closed.
560 */
561 public boolean hasNextBigDecimal () throws IllegalStateException // TESTED
562 {
563 try
564 {
565 myBigDecimal (false);
566 return true;
567 }
568 catch (InputMismatchException nfe)
569 {
570 return false;
571 }
572 }
573
574 /**
575 * Checks if the string to the next delimiter can be interpreted as
576 * a BigInteger number. <br> Call {@link #hasNextBigInteger(int)}
577 * with the current radix.
578 *
579 * @see #nextBigInteger()
580 * @return <code> true </code> if the next string is a BigInteger number.
581 * @throws IllegalStateException
582 * if the Scanner is closed.
583 */
584 public boolean hasNextBigInteger () throws IllegalStateException // TESTED
585 {
586 return hasNextBigInteger (this.currentRadix);
587 }
588
589 /**
590 * Checks if the string to the next delimiter can be interpreted as
591 * a BigInteger number. <br>
592 *
593 * @param radix
594 * The radix to use for this check. The global radix of the Scanner will not be
595 * changed.
596 * @return <code> true </code> if the next string is a BigInteger number.
597 * @throws IllegalStateException
598 * if the Scanner is closed.
599 */
600 public boolean hasNextBigInteger (final int radix) throws
601 IllegalStateException
602 {
603 try
604 {
605 myNextBigInteger (radix, false, BIG_INTEGER);
606 return true;
607 }
608 catch (InputMismatchException ime)
609 {
610 return false;
611 }
612 }
613
614 /**
615 * Checks if the next string could be a boolean. The method handles
616 * the input not case sensitiv, so "true" and "TRUE" and even "tRuE"
617 * are <code> true </code>.
618 *
619 * @see #nextBoolean()
620 * @return Return <code> true </code> if the next string is a boolean.
621 * @throws IllegalStateException
622 * if the Scanner is closed.
623 */
624 public boolean hasNextBoolean () throws IllegalStateException // TESTED
625 {
626 try
627 {
628 myNextBoolean (false);
629 return true;
630 }
631 catch (InputMismatchException ime)
632 {
633 return false;
634 }
635 }
636
637 /**
638 * Checks if the string to the next delimiter can be interpreted as
639 * a byte number. <br> Calls {@link #hasNextByte(int)} with the
640 * current radix.
641 *
642 * @see #nextByte()
643 * @return <code> true </code> if the next string is a byte number.
644 * @throws IllegalStateException
645 * if the Scanner is closed.
646 */
647 public boolean hasNextByte () throws IllegalStateException // TESTED
648 {
649 return hasNextByte (this.currentRadix);
650 }
651
652 /**
653 * Checks if the string to the next delimiter can be interpreted as
654 * a byte number with the given radix. <br> To check, the private
655 * method {@link #myNextByte(int, boolean)} is called, and if no
656 * error occurs the next string could be a byte.
657 *
658 * @see #nextByte(int)
659 * @param radix The radix to use for this check. The global radix of
660 * the Scanner will not be changed.
661 * @return <code> true </code> if the next string is a byte number.
662 * @throws IllegalStateException
663 * if the Scanner is closed.
664 */
665 public boolean hasNextByte (final int radix) throws IllegalStateException
666 {
667 try
668 {
669 myNextByte (radix, false);
670 return true;
671 }
672 catch (InputMismatchException ime)
673 {
674 return false;
675 }
676 }
677
678 /**
679 * Checks if the string to the next delimiter can be interpreted as
680 * a double number. <br> To check, the private method {@link
681 * #myNextDouble(boolean)} is called, and if no error occurs the
682 * next string could be a double.
683 *
684 * @see #nextDouble()
685 * @return <code> true </code> if the next string is a double number.
686 * @throws IllegalStateException
687 * if the Scanner is closed.
688 */
689 public boolean hasNextDouble () throws IllegalStateException // TESTED
690 {
691 try
692 {
693 myNextDouble (false);
694 return true;
695 }
696 catch (InputMismatchException ime)
697 {
698 return false;
699 }
700 }
701
702 /**
703 * Checks if the string to the next delimiter can be interpreted as
704 * a double number. Because every float is a double this is
705 * checked.<br> To check, the private method {@link
706 * #myNextDouble(boolean)} is called, and if no error occurs the
707 * next string could be a double.
708 *
709 * @see #nextFloat()
710 * @return <code> true </code> if the next string is a double number.
711 * @throws IllegalStateException
712 * if the Scanner is closed.
713 */
714 public boolean hasNextFloat () throws IllegalStateException // TESTED
715 {
716 try
717 {
718 myNextDouble (false);
719 // myNextFloat(false);
720 return true;
721 }
722 catch (InputMismatchException ime)
723 {
724 return false;
725 }
726 }
727
728 /**
729 * Checks if the string to the next delimiter can be interpreted as
730 * an int number. <br> To check, the private method {@link
731 * #myNextInt(int, boolean)} is called, and if no error occurs the
732 * next string could be an int.
733 *
734 * @see #nextInt(int)
735 * @return <code> true </code> if the next string is an int number.
736 * @throws IllegalStateException
737 * if the Scanner is closed.
738 */
739 public boolean hasNextInt () throws IllegalStateException // TESTED
740 {
741 return hasNextInt (this.currentRadix);
742 }
743
744 /**
745 * Checks if the string to the next delimiter can be interpreted as
746 * an int number with the given radix. <br> To check, the private
747 * method {@link #myNextInt(int, boolean)} is called, and if no
748 * error occurs the next string could be an int.
749 *
750 * @see #nextInt(int)
751 * @param radix
752 * The radix to use for this check. The global radix of the Scanner will not be
753 * changed.
754 * @return <code> true </code> if the next string is an int number.
755 * @throws IllegalStateException
756 * if the Scanner is closed.
757 */
758 public boolean hasNextInt (final int radix) throws IllegalStateException
759 {
760 try
761 {
762 myNextInt (radix, false);
763 return true;
764 }
765 catch (InputMismatchException ime)
766 {
767 return false;
768 }
769 }
770
771 /**
772 * Checks if there is a current line, which ends at the next line
773 * break or the end of the input.
774 *
775 * @return <code> true </code> if there is a current line.
776 * @throws IllegalStateException
777 * if the Scanner is closed.
778 */
779 public boolean hasNextLine () throws IllegalStateException // TESTED
780 {
781 return (myNextLine (false) != null);
782 }
783
784 /**
785 * Checks if the string to the next delimiter can be interpreted as
786 * a long number. <br> To check, the private method {@link
787 * #myNextLong(int, boolean)} is called, and if no error occurs the
788 * next string could be a long.
789 *
790 * @see #nextLong()
791 * @return <code> true </code> if the next string is a long number.
792 * @throws IllegalStateException
793 * if the Scanner is closed.
794 */
795 public boolean hasNextLong () throws IllegalStateException // TESTED
796 {
797 return hasNextLong (this.currentRadix);
798 }
799
800 /**
801 * Checks if the string to the next delimiter can be interpreted as
802 * a long number with the given radix. <br> To check, the private
803 * method {@link #myNextLong(int, boolean)} is called, and if no
804 * error occurs the next string could be a long.
805 *
806 * @see #nextLong(int)
807 * @param radix
808 * The radix to use for this check. The global radix of the Scanner will not be
809 * changed.
810 * @return <code> true </code> if the next string is a long number.
811 * @throws IllegalStateException
812 * if the Scanner is closed.
813 */
814 public boolean hasNextLong (final int radix) throws IllegalStateException
815 {
816 try
817 {
818 myNextLong (radix, false);
819 return true;
820 }
821 catch (InputMismatchException ime)
822 {
823 return false;
824 }
825 }
826
827 /**
828 * Checks if the string to the next delimiter can be interpreted as
829 * a short number with the given radix. <br> To check, the private
830 * method {@link #myNextShort(int, boolean)} is called, and if no
831 * error occurs the next string could be a short.
832 *
833 * @see #nextShort(int)
834 * @return <code> true </code> if the next string is a short number.
835 * @throws IllegalStateException
836 * if the Scanner is closed.
837 */
838 public boolean hasNextShort () throws IllegalStateException // TESTED
839 {
840 return hasNextShort (this.currentRadix);
841 }
842
843 /**
844 * Checks if the string to the next delimiter can be interpreted as
845 * a short number. <br> To check, the private method {@link
846 * #myNextShort(int, boolean)} is called, and if no error occurs the
847 * next string could be a short.
848 *
849 * @see #nextShort(int)
850 * @param radix
851 * The radix to use for this check. The global radix of the Scanner will not be
852 * changed.
853 * @return <code> true </code> if the next string is a short number.
854 * @throws IllegalStateException
855 * if the Scanner is closed.
856 */
857 public boolean hasNextShort (final int radix) throws IllegalStateException
858 {
859 try
860 {
861 myNextShort (radix, false);
862 return true;
863 }
864 catch (InputMismatchException ime)
865 {
866 return false;
867 }
868 }
869
870 /**
871 * Returns the last {@link IOException} occured.
872 *
873 * @return Returns the last {@link IOException}.
874 */
875 public IOException ioException ()
876 {
877 return this.lastIOException;
878 }
879
880 /**
881 * Returns the current value of {@link #useLocale}. This is used to
882 * tell the Scanner if it should use the Locale format or just
883 * handle numbers of the default format.
884 *
885 * @see #setUseLocale(boolean)
886 * @return the useLoclae.
887 */
888 public boolean isUseLocale () // TESTED
889 {
890 return this.useLocale;
891 }
892
893 /**
894 * Returns the current Locale. It is initialized with {@link
895 * Locale#getDefault()}.
896 *
897 * @see #useLocale(Locale)
898 * @return Returns the current Locale.
899 */
900 public Locale locale () // TESTED
901 {
902 return this.actLocale;
903 }
904
905 /**
906 * Returns the last MatchResult found. This is updated after every
907 * successfully search.
908 *
909 * @return Returns the last {@link MatchResult} found.
910 */
911 public MatchResult match () // TESTED
912 {
913 return this.actResult;
914 }
915
916 /**
917 * Uses the current delimiter to find the next string in the
918 * buffer. If a string is found the current position is set after
919 * the delimiter, otherwise a {@link NoSuchElementException} is
920 * thrown. A successful match sets the matchResult.
921 *
922 * @see #match()
923 * @return Returns the next string of the buffer.
924 * @throws NoSuchElementException
925 * If no element was found an exception is thrown.
926 * @throws IllegalStateException
927 * If the Scanner is closed.
928 */
929 public String next () throws NoSuchElementException, IllegalStateException // TESTED
930 {
931 return myCoreNext (true, this.p);
932 }
933
934 /**
935 * Tries to match the buffer with the given pattern. The current
936 * delimiter will not be changed.
937 *
938 * @param pattern
939 * The pattern to match.
940 * @return Returns the next string matching the pattern.
941 * @throws NoSuchElementException
942 * If no element was found an exception is thrown.
943 * @throws IllegalStateException
944 * If the Scanner is closed.
945 */
946 public String next (final Pattern pattern) throws NoSuchElementException, IllegalStateException // TESTED
947 {
948 return myNext (pattern, true);
949 }
950
951 /**
952 * Tries to match the buffer with the given pattern. The current
953 * delimiter will not be changed. Calls the {@link #next(Pattern)}
954 * with the compiled pattern.
955 *
956 * @see #next(Pattern)
957 * @param pattern
958 * The pattern to match.
959 * @return Returns the next string matching the pattern.
960 * @throws NoSuchElementException
961 * If no element was found an exception is thrown.
962 * @throws IllegalStateException
963 * If the Scanner is closed.
964 */
965 public String next (final String pattern) throws NoSuchElementException, IllegalStateException // TESTED
966 {
967 return next (Pattern.compile (pattern));
968 }
969
970 /**
971 * Tries to interpret the next string as a BigDecimal value.
972 *
973 * @return Returns the BigDecimal value of the next string.
974 * @throws NoSuchElementException
975 * If no string is found or the string is not a BigDecimal.
976 * @throws IllegalStateException
977 * If the Scanner is closed.
978 */
979 public BigDecimal nextBigDecimal () throws NoSuchElementException, IllegalStateException // TESTED
980 {
981 return myBigDecimal (true);
982 }
983
984 /**
985 * Tries to interpret the next string as a BigInteger value. Call
986 * {@link #nextBigInteger(int)} with the current radix as parameter,
987 * and return the value.
988 *
989 * @see #nextBigInteger(int)
990 * @return Returns the BigInteger value of the next string.
991 * @throws NoSuchElementException
992 * If no string is found or the string is not a BigInteger.
993 * @throws IllegalStateException
994 * If the Scanner is closed.
995 */
996 public BigInteger nextBigInteger () throws NoSuchElementException, IllegalStateException // TESTED
997 {
998 return nextBigInteger (this.currentRadix);
999 }
1000
1001 /**
1002 * Tries to interpret the next string as a BigInteger value with the
1003 * given radix.
1004 *
1005 * @param radix
1006 * The radix to be used for this BigInteger. The current radix of the Scanner is not
1007 * changed.
1008 * @return Returns the BigInteger value of the next string.
1009 * @throws NoSuchElementException
1010 * If no string is found or the string is not a BigInteger.
1011 * @throws IllegalStateException
1012 * If the Scanner is closed.
1013 */
1014 public BigInteger nextBigInteger (final int radix) throws
1015 NoSuchElementException, IllegalStateException
1016 {
1017 return myNextBigInteger (radix, true, BIG_INTEGER);
1018 }
1019
1020 /**
1021 * Tries to interpret the next string to the delimiter as a boolean
1022 * value, ignoring case.
1023 *
1024 * @return Returns the boolean value of the next matching string or throws an exception.
1025 * @throws NoSuchElementException
1026 * If no string is found or the string is not a boolean.
1027 * @throws IllegalStateException
1028 * If the Scanner is closed.
1029 */
1030 public boolean nextBoolean () throws NoSuchElementException, IllegalStateException // TESTED
1031 {
1032 return myNextBoolean (true);
1033 }
1034
1035 /**
1036 * Tries to interpret the next string as a byte value. Call {@link
1037 * #nextByte(int)} with the current radix as parameter, and return
1038 * the value.
1039 *
1040 * @see #nextByte(int)
1041 * @return Returns the byte value of the next string.
1042 * @throws NoSuchElementException
1043 * If no string is found or the string is not a byte
1044 * @throws IllegalStateException
1045 * If the Scanner is closed.
1046 */
1047 public byte nextByte () throws NoSuchElementException, IllegalStateException // TESTED
1048 {
1049 return nextByte (this.currentRadix);
1050 }
1051
1052 /**
1053 * Tries to interpret the next string as a byte value with the given
1054 * radix.
1055 *
1056 * @param radix
1057 * The radix to be used for this byte. The current radix of the Scanner is not
1058 * changed.
1059 * @return Returns the byte value of the next string.
1060 * @throws NoSuchElementException
1061 * If no string is found or the string is not a byte.
1062 * @throws IllegalStateException
1063 * If the Scanner is closed.
1064 */
1065 public byte nextByte (final int radix) throws NoSuchElementException,
1066 IllegalStateException
1067 {
1068 return myNextByte (radix, true);
1069 }
1070
1071 /**
1072 * Tries to interpret the next string as a double value.
1073 *
1074 * @return Returns the int value of the next string.
1075 * @throws NoSuchElementException
1076 * If no string is found or the string is not a double.
1077 * @throws IllegalStateException
1078 * If the Scanner is closed.
1079 */
1080 public double nextDouble () throws NoSuchElementException, IllegalStateException // TESTED
1081 {
1082 return myNextDouble (true);
1083 }
1084
1085 /**
1086 * Tries to interpret the next string as a double value, and then
1087 * casts down to float.
1088 *
1089 * @return Returns the int value of the next string.
1090 * @throws NoSuchElementException
1091 * If no string is found or the string is not a double.
1092 * @throws IllegalStateException
1093 * If the Scanner is closed.
1094 */
1095 public float nextFloat () throws NoSuchElementException, IllegalStateException // TESTED
1096 {
1097 return (float) myNextDouble (true);
1098 // return myNextFloat(true);
1099 }
1100
1101 /**
1102 * Tries to interpret the next string as an int value. Calls {@link
1103 * #nextInt(int)} with the current radix as parameter, and return
1104 * the value.
1105 *
1106 * @see #nextInt(int)
1107 * @return Returns the int value of the next string.
1108 * @throws NoSuchElementException
1109 * If no string is found or the string is not an int.
1110 * @throws IllegalStateException
1111 * If the Scanner is closed.
1112 */
1113 public int nextInt () throws NoSuchElementException, IllegalStateException // TESTED
1114 {
1115 return nextInt (this.currentRadix);
1116 }
1117
1118 /**
1119 * Tries to interpret the next string as an int value with the given
1120 * radix.
1121 *
1122 * @param radix
1123 * The radix to be used for this int. The current radix of the Scanner is not changed
1124 * @return Returns the int value of the next string.
1125 * @throws NoSuchElementException
1126 * If no string is found or the string is not an int.
1127 * @throws IllegalStateException
1128 * If the Scanner is closed.
1129 */
1130 public int nextInt (final int radix) throws NoSuchElementException,
1131 IllegalStateException
1132 {
1133 return myNextInt (radix, true);
1134 }
1135
1136 /**
1137 * Tries to match the system line seperator, and returns the current
1138 * line.
1139 *
1140 * @return Returns the current line.
1141 * @throws NoSuchElementException
1142 * If the current delimiter is not found.
1143 * @throws IllegalStateException
1144 * If the Scanner is closed.
1145 */
1146 public String nextLine () throws NoSuchElementException, IllegalStateException // TESTED
1147 {
1148 return myNextLine (true);
1149 }
1150
1151 /**
1152 * Tries to interpret the next string as a long value. Calls {@link
1153 * #nextLong(int)} with the current radix as parameter, and return
1154 * the value.
1155 *
1156 * @see #nextLong(int)
1157 * @return Returns the long value of the next string.
1158 * @throws NoSuchElementException
1159 * If no string is found or the string is not a long.
1160 * @throws IllegalStateException
1161 * If the Scanner is closed.
1162 */
1163 public long nextLong () throws NoSuchElementException, IllegalStateException // TESTED
1164 {
1165 return nextLong (this.currentRadix);
1166 }
1167
1168 /**
1169 * Tries to interpret the next string as a long value with the given
1170 * radix.
1171 *
1172 * @param radix
1173 * The radix to be used for this long. The current radix of the Scanner is not
1174 * changed
1175 * @return Returns the long value of the next string.
1176 * @throws NoSuchElementException
1177 * If no string is found or the string is not a long.
1178 * @throws IllegalStateException
1179 * If the Scanner is closed.
1180 */
1181 public long nextLong (final int radix) throws NoSuchElementException,
1182 IllegalStateException
1183 {
1184 return myNextLong (radix, true);
1185 }
1186
1187 /**
1188 * Tries to interpret the next string as a short value. Calls {@link
1189 * #nextShort(int)} with the current radix as parameter, and return
1190 * the value.
1191 *
1192 * @see #nextShort(int)
1193 * @return Returns the short value of the next string.
1194 * @throws NoSuchElementException
1195 * If no string is found or the string is not a short.
1196 */
1197 public short nextShort () throws NoSuchElementException // TESTED
1198 {
1199 return nextShort (this.currentRadix);
1200 }
1201
1202 /**
1203 * Tries to interpret the next string as a short value with the
1204 * given radix.
1205 *
1206 * @param radix
1207 * The radix to be used for this short. The current radix of the Scanner is not
1208 * changed.
1209 * @return Returns the short value of the next string.
1210 * @throws NoSuchElementException
1211 * If no string is found or the string is not a short.
1212 */
1213 public short nextShort (final int radix) throws NoSuchElementException
1214 {
1215 return myNextShort (radix, true);
1216 }
1217
1218 /**
1219 * @return Returns the current radix.
1220 */
1221 public int radix ()
1222 {
1223 return this.currentRadix;
1224 }
1225
1226 /**
1227 * The remove operation is not supported by this implementation of
1228 * Iterator.
1229 */
1230 public void remove ()
1231 {
1232 }
1233
1234 /**
1235 * @param useLocale the useLocale to set.
1236 */
1237 public void setUseLocale (final boolean useLocale) // TESTED
1238 {
1239 this.useLocale = useLocale;
1240 }
1241
1242 /**
1243 * Skips the given pattern. Sets skipped <code>true</code>.
1244 *
1245 * @param pattern
1246 * Pattern which should be skipped.
1247 * @return <code>this</code> with the skipped buffer.
1248 * @throws NoSuchElementException
1249 * If the Pattern is not found.
1250 */
1251 public Scanner skip (final Pattern pattern) throws NoSuchElementException
1252 {
1253 this.doSkipp = true;
1254 int end;
1255 boolean found;
1256 Matcher matcher = pattern.matcher (this.actBuffer);
1257 matcher.region (this.actPos - 1, this.actBuffer.length ());
1258
1259 found = matcher.find ();
1260 found = myFillBuffer_loop (matcher, this.actPos - 1, found);
1261 end = matcher.end ();
1262
1263 this.actPos = end + 1;
1264
1265 this.doSkipp = false;
1266 this.skipped = true;
1267
1268 actResult = null;
1269
1270 if (!found)
1271 {
1272 throw new NoSuchElementException ();
1273 }
1274 return this;
1275 }
1276
1277 /**
1278 * Skips a given pattern. Calls {@link #skip(Pattern)} with the
1279 * compiled pattern.
1280 *
1281 * @see #skip(Pattern)
1282 * @param pattern
1283 * Pattern which should be skipped.
1284 * @return <code>this</code> with the skipped buffer.
1285 */
1286 public Scanner skip (final String pattern)
1287 {
1288 return skip (Pattern.compile (pattern));
1289 }
1290
1291 /**
1292 * Returns the string representation of this Scanner.
1293 */
1294 @Override
1295 public String toString ()
1296 {
1297 String tmpStr2;
1298 String rc = this.getClass ().getName ();
1299 tmpStr2 = rc;
1300 tmpStr2 = "[delimiters=" + this.p.pattern () + "]";
1301 rc += tmpStr2;
1302 tmpStr2 = "[position=" + (this.procesedChars + this.actPos) + "]";
1303 rc += tmpStr2;
1304 tmpStr2 = "[match valid=" + this.matchValid + "]";
1305 rc += tmpStr2;
1306 tmpStr2 = "[need input=" + this.needInput + "]";
1307 rc += tmpStr2;
1308 tmpStr2 = "[source closed=" + this.isClosed + "]";
1309 rc += tmpStr2;
1310 tmpStr2 = "[skipped=" + this.skipped + "]";
1311 rc += tmpStr2;
1312 tmpStr2 = "[group separator=\\" + this.dfs.getGroupingSeparator () + "]";
1313 rc += tmpStr2;
1314 tmpStr2 = "[decimal separator=\\" + this.dfs.getDecimalSeparator () + "]";
1315 rc += tmpStr2;
1316 tmpStr2 =
1317 "[positive prefix=" + myConvert (this.df.getPositivePrefix ()) + "]";
1318 rc += tmpStr2;
1319 tmpStr2 =
1320 "[negative prefix=" + myConvert (this.df.getNegativePrefix ()) + "]";
1321 rc += tmpStr2;
1322 tmpStr2 =
1323 "[positive suffix=" + myConvert (this.df.getPositiveSuffix ()) + "]";
1324 rc += tmpStr2;
1325 tmpStr2 =
1326 "[negative suffix=" + myConvert (this.df.getNegativeSuffix ()) + "]";
1327 rc += tmpStr2;
1328 tmpStr2 = "[NaN string=" + myConvert (this.dfs.getNaN ()) + "]";
1329 rc += tmpStr2;
1330 tmpStr2 = "[infinity string=" + myConvert (this.dfs.getInfinity ()) + "]";
1331 rc += tmpStr2;
1332 return rc;
1333 }
1334
1335 /**
1336 * Sets the current pattern to the given parameter, and updates the
1337 * {@link Matcher} with the new pattern.
1338 *
1339 * @param pattern
1340 * The new pattern to use.
1341 * @return Returns the Scanner (<code>this</code>) with the new pattern.
1342 */
1343 public Scanner useDelimiter (final Pattern pattern) // TESTED
1344 {
1345 if (pattern != null)
1346 {
1347 this.p = pattern;
1348 this.myMatcher = this.p.matcher (this.actBuffer);
1349 }
1350 return this;
1351 }
1352
1353 /**
1354 * Sets the current pattern to the given parameter. Compiles the
1355 * pattern and calls {@link #useDelimiter(Pattern)}
1356 *
1357 * @see #useDelimiter(Pattern)
1358 * @param pattern
1359 * The new pattern to use.
1360 * @return Returns the Scanner (<code>this</code>) with the new pattern.
1361 */
1362 public Scanner useDelimiter (final String pattern) // TESTED
1363 {
1364 return useDelimiter (Pattern.compile (pattern));
1365 }
1366
1367 /**
1368 * Sets the current Locale to the given parameter. Formats and
1369 * Symbols are also set using the new Locale.
1370 *
1371 * @param locale The new Locale to use. If it is <code>null</code>
1372 * nothing happens.
1373 * @return Returns the Scanner (<code>this</code>) with the new Locale.
1374 */
1375 public Scanner useLocale (final Locale locale) // TESTED
1376 {
1377 if (locale != null)
1378 {
1379 this.actLocale = locale;
1380 this.actFormat = NumberFormat.getInstance (this.actLocale);
1381 this.dfs = new DecimalFormatSymbols (this.actLocale);
1382 this.df = (DecimalFormat) this.actFormat;
1383 }
1384 return this;
1385 }
1386
1387 /**
1388 * Sets the current radix to the current value if the given radix is
1389 * >= 2 and <= 36 otherwise an {@link IllegalArgumentException} is
1390 * thrown.
1391 *
1392 * @param radix
1393 * the new radix to use as default.
1394 * @return <code> this </code> with the new radix value.
1395 * @throws IllegalArgumentException
1396 * When the given radix is out of bounds.
1397 */
1398 public Scanner useRadix (final int radix) throws IllegalArgumentException
1399 {
1400 if (radix < 2 || radix > 36)
1401 {
1402 throw new IllegalArgumentException ();
1403 }
1404 this.currentRadix = radix;
1405 return this;
1406 }
1407
1408 /**
1409 * Checks if it is necessary to apply the current Locale on the
1410 * String. If so the String is converted using the {@link
1411 * NumberFormat#parse(String)} into a Number and then back to a
1412 * default stringrepresentation of that Number.
1413 *
1414 * @see #setUseLocale(boolean)
1415 * @param str
1416 * String to convert into another string.
1417 * @param radix Radix of the Number in the original string. It has
1418 * to be 10 for anything to happen.
1419 * @return Eighter the Stringrepresention of the number without the
1420 * Locale or an unchanged string.
1421 * @throws ParseException
1422 * if {@link NumberFormat#parse(String)} fails to parse.
1423 */
1424 private String myApplyLocale (final String str,
1425 final int radix) throws ParseException
1426 {
1427 String rc;
1428
1429 if (this.useLocale && radix == 10)
1430 {
1431 rc = this.actFormat.parse (str).toString ();
1432 return rc;
1433 }
1434
1435 return str;
1436 }
1437
1438 /**
1439 * If {@link #useLocale} is set and radix is 10 the string is tryed
1440 * to be converted to string without Locale settings, because the
1441 * "normal" convert from Local has only double precision and it is
1442 * not enough for the about 50 digits of precision of the
1443 * BigDecimal. So in the first step the string is seperated into the
1444 * integer part which is converted to a long, and the fraction part
1445 * is appended afterwards. Between the integer and the fraction part
1446 * comes a ".". Finally the resulting string is returned.
1447 *
1448 * @see #setUseLocale(boolean)
1449 * @param str String representation of a BigDecimal number.
1450 * @return The default String representation (without Locale) of the
1451 * BigInteger.
1452 * @throws ParseException
1453 * If the String has more than one decimal seperators a parse exception is thrown.
1454 */
1455 private String myApplyLocaleBD (final String str) throws ParseException
1456 {
1457 if (!this.useLocale || this.currentRadix != 10)
1458 {
1459 return str;
1460 }
1461
1462 String negPrefix = this.df.getNegativePrefix ();
1463 String negSuffix = this.df.getNegativeSuffix ();
1464 String posPrefix = this.df.getPositivePrefix ();
1465 String posSuffix = this.df.getPositiveSuffix ();
1466
1467 char d = this.dfs.getDecimalSeparator ();
1468 int begin1, begin2;
1469 boolean isNegativ = false;
1470 String parts = null;
1471
1472 String tmpStr1 = "";
1473
1474 begin1 = str.indexOf (d);
1475 begin2 = str.indexOf (d, begin1 + 1);
1476
1477 if (begin2 > 0)
1478 {
1479 throw new ParseException ("more than one Decimal seperators", begin2);
1480 }
1481
1482 parts = str.substring (0, begin1);
1483
1484 if ((negPrefix.length () > 0
1485 && str.substring (0, negPrefix.length ()).equals (negPrefix))
1486 || (negSuffix.length () > 0
1487 && str.substring (str.length () -
1488 negSuffix.length ()).equals (negSuffix)))
1489 {
1490 parts += negSuffix;
1491 isNegativ = true;
1492 }
1493 else
1494 if ((posPrefix.length () > 0
1495 && str.substring (0, posPrefix.length ()).equals (posPrefix))
1496 || (posSuffix.length () > 0
1497 && str.substring (str.length () -
1498 posSuffix.length ()).equals (posSuffix)))
1499 {
1500 parts += posSuffix;
1501 }
1502
1503 tmpStr1 = this.actFormat.parse (parts).toString ();
1504
1505 if (isNegativ)
1506 {
1507 tmpStr1 +=
1508 "." + str.substring (str.indexOf (d) + 1,
1509 str.length () - negSuffix.length ());
1510 }
1511 else
1512 {
1513 tmpStr1 +=
1514 "." + str.substring (str.indexOf (d) + 1,
1515 str.length () - posSuffix.length ());
1516 }
1517
1518 return tmpStr1;
1519 }
1520
1521 /**
1522 * Tries to interpret the next String as a BigDecimal. Therfore the
1523 * next String is get with {@link #myCoreNext(boolean, Pattern)} and
1524 * then {@link #myApplyLocaleBD(String)} is called to convert the
1525 * String into a BigDecimal.
1526 *
1527 * @param delete
1528 * Should the found string be deleted or not.
1529 * @return Returns the BigDecimal value of the next string.
1530 * @throws InputMismatchException
1531 * If the string is not a BigDecimal
1532 */
1533 private BigDecimal myBigDecimal (final boolean delete) throws
1534 InputMismatchException
1535 {
1536 BigDecimal rc;
1537 String tmp = myCoreNext (delete, this.p);
1538 try
1539 {
1540 tmp = myApplyLocaleBD (tmp);
1541 }
1542 catch (ParseException e)
1543 {
1544 throw new InputMismatchException (ERR_PREFIX + tmp + IS_NOT +
1545 "BigDecimal!!");
1546 }
1547 rc = new BigDecimal (tmp);
1548
1549 return rc;
1550 }
1551
1552 /**
1553 * Applies suffix ("\E") and prefix ("\Q") if str.length != 0 Used
1554 * by the toString method.
1555 *
1556 * @param str
1557 * the string on which the suffix and prefix should be applied.
1558 * @return The new new string with the suffix and prefix.
1559 */
1560 private String myConvert (final String str)
1561 {
1562 if (str != null && str.length () > 0)
1563 {
1564 return "\\Q" + str + "\\E";
1565 }
1566 return str;
1567 }
1568
1569 /**
1570 * Searches the current Matcher for the current Pattern. If the end
1571 * is reached during the search it tried to read again from the
1572 * source. The search results are always saved in {@link #actResult}
1573 * which is returned when match() is called. If doSkip is true the
1574 * pattern is also taken.
1575 *
1576 * @param delete
1577 * if true the aktPos is set.
1578 * @param pattern
1579 * pattern to search for.
1580 * @return Returns the String which matches the pattern.
1581 * @throws NoSuchElementException
1582 * If the search has no result.
1583 */
1584 private String myCoreNext (final boolean delete, final Pattern pattern)
1585 throws NoSuchElementException
1586 {
1587 if (this.isClosed)
1588 {
1589 throw new IllegalStateException ("Scanner closed");
1590 }
1591 if (shallUseLastFound (pattern != null ? pattern : this.p))
1592 {
1593 if (this.last_RegionEnd != this.myMatcher.regionEnd ())
1594 {
1595 System.out.println (this.last_RegionEnd + " != " +
1596 this.myMatcher.regionEnd () + " (" +
1597 (this.last_RegionEnd -
1598 this.myMatcher.regionEnd ()) + ")");
1599 }
1600 if (delete)
1601 {
1602 this.actPos = this.lastNextPos;
1603 this.lastFoundPresent = false;
1604 this.actResult = this.lastResult;
1605 }
1606 return this.lastFound;
1607 }
1608
1609 boolean found = false;
1610 int left;
1611 int endIndex;
1612
1613 String tmp2 = null;
1614
1615 if (this.actPos > this.MAX_PREFIX)
1616 {
1617 // skipp the processed chars so that the size of the buffer don't grow to much even with
1618 // huge files
1619 this.procesedChars += this.actPos;
1620 this.actBuffer = this.actBuffer.substring (this.actPos);
1621 this.actPos = 0;
1622 this.myMatcher = pattern.matcher (this.actBuffer);
1623 }
1624
1625 left = this.actBuffer.length () - this.actPos;
1626 if (left < this.MIN_BUF_LEN)
1627 {
1628 myFillBuffer ();
1629 }
1630 found = this.myMatcher.find (this.actPos);
1631
1632 found = myFillBuffer_loop (this.myMatcher, this.actPos, found);
1633
1634 this.needInput = false;
1635
1636 if (found)
1637 {
1638 if (this.doSkipp)
1639 {
1640 endIndex = this.myMatcher.end ();
1641 }
1642 else
1643 {
1644 endIndex = this.myMatcher.start ();
1645 }
1646 tmp2 = this.actBuffer.substring (this.actPos, endIndex);
1647 this.lastNextPos = this.myMatcher.end ();
1648 /*
1649 * if the delete flag is set, just set the current position after the end of the matched
1650 * pattern.
1651 */
1652 if (delete)
1653 {
1654 this.actPos = this.lastNextPos;
1655 }
1656 else
1657 {
1658 this.lastFound = tmp2;
1659 this.lastFoundPresent = true;
1660 this.lastPatternHash = pattern.hashCode ();
1661 }
1662 this.last_RegionStart = this.myMatcher.regionStart ();
1663 this.last_RegionEnd = this.myMatcher.regionEnd ();
1664 this.last_anchor = this.myMatcher.hasAnchoringBounds ();
1665 this.last_transparent = this.myMatcher.hasTransparentBounds ();
1666 }
1667 else if (this.myMatcher.hitEnd ())
1668 // the end of input is matched
1669 {
1670 tmp2 = this.actBuffer.substring (this.actPos);
1671 this.lastNextPos = this.actBuffer.length ();
1672 if (delete)
1673 {
1674 this.actPos = this.lastNextPos;
1675 }
1676 else
1677 {
1678 this.lastFound = tmp2;
1679 this.lastFoundPresent = true;
1680 this.lastPatternHash = pattern.hashCode ();
1681 }
1682 this.last_RegionStart = this.myMatcher.regionStart ();
1683 this.last_RegionEnd = this.myMatcher.regionEnd ();
1684 this.last_anchor = this.myMatcher.hasAnchoringBounds ();
1685 this.last_transparent = this.myMatcher.hasTransparentBounds ();
1686 }
1687 else
1688 {
1689 /*
1690 * if no match found an Exception is throwed
1691 */
1692 throw new NoSuchElementException ();
1693 }
1694 /*
1695 * change the Result only when a nextXXX() method was called, not if a hasNextXXX() method
1696 * is called
1697 */
1698 if (delete)
1699 {
1700 this.actResult = this.myMatcher.toMatchResult ();
1701
1702 this.matchValid = this.actResult != null;
1703 }
1704 else
1705 {
1706 this.lastResult = this.myMatcher.toMatchResult ();
1707 }
1708
1709 this.skipped = this.doSkipp;
1710 this.doSkipp = false;
1711
1712 return tmp2;
1713 }
1714
1715 /**
1716 * Used to fill the String buffer from a source. Therfore the 3
1717 * possible sources are checked if they are not <code>null</code>
1718 * and this not used, otherwise the read method is called on the
1719 * source. If a charsetName is set and not <code>null</code> it is
1720 * applied to convert to String.
1721 */
1722 private void myFillBuffer ()
1723 {
1724 int len;
1725 String tmpStr;
1726 CharBuffer cb = null;
1727 ByteBuffer bb = null;
1728
1729 if (this.bIS != null)
1730 {
1731 try
1732 {
1733 len = this.bIS.read (this.tmpBuffer);
1734 if (len < 0)
1735 {
1736 return;
1737 }
1738 if (this.charsetName != null)
1739 {
1740 tmpStr = new String (this.tmpBuffer, 0, len, this.charsetName);
1741 }
1742 else
1743 {
1744 tmpStr = new String (this.tmpBuffer, 0, len);
1745 }
1746 this.actBuffer += tmpStr;
1747 }
1748 catch (IOException e)
1749 {
1750 this.lastIOException = e;
1751 }
1752 }
1753 else if (this.readableSource != null)
1754 {
1755 try
1756 {
1757 cb = CharBuffer.allocate (1000);
1758 this.needInput = true;
1759 len = this.readableSource.read (cb);
1760 if (len < 0)
1761 {
1762 return;
1763 }
1764 this.needInput = false;
1765 tmpStr = new String (cb.array ());
1766 this.actBuffer += tmpStr;
1767 }
1768 catch (IOException e)
1769 {
1770 this.lastIOException = e;
1771 }
1772 }
1773 else if (this.rbcSource != null)
1774 {
1775 try
1776 {
1777 bb = ByteBuffer.allocate (1000);
1778 this.needInput = true;
1779 len = this.rbcSource.read (bb);
1780 this.needInput = false;
1781 if (len < 0)
1782 {
1783 return;
1784 }
1785 if (this.charsetName != null)
1786 {
1787 tmpStr = new String (bb.array (), 0, len, this.charsetName);
1788 }
1789 else
1790 {
1791 tmpStr = new String (bb.array (), 0, len);
1792 }
1793 this.actBuffer += tmpStr;
1794 }
1795 catch (IOException e)
1796 {
1797 this.lastIOException = e;
1798 }
1799 }
1800
1801 this.myMatcher.reset (this.actBuffer);
1802 }
1803
1804 /**
1805 * A loop in which the {@link #myFillBuffer()} is called and checked
1806 * if the pattern is found in the matcher and if the buffersize
1807 * changes after the read.
1808 *
1809 * @param aktM
1810 * The current Matcher.
1811 * @param pos
1812 * Position from which the matcher should start matching.
1813 * @param found
1814 * if already found.
1815 * @return <code> true </code> if the matcher has found a match.
1816 */
1817 private boolean myFillBuffer_loop (final Matcher aktM, final int pos,
1818 boolean found)
1819 {
1820 int tmp;
1821
1822 tmp = this.actBuffer.length ();
1823 while (aktM.hitEnd ()
1824 && ((this.bIS != null) || (this.readableSource != null)
1825 || (this.rbcSource != null)))
1826 {
1827 myFillBuffer ();
1828 if (tmp == this.actBuffer.length ())
1829 {
1830 break;
1831 }
1832 found = aktM.find (pos);
1833 this.needInput = true;
1834 }
1835 return found;
1836 }
1837
1838 /**
1839 * Used to find the given pattern in the given string before the
1840 * given horizon. Therfore the current matcher is copied, and
1841 * overwritten using the given pattern and the given Sting. <br>
1842 * After the search the original values are restored, and skipped is
1843 * set <code> true </code>.
1844 *
1845 * @param pattern
1846 * Pattern which should be matched.
1847 * @param str
1848 * The String in which the pattern should be matched.
1849 * @param horizon
1850 * the horizon whithin the match should be, if 0 then it is ignored.
1851 * @return Returns the String in the given String that matches the pattern.
1852 */
1853 private String myFindPInStr (final Pattern pattern, final String str,
1854 final int horizon)
1855 {
1856 String rc = null;
1857 int curPos = this.actPos;
1858 Matcher aktMatcher = this.myMatcher;
1859
1860 this.myMatcher = pattern.matcher (str);
1861 if (horizon > 0)
1862 {
1863 this.myMatcher.useAnchoringBounds (true);
1864 this.myMatcher.useTransparentBounds (true);
1865 this.myMatcher.region (this.actPos, this.actPos + horizon);
1866 }
1867 rc = myCoreNext (true, pattern);
1868 this.myMatcher = aktMatcher;
1869
1870 this.actPos = curPos;
1871 this.skipped = true;
1872
1873 return rc;
1874 }
1875
1876 /**
1877 * Used by the {@link #hasNext(Pattern)} and {@link #next(Pattern)}
1878 * methods. Therfore a substring is taken first to the current
1879 * delimiter, afterwards the given pattern is searched in this
1880 * subsring.<br> Finally the current Buffer and matcher (which have
1881 * been temporarily changed) are set back.<br> <br> The {@link
1882 * #skipped} is set <code> true </code>.
1883 *
1884 * @param pattern
1885 * Pattern to find until the current delimiter.
1886 * @param delete
1887 * Is <code> true </code> if a next method is called.<br>
1888 * Is <code> false </code> if a hasNext method is called.
1889 * @return Returns the String which is returned by the public methods.
1890 */
1891 private String myNext (final Pattern pattern, final boolean delete)
1892 {
1893 String tmpStr;
1894 Matcher aktMatcher = this.myMatcher;
1895 String result;
1896 String currBuffer = this.actBuffer;
1897 int currAktPos;
1898
1899 tmpStr = myCoreNext (delete, this.p);
1900 this.myMatcher = pattern.matcher (tmpStr);
1901 this.actBuffer = tmpStr;
1902 currAktPos = this.actPos;
1903 this.actPos = 0;
1904 result = myCoreNext (delete, pattern);
1905 this.actPos = currAktPos;
1906
1907 this.actBuffer = currBuffer;
1908 this.myMatcher = aktMatcher;
1909 this.skipped = true;
1910
1911 return result;
1912 }
1913
1914 /**
1915 * Calls the next() method internally to get the next String, and
1916 * trys to apply a locale which is only applied if the radix is 10
1917 * and useLocale is <code> true </code>. Afterwards it is tried to
1918 * call the Constructor of a {@link BigInteger} with the given
1919 * radix.
1920 *
1921 * @param radix The radix to use.
1922 * @param delete If the found String should be removed from input or
1923 * not.
1924 * @param name name of "BigInteger" in case of an Error.
1925 * @return Returns the new BigInteger created if there is no Error.
1926 * @throws InputMismatchException
1927 * If there is a {@link ParseException} or a {@link NumberFormatException}.
1928 */
1929 private BigInteger myNextBigInteger (final int radix, final boolean delete,
1930 final String name)
1931 {
1932 BigInteger rc;
1933 String tmp = myPrepareForNext (this.p, delete);
1934
1935 try
1936 {
1937 tmp = myApplyLocale (tmp, radix);
1938 rc = new BigInteger (tmp, radix);
1939 return rc;
1940 }
1941 catch (NumberFormatException nfe)
1942 {
1943 }
1944 catch (ParseException e)
1945 {
1946 }
1947 throw new InputMismatchException (ERR_PREFIX + tmp + IS_NOT + name);
1948 }
1949
1950 /**
1951 * Checks if the next String is either "true" or "false", otherwise
1952 * an {@link InputMismatchException} is thrown. It ignores the case
1953 * of the string so that "true" and "TRUE" and even "TrUe" are
1954 * accepted.
1955 *
1956 * @param delete Should the found value be removed from the input or
1957 * not.
1958 * @return Returns the boolean value (if it is a boolean).
1959 * @throws InputMismatchException
1960 * If the next String is not a boolean.
1961 */
1962 private boolean myNextBoolean (final boolean delete) throws
1963 InputMismatchException
1964 {
1965 String tmp = myPrepareForNext (this.p, delete);
1966 if (tmp.equalsIgnoreCase ("true"))
1967 {
1968 return true;
1969 }
1970 else if (tmp.equalsIgnoreCase ("false"))
1971 {
1972 return false;
1973 }
1974 else
1975 {
1976 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_BOOLEAN);
1977 }
1978 }
1979
1980 /**
1981 * Calls the {@link #myPrepareForNext(Pattern, boolean)} which calls
1982 * the {@link #myCoreNext(boolean, Pattern)} to return the next
1983 * String matching the current delimier. Afterwards it is tryed to
1984 * convert the String into a byte. Any Error will lead into a {@link
1985 * InputMismatchException}.
1986 *
1987 * @param radix The radix to use.
1988 * @param delete Should the found String be removed from the input.
1989 * @return Returns the byte value of the String.
1990 * @throws InputMismatchException if the next String is not a byte.
1991 */
1992 private byte myNextByte (final int radix,
1993 final boolean delete) throws InputMismatchException
1994 {
1995 byte rc;
1996 String tmp = myPrepareForNext (this.p, delete);
1997
1998 try
1999 {
2000 tmp = myApplyLocale (tmp, radix);
2001 rc = Byte.parseByte (tmp, radix);
2002 return rc;
2003 }
2004 catch (NumberFormatException nfe)
2005 {
2006 }
2007 catch (ParseException e)
2008 {
2009 }
2010 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_BYTE);
2011 }
2012
2013 /**
2014 * Tries to interpret the next String as a double value. To verify
2015 * if the double value is correct, it is converted back to a String
2016 * using the default Locale and this String is compared with the
2017 * String from which the double was converted. If the two Strings
2018 * don't match, an {@link InputMismatchException} is thrown.<br>
2019 * <br> The radix used is always 10 even if the global radix is
2020 * changed.
2021 *
2022 * @param delete Should the String be removed, if true it will be
2023 * also removed if the String is not a double value.
2024 * @return Returns the double value of the next String.
2025 * @throws InputMismatchException if the next String is not a
2026 * double.
2027 */
2028 private double myNextDouble (final boolean delete) throws
2029 InputMismatchException
2030 {
2031 double rc;
2032 String tmp = myPrepareForNext (this.p, delete);
2033
2034 try
2035 {
2036 tmp = myApplyLocale (tmp, 10);
2037 rc = Double.parseDouble (tmp);
2038 if (("" + rc).equals (tmp))
2039 {
2040 return rc;
2041 }
2042 }
2043 catch (ParseException e)
2044 {
2045 }
2046 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_DOUBLE);
2047 }
2048
2049 /**
2050 * Tries to interpret the next String as an int value. Therfore
2051 * {@link #myApplyLocale(String, int)} decides if the current Locale
2052 * should be applied or not and then the result is parsed using
2053 * {@link Integer#parseInt(String, int)}. Any Error will lead to an
2054 * {@link InputMismatchException}.
2055 *
2056 * @param radix The radix to use.
2057 * @param delete <code> true </code> if the String should be deleted
2058 * from the input.
2059 * @return Returns the int value of the String.
2060 * @throws InputMismatchException if the next String is not an int.
2061 */
2062 private int myNextInt (final int radix,
2063 final boolean delete) throws InputMismatchException
2064 {
2065 int rc;
2066 String tmp = myPrepareForNext (this.p, delete);
2067 try
2068 {
2069 tmp = myApplyLocale (tmp, radix);
2070 rc = Integer.parseInt (tmp, radix);
2071 return rc;
2072 }
2073 catch (NumberFormatException nfe)
2074 {
2075 }
2076 catch (ParseException e)
2077 {
2078 }
2079 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_INT);
2080 }
2081
2082 /**
2083 * Finds the next line using the {@link #NEW_LINE} constant which is
2084 * set to the system specific line seperator.
2085 *
2086 * @param delete Should the found line be deleted from the input.
2087 * @return Returns the current line.
2088 */
2089 private String myNextLine (final boolean delete)
2090 {
2091 String rc = null;
2092 rc = myPrepareForNext (Pattern.compile (NEW_LINE), delete);
2093 return rc;
2094 }
2095
2096 /**
2097 * Tries to interpret the next String as a long value with the given
2098 * radix. Therfore the {@link Long#parseLong(String, int)} is called
2099 * and every Error will lead into a {@link InputMismatchException}.
2100 *
2101 * @param radix The radix to be used.
2102 * @param delete Should the found String be deleted from the input.
2103 * @return the long value of the next String.
2104 * @throws InputMismatchException if the next String is not a long.
2105 */
2106 private long myNextLong (final int radix,
2107 final boolean delete) throws InputMismatchException
2108 {
2109 long rc;
2110 String tmp = myPrepareForNext (this.p, delete);
2111
2112 try
2113 {
2114 tmp = myApplyLocale (tmp, radix);
2115 rc = Long.parseLong (tmp, radix);
2116 return rc;
2117 }
2118 catch (NumberFormatException nfe)
2119 {
2120 }
2121 catch (ParseException e)
2122 {
2123 }
2124 throw new InputMismatchException (ERR_PREFIX + tmp + NOT_LONG);
2125 }
2126
2127 /**
2128 * Tries to interpret the next String as a short value with the
2129 * given radix. Therfore the {@link Short#parseShort(String, int)}
2130 * is called and every Error will lead into a {@link
2131 * InputMismatchException} .
2132 *
2133 * @param radix
2134 * The radix to be used.
2135 * @param delete
2136 * Should the found String be deleted from the input.
2137 * @return the long value of the next String.
2138 * @throws InputMismatchException
2139 * if the next String is not a short.
2140 */
2141 private short myNextShort (final int radix,
2142 final boolean delete) throws
2143 InputMismatchException
2144 {
2145 short rc;
2146 String tmp = myPrepareForNext (this.p, delete);
2147
2148 try
2149 {
2150 tmp = myApplyLocale (tmp, radix);
2151 rc = Short.parseShort (tmp, radix);
2152 return rc;
2153 }
2154 catch (NumberFormatException nfe)
2155 {
2156 }
2157 catch (ParseException e)
2158 {
2159 }
2160 throw new InputMismatchException (ERR_PREFIX + tmp +
2161 "\" is not a short");
2162 }
2163
2164 /**
2165 * Sets the current pattern to the given pattern and calls the
2166 * {@link #myCoreNext(boolean, Pattern)}. Finally sets the pattern
2167 * back to its old value.
2168 *
2169 * @param aktPattern Pattern to be used for the next match.
2170 * @param delete Should the found String be deleted or not.
2171 * @return Return the String returned from {@link
2172 * #myCoreNext(boolean, Pattern)}.
2173 */
2174 private String myPrepareForNext (final Pattern aktPattern,
2175 final boolean delete)
2176 {
2177
2178 String rc;
2179 Pattern oldPattern = this.p;
2180 useDelimiter (aktPattern);
2181
2182 rc = myCoreNext (delete, aktPattern);
2183
2184 useDelimiter (oldPattern);
2185
2186 return rc;
2187 }
2188
2189 /**
2190 * Determinates if the last found can be used, so that after a
2191 * hasNextXXX the nextXXX has not to search if nothing has
2192 * changed.<br /> Used in {@link #myCoreNext(boolean, Pattern)}.
2193 *
2194 * @param aktP The pattern which should be checked.
2195 * @return <code> true </code> if the searchresult is already ready.
2196 */
2197 private boolean shallUseLastFound (final Pattern aktP)
2198 {
2199 if (this.lastFoundPresent &&
2200 this.lastPatternHash == aktP.hashCode () &&
2201 this.last_RegionStart == this.myMatcher.regionStart () &&
2202 this.last_anchor == this.myMatcher.hasAnchoringBounds () &&
2203 this.last_transparent == this.myMatcher.hasTransparentBounds ())
2204 {
2205 if (this.last_RegionEnd != this.myMatcher.regionEnd ())
2206 {
2207 int tmpVal =
2208 this.myMatcher.regionEnd () -
2209 this.last_RegionEnd - this.MAX_PREFIX;
2210 if (tmpVal > 0 && tmpVal < 20)
2211 {
2212 this.last_RegionEnd =
2213 this.myMatcher.regionEnd ();
2214 return true;
2215 }
2216 }
2217 else
2218 return true;
2219 }
2220 return false;
2221 }
2222
2223 }