1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java $
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 576077 $
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or more contributor license agreements.  See the NOTICE file
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed with this work for additional information
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * regarding copyright ownership.  The ASF licenses this file
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to you under the Apache License, Version 2.0 (the
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "License"); you may not use this file except in compliance
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the License.  You may obtain a copy of the License at
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *   http://www.apache.org/licenses/LICENSE-2.0
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing,
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * software distributed under the License is distributed on an
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * KIND, either express or implied.  See the License for the
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specific language governing permissions and limitations
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * under the License.
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation.  For more
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>.
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.impl.io;
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.IOException;
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.InputStream;
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.io.SessionInputBuffer;
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.io.HttpTransportMetrics;
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.params.CoreConnectionPNames;
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.params.HttpParams;
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.params.HttpProtocolParams;
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.protocol.HTTP;
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.util.ByteArrayBuffer;
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.util.CharArrayBuffer;
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Abstract base class for session input buffers that stream data
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * from a {@link InputStream}.
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic abstract class AbstractSessionInputBuffer implements SessionInputBuffer {
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private InputStream instream;
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private byte[] buffer;
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int bufferpos;
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int bufferlen;
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private ByteArrayBuffer linebuffer = null;
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String charset = HTTP.US_ASCII;
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean ascii = true;
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int maxLineLen = -1;
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private HttpTransportMetricsImpl metrics;
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected void init(final InputStream instream, int buffersize, final HttpParams params) {
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (instream == null) {
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Input stream may not be null");
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffersize <= 0) {
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Buffer size may not be negative or zero");
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (params == null) {
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("HTTP parameters may not be null");
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.instream = instream;
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.buffer = new byte[buffersize];
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.bufferpos = 0;
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.bufferlen = 0;
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.linebuffer = new ByteArrayBuffer(buffersize);
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.charset = HttpProtocolParams.getHttpElementCharset(params);
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII)
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                     || this.charset.equalsIgnoreCase(HTTP.ASCII);
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.maxLineLen = params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1);
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.metrics = new HttpTransportMetricsImpl();
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected int fillBuffer() throws IOException {
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // compact the buffer if necessary
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.bufferpos > 0) {
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int len = this.bufferlen - this.bufferpos;
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (len > 0) {
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                System.arraycopy(this.buffer, this.bufferpos, this.buffer, 0, len);
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.bufferpos = 0;
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.bufferlen = len;
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int l;
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int off = this.bufferlen;
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int len = this.buffer.length - off;
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        l = this.instream.read(this.buffer, off, len);
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (l == -1) {
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return -1;
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.bufferlen = off + l;
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.metrics.incrementBytesTransferred(l);
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return l;
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected boolean hasBufferedData() {
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.bufferpos < this.bufferlen;
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public int read() throws IOException {
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int noRead = 0;
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!hasBufferedData()) {
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            noRead = fillBuffer();
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (noRead == -1) {
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return -1;
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.buffer[this.bufferpos++] & 0xff;
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public int read(final byte[] b, int off, int len) throws IOException {
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (b == null) {
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return 0;
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int noRead = 0;
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!hasBufferedData()) {
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            noRead = fillBuffer();
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (noRead == -1) {
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return -1;
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int chunk = this.bufferlen - this.bufferpos;
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (chunk > len) {
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            chunk = len;
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.bufferpos += chunk;
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return chunk;
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public int read(final byte[] b) throws IOException {
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (b == null) {
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return 0;
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return read(b, 0, b.length);
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int locateLF() {
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (int i = this.bufferpos; i < this.bufferlen; i++) {
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (this.buffer[i] == HTTP.LF) {
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                return i;
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return -1;
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public int readLine(final CharArrayBuffer charbuffer) throws IOException {
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charbuffer == null) {
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.linebuffer.clear();
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int noRead = 0;
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean retry = true;
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (retry) {
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // attempt to find end of line (LF)
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int i = locateLF();
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (i != -1) {
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // end of line found.
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (this.linebuffer.isEmpty()) {
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // the entire line is preset in the read buffer
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    return lineFromReadBuffer(charbuffer, i);
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                retry = false;
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                int len = i + 1 - this.bufferpos;
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.linebuffer.append(this.buffer, this.bufferpos, len);
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.bufferpos = i + 1;
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // end of line not found
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (hasBufferedData()) {
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    int len = this.bufferlen - this.bufferpos;
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    this.linebuffer.append(this.buffer, this.bufferpos, len);
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    this.bufferpos = this.bufferlen;
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                noRead = fillBuffer();
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (noRead == -1) {
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    retry = false;
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (this.maxLineLen > 0 && this.linebuffer.length() >= this.maxLineLen) {
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new IOException("Maximum line length limit exceeded");
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (noRead == -1 && this.linebuffer.isEmpty()) {
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // indicate the end of stream
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return -1;
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return lineFromLineBuffer(charbuffer);
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int lineFromLineBuffer(final CharArrayBuffer charbuffer)
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throws IOException {
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // discard LF if found
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int l = this.linebuffer.length();
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (l > 0) {
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (this.linebuffer.byteAt(l - 1) == HTTP.LF) {
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                l--;
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.linebuffer.setLength(l);
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // discard CR if found
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (l > 0) {
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (this.linebuffer.byteAt(l - 1) == HTTP.CR) {
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    l--;
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    this.linebuffer.setLength(l);
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        l = this.linebuffer.length();
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.ascii) {
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            charbuffer.append(this.linebuffer, 0, l);
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // This is VERY memory inefficient, BUT since non-ASCII charsets are
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // NOT meant to be used anyway, there's no point optimizing it
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            String s = new String(this.linebuffer.buffer(), 0, l, this.charset);
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            charbuffer.append(s);
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return l;
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int lineFromReadBuffer(final CharArrayBuffer charbuffer, int pos)
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throws IOException {
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int off = this.bufferpos;
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int len;
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.bufferpos = pos + 1;
241633bc1a8d332166c7fca3e4f6fa8e5603f1618beDan Bornstein        // BEGIN android-changed
242633bc1a8d332166c7fca3e4f6fa8e5603f1618beDan Bornstein        // The first test below was fixed to not try to skip beyond the
243633bc1a8d332166c7fca3e4f6fa8e5603f1618beDan Bornstein        // start of the live part of the buffer.
244633bc1a8d332166c7fca3e4f6fa8e5603f1618beDan Bornstein        if (pos > off && this.buffer[pos - 1] == HTTP.CR) {
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // skip CR if found
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos--;
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
248633bc1a8d332166c7fca3e4f6fa8e5603f1618beDan Bornstein        // END android-changed
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        len = pos - off;
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.ascii) {
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            charbuffer.append(this.buffer, off, len);
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // This is VERY memory inefficient, BUT since non-ASCII charsets are
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // NOT meant to be used anyway, there's no point optimizing it
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            String s = new String(this.buffer, off, len, this.charset);
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            charbuffer.append(s);
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return len;
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public String readLine() throws IOException {
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer charbuffer = new CharArrayBuffer(64);
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int l = readLine(charbuffer);
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (l != -1) {
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return charbuffer.toString();
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return null;
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpTransportMetrics getMetrics() {
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.metrics;
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
276