Home | History | Annotate | Download | only in data
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2016 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 /**
      5  *******************************************************************************
      6  * Copyright (C) 2001-2015, International Business Machines Corporation and
      7  * others. All Rights Reserved.
      8  *******************************************************************************
      9  */
     10 
     11 package android.icu.impl.data;
     12 
     13 import java.io.BufferedReader;
     14 import java.io.Closeable;
     15 import java.io.IOException;
     16 import java.io.InputStream;
     17 import java.io.InputStreamReader;
     18 import java.io.UnsupportedEncodingException;
     19 
     20 import android.icu.impl.ICUData;
     21 import android.icu.impl.PatternProps;
     22 
     23 /**
     24  * A reader for text resource data in the current package or the package
     25  * of a given class object.  The
     26  * resource data is loaded through the class loader, so it will
     27  * typically be a file in the same directory as the *.class files, or
     28  * a file within a JAR file in the corresponding subdirectory.  The
     29  * file must be a text file in one of the supported encodings; when the
     30  * resource is opened by constructing a <code>ResourceReader</code>
     31  * object the encoding is specified.
     32  *
     33  * <p>2015-sep-03 TODO: Only used in android.icu.dev.test.format, move there.
     34  *
     35  * @author Alan Liu
     36  * @hide Only a subset of ICU is exposed in Android
     37  */
     38 public class ResourceReader implements Closeable {
     39     private BufferedReader reader = null;
     40     private String resourceName;
     41     private String encoding; // null for default encoding
     42     private Class<?> root;
     43 
     44     /**
     45      * The one-based line number. Has the special value -1 before the
     46      * object is initialized. Has the special value 0 after initialization
     47      * but before the first line is read.
     48      */
     49     private int lineNo;
     50 
     51     /**
     52      * Construct a reader object for the text file of the given name
     53      * in this package, using the given encoding.
     54      * @param resourceName the name of the text file located in this
     55      * package's ".data" subpackage.
     56      * @param encoding the encoding of the text file; if unsupported
     57      * an exception is thrown
     58      * @exception UnsupportedEncodingException if
     59      * <code>encoding</code> is not supported by the JDK.
     60      */
     61     public ResourceReader(String resourceName, String encoding)
     62         throws UnsupportedEncodingException {
     63         this(ICUData.class, "data/" + resourceName, encoding);
     64     }
     65 
     66     /**
     67      * Construct a reader object for the text file of the given name
     68      * in this package, using the default encoding.
     69      * @param resourceName the name of the text file located in this
     70      * package's ".data" subpackage.
     71      */
     72     public ResourceReader(String resourceName) {
     73         this(ICUData.class, "data/" + resourceName);
     74     }
     75 
     76     /**
     77      * Construct a reader object for the text file of the given name
     78      * in the given class's package, using the given encoding.
     79      * @param resourceName the name of the text file located in the
     80      * given class's package.
     81      * @param encoding the encoding of the text file; if unsupported
     82      * an exception is thrown
     83      * @exception UnsupportedEncodingException if
     84      * <code>encoding</code> is not supported by the JDK.
     85      */
     86     public ResourceReader(Class<?> rootClass, String resourceName, String encoding)
     87         throws UnsupportedEncodingException {
     88         this.root = rootClass;
     89         this.resourceName = resourceName;
     90         this.encoding = encoding;
     91         lineNo = -1;
     92         _reset();
     93     }
     94 
     95          /**
     96           * Construct a reader object for the input stream associated with
     97           * the given resource name.
     98           * @param is the input stream of the resource
     99           * @param resourceName the name of the resource
    100           */
    101           public ResourceReader(InputStream is, String resourceName, String encoding) {
    102                    this.root = null;
    103          this.resourceName = resourceName;
    104          this.encoding = encoding;
    105 
    106          this.lineNo = -1;
    107          try {
    108              InputStreamReader isr = (encoding == null)
    109                  ? new InputStreamReader(is)
    110                  : new InputStreamReader(is, encoding);
    111 
    112              this.reader = new BufferedReader(isr);
    113              this.lineNo= 0;
    114          }
    115          catch (UnsupportedEncodingException e) {
    116          }
    117      }
    118 
    119           /**
    120            * Construct a reader object for the input stream associated with
    121            * the given resource name.
    122            * @param is the input stream of the resource
    123            * @param resourceName the name of the resource
    124            */
    125           public ResourceReader(InputStream is, String resourceName) {
    126               this(is, resourceName, null);
    127           }
    128 
    129     /**
    130      * Construct a reader object for the text file of the given name
    131      * in the given class's package, using the default encoding.
    132      * @param resourceName the name of the text file located in the
    133      * given class's package.
    134      */
    135     public ResourceReader(Class<?> rootClass, String resourceName) {
    136         this.root = rootClass;
    137         this.resourceName = resourceName;
    138         this.encoding = null;
    139         lineNo = -1;
    140         try {
    141             _reset();
    142         } catch (UnsupportedEncodingException e) {}
    143     }
    144 
    145     /**
    146      * Read and return the next line of the file or <code>null</code>
    147      * if the end of the file has been reached.
    148      */
    149     public String readLine() throws IOException {
    150         if (lineNo == 0) {
    151             // Remove BOMs
    152             ++lineNo;
    153             String line = reader.readLine();
    154             if (line != null && (line.charAt(0) == '\uFFEF' ||
    155                                  line.charAt(0) == '\uFEFF')) {
    156                 line = line.substring(1);
    157             }
    158             return line;
    159         }
    160         ++lineNo;
    161         return reader.readLine();
    162     }
    163 
    164     /**
    165      * Read a line, ignoring blank lines and lines that start with
    166      * '#'.
    167      * @param trim if true then trim leading Pattern_White_Space.
    168      */
    169     public String readLineSkippingComments(boolean trim) throws IOException {
    170         for (;;) {
    171             String line = readLine();
    172             if (line == null) {
    173                 return line;
    174             }
    175             // Skip over white space
    176             int pos = PatternProps.skipWhiteSpace(line, 0);
    177             // Ignore blank lines and comment lines
    178             if (pos == line.length() || line.charAt(pos) == '#') {
    179                 continue;
    180             }
    181             // Process line
    182             if (trim) line = line.substring(pos);
    183             return line;
    184         }
    185     }
    186 
    187 
    188     /**
    189      * Read a line, ignoring blank lines and lines that start with
    190      * '#'. Do not trim leading Pattern_White_Space.
    191      */
    192     public String readLineSkippingComments() throws IOException {
    193         return readLineSkippingComments(false);
    194     }
    195 
    196     /**
    197      * Return the one-based line number of the last line returned by
    198      * readLine() or readLineSkippingComments(). Should only be called
    199      * after a call to one of these methods; otherwise the return
    200      * value is undefined.
    201      */
    202     public int getLineNumber() {
    203         return lineNo;
    204     }
    205 
    206     /**
    207      * Return a string description of the position of the last line
    208      * returned by readLine() or readLineSkippingComments().
    209      */
    210     public String describePosition() {
    211         return resourceName + ':' + lineNo;
    212     }
    213 
    214     /**
    215      * Reset this reader so that the next call to
    216      * <code>readLine()</code> returns the first line of the file
    217      * again.  This is a somewhat expensive call, however, calling
    218      * <code>reset()</code> after calling it the first time does
    219      * nothing if <code>readLine()</code> has not been called in
    220      * between.
    221      */
    222     public void reset() {
    223         try {
    224             _reset();
    225         } catch (UnsupportedEncodingException e) {}
    226         // We swallow this exception, if there is one.  If the encoding is
    227         // invalid, the constructor will have thrown this exception already and
    228         // the caller shouldn't use the object afterwards.
    229     }
    230 
    231     /**
    232      * Reset to the start by reconstructing the stream and readers.
    233      * We could also use mark() and reset() on the stream or reader,
    234      * but that would cause them to keep the stream data around in
    235      * memory.  We don't want that because some of the resource files
    236      * are large, e.g., 400k.
    237      */
    238     private void _reset() throws UnsupportedEncodingException {
    239         try {
    240             close();
    241         } catch (IOException e) {}
    242         if (lineNo == 0) {
    243             return;
    244         }
    245         InputStream is = ICUData.getStream(root, resourceName);
    246         if (is == null) {
    247             throw new IllegalArgumentException("Can't open " + resourceName);
    248         }
    249 
    250         InputStreamReader isr =
    251             (encoding == null) ? new InputStreamReader(is) :
    252                                  new InputStreamReader(is, encoding);
    253         reader = new BufferedReader(isr);
    254         lineNo = 0;
    255     }
    256 
    257     /**
    258      * Closes the underlying reader and releases any system resources
    259      * associated with it. If the stream is already closed then invoking
    260      * this method has no effect.
    261      */
    262     @Override
    263     public void close() throws IOException {
    264         if (reader != null) {
    265             reader.close();
    266             reader = null;
    267         }
    268     }
    269 }
    270