StringBufferInputStream.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.io;
19
20import org.apache.harmony.luni.util.Msg;
21
22/**
23 * A specialized {@link InputStream} that reads bytes from a {@code String} in
24 * a sequential manner.
25 *
26 * @deprecated Use {@link StringReader}
27 */
28@Deprecated
29public class StringBufferInputStream extends InputStream {
30    /**
31     * The source string containing the data to read.
32     */
33    protected String buffer;
34
35    /**
36     * The total number of characters in the source string.
37     */
38    protected int count;
39
40    /**
41     * The current position within the source string.
42     */
43    protected int pos;
44
45    /**
46     * Construct a new {@code StringBufferInputStream} with {@code str} as
47     * source. The size of the stream is set to the {@code length()} of the
48     * string.
49     *
50     * @param str
51     *            the source string for this stream.
52     * @throws NullPointerException
53     *             if {@code str} is {@code null}.
54     */
55    public StringBufferInputStream(String str) {
56        if (str == null) {
57            throw new NullPointerException();
58        }
59        buffer = str;
60        count = str.length();
61    }
62
63    @Override
64    public synchronized int available() {
65        return count - pos;
66    }
67
68    /**
69     * Reads a single byte from the source string and returns it as an integer
70     * in the range from 0 to 255. Returns -1 if the end of the source string
71     * has been reached.
72     *
73     * @return the byte read or -1 if the end of the source string has been
74     *         reached.
75     */
76    @Override
77    public synchronized int read() {
78        return pos < count ? buffer.charAt(pos++) & 0xFF : -1;
79    }
80
81    /**
82     * Reads at most {@code length} bytes from the source string and stores them
83     * in the byte array {@code b} starting at {@code offset}.
84     *
85     * @param b
86     *            the byte array in which to store the bytes read.
87     * @param offset
88     *            the initial position in {@code b} to store the bytes read from
89     *            this stream.
90     * @param length
91     *            the maximum number of bytes to store in {@code b}.
92     * @return the number of bytes actually read or -1 if the end of the source
93     *         string has been reached.
94     * @throws IndexOutOfBoundsException
95     *             if {@code offset < 0} or {@code length < 0}, or if
96     *             {@code offset + length} is greater than the length of
97     *             {@code b}.
98     * @throws NullPointerException
99     *             if {@code b} is {@code null}.
100     */
101    @Override
102    public synchronized int read(byte[] b, int offset, int length) {
103        // BEGIN android-note
104        // changed array notation to be consistent with the rest of harmony
105        // END android-note
106        // According to 22.7.6 should return -1 before checking other
107        // parameters.
108        if (pos >= count) {
109            return -1;
110        }
111        if (b == null) {
112            // K0047=buffer is null
113            throw new NullPointerException(Msg.getString("K0047"));
114        }
115        // avoid int overflow
116        if (offset < 0 || offset > b.length) {
117            // K002e=Offset out of bounds \: {0}
118            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset));
119        }
120        if (length < 0 || length > b.length - offset) {
121            // K0031=Length out of bounds \: {0}
122            throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length));
123        }
124
125        if (length == 0) {
126            return 0;
127        }
128
129        int copylen = count - pos < length ? count - pos : length;
130        for (int i = 0; i < copylen; i++) {
131            b[offset + i] = (byte) buffer.charAt(pos + i);
132        }
133        pos += copylen;
134        return copylen;
135    }
136
137    /**
138     * Resets this stream to the beginning of the source string.
139     */
140    @Override
141    public synchronized void reset() {
142        pos = 0;
143    }
144
145    /**
146     * Skips {@code n} characters in the source string. It does nothing and
147     * returns 0 if {@code n} is negative. Less than {@code n} characters are
148     * skipped if the end of the source string is reached before the operation
149     * completes.
150     *
151     * @param n
152     *            the number of characters to skip.
153     * @return the number of characters actually skipped.
154     */
155    @Override
156    public synchronized long skip(long n) {
157        if (n <= 0) {
158            return 0;
159        }
160
161        int numskipped;
162        if (this.count - pos < n) {
163            numskipped = this.count - pos;
164            pos = this.count;
165        } else {
166            numskipped = (int) n;
167            pos += n;
168        }
169        return numskipped;
170    }
171}
172