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; 26a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A class for turning a byte stream into a character stream. Data read from the 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * source input stream is converted into characters by either a default or a 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provided character converter. The default encoding is taken from the 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * "file.encoding" system property. {@code InputStreamReader} contains a buffer 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of bytes read from the source stream and converts these into characters as 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * needed. The buffer size is 8K. 35f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see OutputStreamWriter 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class InputStreamReader extends Reader { 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream in; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean endOfInput = false; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes private CharsetDecoder decoder; 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 45b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes private final ByteBuffer bytes = ByteBuffer.allocate(8192); 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new {@code InputStreamReader} on the {@link InputStream} 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code in}. This constructor sets the character converter to the encoding 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified in the "file.encoding" property and falls back to ISO 8859_1 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (ISO-Latin-1) if the property doesn't exist. 52f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input stream from which to read characters. 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStreamReader(InputStream in) { 5746ff2ede6c9f5ad431303d388986ec3d72b2fbd3Elliott Hughes this(in, Charset.defaultCharset()); 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new InputStreamReader on the InputStream {@code in}. The 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character converter that is used to decode bytes into characters is 639b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * identified by name by {@code charsetName}. If the encoding cannot be found, an 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * UnsupportedEncodingException error is thrown. 65f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the InputStream from which to read characters. 689b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * @param charsetName 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * identifies the character converter to use. 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 719b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * if {@code charsetName} is {@code null}. 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnsupportedEncodingException 739b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes * if the encoding specified by {@code charsetName} cannot be found. 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 759b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes public InputStreamReader(InputStream in, final String charsetName) 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws UnsupportedEncodingException { 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(in); 789b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes if (charsetName == null) { 799b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes throw new NullPointerException("charsetName == null"); 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.in = in; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 839b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes decoder = Charset.forName(charsetName).newDecoder().onMalformedInput( 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction.REPLACE).onUnmappableCharacter( 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction.REPLACE); 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalArgumentException e) { 8743f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein throw (UnsupportedEncodingException) 889b9e9145bc55a47be42a9d3f7ecc9f6b533739b2Elliott Hughes new UnsupportedEncodingException(charsetName).initCause(e); 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9043f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.limit(0); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new InputStreamReader on the InputStream {@code in} and 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * CharsetDecoder {@code dec}. 96f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the source InputStream from which to read characters. 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param dec 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the CharsetDecoder used by the character conversion. 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public InputStreamReader(InputStream in, CharsetDecoder dec) { 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(in); 104dda692d6341fcbbb8f1ef9344024989b110bc040Narayan Kamath if (dec == null) { 105dda692d6341fcbbb8f1ef9344024989b110bc040Narayan Kamath throw new NullPointerException("dec == null"); 106dda692d6341fcbbb8f1ef9344024989b110bc040Narayan Kamath } 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 /** 152817b74b58acb99b2e161228e329a6e6ae2d9d62bElliott Hughes * Returns the canonical 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 } 161817b74b58acb99b2e161228e329a6e6ae2d9d62bElliott Hughes return decoder.charset().name(); 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 /** 188325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes * Reads up to {@code count} characters from this reader and stores them 189325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes * at position {@code offset} in the character array {@code buffer}. 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 * 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IndexOutOfBoundsException 196325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes * if {@code offset < 0 || count < 0 || offset + count > buffer.length}. 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this reader is closed or some other I/O error occurs. 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 201325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes public int read(char[] buffer, int offset, int count) throws IOException { 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 204b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("InputStreamReader is closed"); 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 206a1603838fe9e865575c87982e32c6343740e464cElliott Hughes 207325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, count); 208325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes if (count == 0) { 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return 0; 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 21143f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 212325ff8c68ed5e530e9e1d487b9e2e6d8f8e2bd37Elliott Hughes CharBuffer out = CharBuffer.wrap(buffer, offset, count); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = CoderResult.UNDERFLOW; 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 21543f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // bytes.remaining() indicates number of bytes in buffer 21643f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // when 1-st time entered, it'll be equal to zero 21743f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein boolean needInput = !bytes.hasRemaining(); 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (out.hasRemaining()) { 22043f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // fill the buffer if needed 22143f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein if (needInput) { 22255392539fea537abfb6581b474918f9d611fba27Jesse Wilson try { 223b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes if (in.available() == 0 && out.position() > offset) { 22455392539fea537abfb6581b474918f9d611fba27Jesse Wilson // we could return the result without blocking read 22555392539fea537abfb6581b474918f9d611fba27Jesse Wilson break; 22655392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 22755392539fea537abfb6581b474918f9d611fba27Jesse Wilson } catch (IOException e) { 22855392539fea537abfb6581b474918f9d611fba27Jesse Wilson // available didn't work so just try the read 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2319229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes int desiredByteCount = bytes.capacity() - bytes.limit(); 23243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein int off = bytes.arrayOffset() + bytes.limit(); 2339229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes int actualByteCount = in.read(bytes.array(), off, desiredByteCount); 23443f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 2359229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes if (actualByteCount == -1) { 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project endOfInput = true; 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 2389229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes } else if (actualByteCount == 0) { 23943f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein break; 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2419229d47c1288e25ead3a2dc27fac8a4a2ee932a3Elliott Hughes bytes.limit(bytes.limit() + actualByteCount); 24243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein needInput = false; 24343f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein } 24443f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 24543f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // decode bytes 24643f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein result = decoder.decode(bytes, out, false); 24743f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein 24843f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein if (result.isUnderflow()) { 24943f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein // compact the buffer if no space left 25043f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein if (bytes.limit() == bytes.capacity()) { 25143f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.compact(); 25243f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein bytes.limit(bytes.position()); 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project bytes.position(0); 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 25543f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein needInput = true; 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == CoderResult.UNDERFLOW && endOfInput) { 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = decoder.decode(bytes, out, true); 263bd024cc687470a008999d96fd3af4a1261413d55Narayan Kamath if (result == CoderResult.UNDERFLOW) { 264bd024cc687470a008999d96fd3af4a1261413d55Narayan Kamath result = decoder.flush(out); 265bd024cc687470a008999d96fd3af4a1261413d55Narayan Kamath } 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder.reset(); 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2683bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes if (result.isMalformed() || result.isUnmappable()) { 2693bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes result.throwException(); 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return out.position() - offset == 0 ? -1 : out.position() - offset; 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean isOpen() { 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return in != null; 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether this reader is ready to be read without blocking. If 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the result is {@code true}, the next {@code read()} will not block. If 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the result is {@code false} then this reader may or may not block when 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code read()} is called. This implementation returns {@code true} if 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * there are bytes available in the buffer or the source stream has bytes 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 287f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if the receiver will not block when {@code read()} 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is called, {@code false} if unknown or blocking will occur. 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this reader is closed or some other I/O error occurs. 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean ready() throws IOException { 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in == null) { 297b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("InputStreamReader is closed"); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 30043f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein return bytes.hasRemaining() || in.available() > 0; 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 307