1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.CharBuffer; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.Charset; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.CharsetDecoder; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.CoderResult; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.CodingErrorAction; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.MalformedInputException; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.UnmappableCharacterException; 28a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A class for turning a byte stream into a character stream. Data read from the 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * source input stream is converted into characters by either a default or a 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provided character converter. The default encoding is taken from the 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * "file.encoding" system property. {@code InputStreamReader} contains a buffer 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of bytes read from the source stream and converts these into characters as 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * needed. The buffer size is 8K. 37f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see OutputStreamWriter 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class InputStreamReader extends Reader { 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream in; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean endOfInput = false; 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 45b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes private CharsetDecoder decoder; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes private final ByteBuffer bytes = ByteBuffer.allocate(8192); 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new {@code InputStreamReader} on the {@link InputStream} 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code in}. This constructor sets the character converter to the encoding 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified in the "file.encoding" property and falls back to ISO 8859_1 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (ISO-Latin-1) if the property doesn't exist. 54f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input stream from which to read characters. 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStreamReader(InputStream in) { 5946ff2ede6c9f5ad431303d388986ec3d72b2fbd3Elliott Hughes this(in, Charset.defaultCharset()); 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new InputStreamReader on the InputStream {@code in}. The 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character converter that is used to decode bytes into characters is 659b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * identified by name by {@code charsetName}. If the encoding cannot be found, an 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * UnsupportedEncodingException error is thrown. 67f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the InputStream from which to read characters. 709b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * @param charsetName 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * identifies the character converter to use. 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 739b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * if {@code charsetName} is {@code null}. 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnsupportedEncodingException 759b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * if the encoding specified by {@code charsetName} cannot be found. 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 779b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes public InputStreamReader(InputStream in, final String charsetName) 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws UnsupportedEncodingException { 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(in); 809b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes if (charsetName == null) { 819b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes throw new NullPointerException("charsetName == null"); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.in = in; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 859b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes decoder = Charset.forName(charsetName).newDecoder().onMalformedInput( 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction.REPLACE).onUnmappableCharacter( 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction.REPLACE); 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalArgumentException e) { 8943f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein throw (UnsupportedEncodingException) 909b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes new UnsupportedEncodingException(charsetName).initCause(e); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.limit(0); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new InputStreamReader on the InputStream {@code in} and 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * CharsetDecoder {@code dec}. 98f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the source InputStream from which to read characters. 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param dec 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the CharsetDecoder used by the character conversion. 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStreamReader(InputStream in, CharsetDecoder dec) { 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(in); 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dec.averageCharsPerByte(); 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.in = in; 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder = dec; 10943f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.limit(0); 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new InputStreamReader on the InputStream {@code in} and 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Charset {@code charset}. 115f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the source InputStream from which to read characters. 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param charset 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the Charset that defines the character converter 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStreamReader(InputStream in, Charset charset) { 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(in); 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.in = in; 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder = charset.newDecoder().onMalformedInput( 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction.REPLACE).onUnmappableCharacter( 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction.REPLACE); 12743f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.limit(0); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes this reader. This implementation closes the source InputStream and 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * releases all local storage. 133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs attempting to close this reader. 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (decoder != null) { 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder.reset(); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder = null; 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in != null) { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.close(); 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in = null; 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 152dbf863488607fbb16a3d28c09f772d9581bd64adElliott Hughes * Returns the historical name of the encoding used by this writer to convert characters to 153dbf863488607fbb16a3d28c09f772d9581bd64adElliott Hughes * bytes, or null if this writer has been closed. Most callers should probably keep 154dbf863488607fbb16a3d28c09f772d9581bd64adElliott Hughes * track of the String or Charset they passed in; this method may not return the same 155dbf863488607fbb16a3d28c09f772d9581bd64adElliott Hughes * name. 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getEncoding() { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1618e9f4948e08c238998b44228ee30aea9d57a7573Elliott Hughes return HistoricalCharsetNames.get(decoder.charset()); 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads a single character from this reader and returns it as an integer 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * with the two higher-order bytes set to 0. Returns -1 if the end of the 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader has been reached. The byte value is either obtained from 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * converting bytes in this reader's buffer or by first filling the buffer 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * from the source InputStream and then reading from the buffer. 170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the character read or -1 if the end of the reader has been 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reached. 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this reader is closed or some other I/O error occurs. 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 180b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("InputStreamReader is closed"); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 182171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes char[] buf = new char[1]; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return read(buf, 0, 1) != -1 ? buf[0] : -1; 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads at most {@code length} characters from this reader and stores them 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * at position {@code offset} in the character array {@code buf}. Returns 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of characters actually read or -1 if the end of the reader has 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * been reached. The bytes are either obtained from converting bytes in this 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader's buffer or by first filling the buffer from the source 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * InputStream and then reading from the buffer. 194f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 195bf87c56b39383f6b11c36c3cdc93df4b03fed914Brian Carlstrom * @param buffer 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the array to store the characters read. 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the initial position in {@code buf} to store the characters 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read from this reader. 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param length 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the maximum number of characters to read. 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the number of characters read or -1 if the end of the reader has 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * been reached. 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IndexOutOfBoundsException 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code offset < 0} or {@code length < 0}, or if 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code offset + length} is greater than the length of 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code buf}. 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this reader is closed or some other I/O error occurs. 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 212b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes public int read(char[] buffer, int offset, int length) throws IOException { 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 215b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("InputStreamReader is closed"); 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 217a1603838fe9e865575c87982e32c6343740e464cElliott Hughes 218a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, length); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (length == 0) { 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 22243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 223b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes CharBuffer out = CharBuffer.wrap(buffer, offset, length); 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = CoderResult.UNDERFLOW; 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 22643f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // bytes.remaining() indicates number of bytes in buffer 22743f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // when 1-st time entered, it'll be equal to zero 22843f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein boolean needInput = !bytes.hasRemaining(); 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (out.hasRemaining()) { 23143f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // fill the buffer if needed 23243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein if (needInput) { 23355392539fea537abfb6581b474918f9d611fba27Jesse Wilson try { 234b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes if (in.available() == 0 && out.position() > offset) { 23555392539fea537abfb6581b474918f9d611fba27Jesse Wilson // we could return the result without blocking read 23655392539fea537abfb6581b474918f9d611fba27Jesse Wilson break; 23755392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 23855392539fea537abfb6581b474918f9d611fba27Jesse Wilson } catch (IOException e) { 23955392539fea537abfb6581b474918f9d611fba27Jesse Wilson // available didn't work so just try the read 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2429229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes int desiredByteCount = bytes.capacity() - bytes.limit(); 24343f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein int off = bytes.arrayOffset() + bytes.limit(); 2449229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes int actualByteCount = in.read(bytes.array(), off, desiredByteCount); 24543f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 2469229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes if (actualByteCount == -1) { 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project endOfInput = true; 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 2499229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes } else if (actualByteCount == 0) { 25043f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein break; 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2529229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes bytes.limit(bytes.limit() + actualByteCount); 25343f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein needInput = false; 25443f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein } 25543f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 25643f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // decode bytes 25743f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein result = decoder.decode(bytes, out, false); 25843f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 25943f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein if (result.isUnderflow()) { 26043f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // compact the buffer if no space left 26143f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein if (bytes.limit() == bytes.capacity()) { 26243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.compact(); 26343f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.limit(bytes.position()); 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytes.position(0); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 26643f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein needInput = true; 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == CoderResult.UNDERFLOW && endOfInput) { 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = decoder.decode(bytes, out, true); 274f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson decoder.flush(out); 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder.reset(); 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2773bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes if (result.isMalformed() || result.isUnmappable()) { 2783bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes result.throwException(); 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return out.position() - offset == 0 ? -1 : out.position() - offset; 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean isOpen() { 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return in != null; 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether this reader is ready to be read without blocking. If 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the result is {@code true}, the next {@code read()} will not block. If 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the result is {@code false} then this reader may or may not block when 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code read()} is called. This implementation returns {@code true} if 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * there are bytes available in the buffer or the source stream has bytes 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 296f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if the receiver will not block when {@code read()} 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is called, {@code false} if unknown or blocking will occur. 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this reader is closed or some other I/O error occurs. 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean ready() throws IOException { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in == null) { 306b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("InputStreamReader is closed"); 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 30943f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein return bytes.hasRemaining() || in.available() > 0; 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 316