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 /** 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); 263f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson decoder.flush(out); 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder.reset(); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2663bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes if (result.isMalformed() || result.isUnmappable()) { 2673bdd9bb460941429ab11dfa13596768f3dc246adElliott Hughes result.throwException(); 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return out.position() - offset == 0 ? -1 : out.position() - offset; 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean isOpen() { 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return in != null; 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether this reader is ready to be read without blocking. If 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the result is {@code true}, the next {@code read()} will not block. If 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the result is {@code false} then this reader may or may not block when 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code read()} is called. This implementation returns {@code true} if 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * there are bytes available in the buffer or the source stream has bytes 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 285f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return {@code true} if the receiver will not block when {@code read()} 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is called, {@code false} if unknown or blocking will occur. 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this reader is closed or some other I/O error occurs. 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean ready() throws IOException { 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (lock) { 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in == null) { 295b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("InputStreamReader is closed"); 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 29843f11e509433970a5f33a6e5edd9b90089fa7d88Dan Bornstein return bytes.hasRemaining() || in.available() > 0; 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 305