src/java.base/share/classes/java/util/Scanner.java

Print this page
rev 13685 : 8149656: Examine usages of sun.misc.LRUCache
Reviewed-by:


  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util;
  27 
  28 import java.io.*;
  29 import java.math.*;
  30 import java.nio.*;
  31 import java.nio.channels.*;
  32 import java.nio.charset.*;
  33 import java.nio.file.Path;
  34 import java.nio.file.Files;
  35 import java.text.*;
  36 import java.util.function.Consumer;
  37 import java.util.regex.*;
  38 import java.util.stream.Stream;
  39 import java.util.stream.StreamSupport;
  40 
  41 import sun.misc.LRUCache;
  42 
  43 /**
  44  * A simple text scanner which can parse primitive types and strings using
  45  * regular expressions.
  46  *
  47  * <p>A {@code Scanner} breaks its input into tokens using a
  48  * delimiter pattern, which by default matches whitespace. The resulting
  49  * tokens may then be converted into values of different types using the
  50  * various {@code next} methods.
  51  *
  52  * <p>For example, this code allows a user to read a number from
  53  * {@code System.in}:
  54  * <blockquote><pre>{@code
  55  *     Scanner sc = new Scanner(System.in);
  56  *     int i = sc.nextInt();
  57  * }</pre></blockquote>
  58  *
  59  * <p>As another example, this code allows {@code long} types to be
  60  * assigned from entries in a file {@code myNumbers}:
  61  * <blockquote><pre>{@code
  62  *      Scanner sc = new Scanner(new File("myNumbers"));


 349 
 350     // A cache of the last primitive type scanned
 351     private Object typeCache = null;
 352 
 353     // Boolean indicating if a match result is available
 354     private boolean matchValid = false;
 355 
 356     // Boolean indicating if this scanner has been closed
 357     private boolean closed = false;
 358 
 359     // The current radix used by this scanner
 360     private int radix = 10;
 361 
 362     // The default radix for this scanner
 363     private int defaultRadix = 10;
 364 
 365     // The locale used by this scanner
 366     private Locale locale = null;
 367 
 368     // A cache of the last few recently used Patterns
 369     private LRUCache<String,Pattern> patternCache =
 370     new LRUCache<String,Pattern>(7) {
 371         protected Pattern create(String s) {
 372             return Pattern.compile(s);
 373         }
 374         protected boolean hasName(Pattern p, String s) {
 375             return p.pattern().equals(s);
 376         }
 377     };
 378 
 379     // A holder of the last IOException encountered
 380     private IOException lastException;
 381 
 382     // Number of times this scanner's state has been modified.
 383     // Generally incremented on most public APIs and checked
 384     // within spliterator implementations.
 385     int modCount;
 386 
 387     // A pattern for java whitespace
 388     private static Pattern WHITESPACE_PATTERN = Pattern.compile(
 389                                                 "\\p{javaWhitespace}+");
 390 
 391     // A pattern for any token
 392     private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
 393 
 394     // A pattern for non-ASCII digits
 395     private static Pattern NON_ASCII_DIGIT = Pattern.compile(
 396         "[\\p{javaDigit}&&[^0-9]]");
 397 


2819                     throw new ConcurrentModificationException();
2820                 }
2821             } else {
2822                 expectedCount = modCount;
2823             }
2824 
2825             while (true) {
2826                 // assert expectedCount == modCount
2827                 if (findPatternInBuffer(pattern, 0)) { // doesn't increment modCount
2828                     cons.accept(matcher.toMatchResult());
2829                     if (expectedCount != modCount) {
2830                         throw new ConcurrentModificationException();
2831                     }
2832                     return true;
2833                 }
2834                 if (needInput)
2835                     readInput(); // doesn't increment modCount
2836                 else
2837                     return false; // reached end of input
2838             }














































2839         }
2840     }
2841 }


  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.util;
  27 
  28 import java.io.*;
  29 import java.math.*;
  30 import java.nio.*;
  31 import java.nio.channels.*;
  32 import java.nio.charset.*;
  33 import java.nio.file.Path;
  34 import java.nio.file.Files;
  35 import java.text.*;
  36 import java.util.function.Consumer;
  37 import java.util.regex.*;
  38 import java.util.stream.Stream;
  39 import java.util.stream.StreamSupport;
  40 


  41 /**
  42  * A simple text scanner which can parse primitive types and strings using
  43  * regular expressions.
  44  *
  45  * <p>A {@code Scanner} breaks its input into tokens using a
  46  * delimiter pattern, which by default matches whitespace. The resulting
  47  * tokens may then be converted into values of different types using the
  48  * various {@code next} methods.
  49  *
  50  * <p>For example, this code allows a user to read a number from
  51  * {@code System.in}:
  52  * <blockquote><pre>{@code
  53  *     Scanner sc = new Scanner(System.in);
  54  *     int i = sc.nextInt();
  55  * }</pre></blockquote>
  56  *
  57  * <p>As another example, this code allows {@code long} types to be
  58  * assigned from entries in a file {@code myNumbers}:
  59  * <blockquote><pre>{@code
  60  *      Scanner sc = new Scanner(new File("myNumbers"));


 347 
 348     // A cache of the last primitive type scanned
 349     private Object typeCache = null;
 350 
 351     // Boolean indicating if a match result is available
 352     private boolean matchValid = false;
 353 
 354     // Boolean indicating if this scanner has been closed
 355     private boolean closed = false;
 356 
 357     // The current radix used by this scanner
 358     private int radix = 10;
 359 
 360     // The default radix for this scanner
 361     private int defaultRadix = 10;
 362 
 363     // The locale used by this scanner
 364     private Locale locale = null;
 365 
 366     // A cache of the last few recently used Patterns
 367     private PatternLRUCache patternCache = new PatternLRUCache(7);








 368 
 369     // A holder of the last IOException encountered
 370     private IOException lastException;
 371 
 372     // Number of times this scanner's state has been modified.
 373     // Generally incremented on most public APIs and checked
 374     // within spliterator implementations.
 375     int modCount;
 376 
 377     // A pattern for java whitespace
 378     private static Pattern WHITESPACE_PATTERN = Pattern.compile(
 379                                                 "\\p{javaWhitespace}+");
 380 
 381     // A pattern for any token
 382     private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
 383 
 384     // A pattern for non-ASCII digits
 385     private static Pattern NON_ASCII_DIGIT = Pattern.compile(
 386         "[\\p{javaDigit}&&[^0-9]]");
 387 


2809                     throw new ConcurrentModificationException();
2810                 }
2811             } else {
2812                 expectedCount = modCount;
2813             }
2814 
2815             while (true) {
2816                 // assert expectedCount == modCount
2817                 if (findPatternInBuffer(pattern, 0)) { // doesn't increment modCount
2818                     cons.accept(matcher.toMatchResult());
2819                     if (expectedCount != modCount) {
2820                         throw new ConcurrentModificationException();
2821                     }
2822                     return true;
2823                 }
2824                 if (needInput)
2825                     readInput(); // doesn't increment modCount
2826                 else
2827                     return false; // reached end of input
2828             }
2829         }
2830     }
2831 
2832     /** Utility class for small LRU caches. */
2833     private static class PatternLRUCache {
2834 
2835         private Pattern[] oa = null;
2836         private final int size;
2837 
2838         PatternLRUCache(int size) {
2839             this.size = size;
2840         }
2841 
2842         boolean hasName(Pattern p, String s) {
2843             return p.pattern().equals(s);
2844         }
2845 
2846         void moveToFront(Object[] oa, int i) {
2847             Object ob = oa[i];
2848             for (int j = i; j > 0; j--)
2849                 oa[j] = oa[j - 1];
2850             oa[0] = ob;
2851         }
2852 
2853         Pattern forName(String name) {
2854             if (oa == null) {
2855                 Pattern[] temp = new Pattern[size];
2856                 oa = temp;
2857             } else {
2858                 for (int i = 0; i < oa.length; i++) {
2859                     Pattern ob = oa[i];
2860                     if (ob == null)
2861                         continue;
2862                     if (hasName(ob, name)) {
2863                         if (i > 0)
2864                             moveToFront(oa, i);
2865                         return ob;
2866                     }
2867                 }
2868             }
2869 
2870             // Create a new object
2871             Pattern ob = Pattern.compile(name);
2872             oa[oa.length - 1] = ob;
2873             moveToFront(oa, oa.length - 1);
2874             return ob;
2875         }
2876     }
2877 }