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