StringBufferInputStream.java revision dd828f42a5c83b4270d4fbf6fce2da1878f1e84a
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 * @since Android 1.0
29 */
30@Deprecated
31public class StringBufferInputStream extends InputStream {
32    /**
33     * The source string containing the data to read.
34     *
35     * @since Android 1.0
36     */
37    protected String buffer;
38
39    /**
40     * The total number of characters in the source string.
41     *
42     * @since Android 1.0
43     */
44    protected int count;
45
46    /**
47     * The current position within the source string.
48     *
49     * @since Android 1.0
50     */
51    protected int pos;
52
53    /**
54     * Construct a new {@code StringBufferInputStream} with {@code str} as
55     * source. The size of the stream is set to the {@code length()} of the
56     * string.
57     *
58     * @param str
59     *            the source string for this stream.
60     * @throws NullPointerException
61     *             if {@code str} is {@code null}.
62     * @since Android 1.0
63     */
64    public StringBufferInputStream(String str) {
65        if (str == null) {
66            throw new NullPointerException();
67        }
68        buffer = str;
69        count = str.length();
70    }
71
72    /**
73     * Returns the number of bytes that are available before this stream will
74     * block.
75     *
76     * @return the number of bytes available before blocking.
77     * @since Android 1.0
78     */
79    @Override
80    public synchronized int available() {
81        return count - pos;
82    }
83
84    /**
85     * Reads a single byte from the source string and returns it as an integer
86     * in the range from 0 to 255. Returns -1 if the end of the source string
87     * has been reached.
88     *
89     * @return the byte read or -1 if the end of the source string has been
90     *         reached.
91     * @since Android 1.0
92     */
93    @Override
94    public synchronized int read() {
95        return pos < count ? buffer.charAt(pos++) & 0xFF : -1;
96    }
97
98    /**
99     * Reads at most {@code length} bytes from the source string and stores them
100     * in the byte array {@code b} starting at {@code offset}.
101     *
102     * @param b
103     *            the byte array in which to store the bytes read.
104     * @param offset
105     *            the initial position in {@code b} to store the bytes read from
106     *            this stream.
107     * @param length
108     *            the maximum number of bytes to store in {@code b}.
109     * @return the number of bytes actually read or -1 if the end of the source
110     *         string has been reached.
111     * @throws ArrayIndexOutOfBoundsException
112     *             if {@code offset < 0} or {@code length < 0}, or if
113     *             {@code offset + length} is greater than the length of
114     *             {@code b}.
115     * @throws NullPointerException
116     *             if {@code b} is {@code null}.
117     * @since Android 1.0
118     */
119    @Override
120    public synchronized int read(byte[] b, int offset, int length) {
121        // BEGIN android-note
122        // changed array notation to be consistent with the rest of harmony
123        // END android-note
124        // According to 22.7.6 should return -1 before checking other
125        // parameters.
126        if (pos >= count) {
127            return -1;
128        }
129        if (b == null) {
130            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
131        }
132        // avoid int overflow
133        // BEGIN android-changed
134        // Exception priorities (in case of multiple errors) differ from
135        // RI, but are spec-compliant.
136        // removed redundant check, used (offset | length) < 0
137        // instead of (offset < 0) || (length < 0) to safe one operation
138        if ((offset | length) < 0 || length > b.length - offset) {
139            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
140        }
141        // END android-changed
142        if (length == 0) {
143            return 0;
144        }
145
146        int copylen = count - pos < length ? count - pos : length;
147        for (int i = 0; i < copylen; i++) {
148            b[offset + i] = (byte) buffer.charAt(pos + i);
149        }
150        pos += copylen;
151        return copylen;
152    }
153
154    /**
155     * Resets this stream to the beginning of the source string.
156     *
157     * @since Android 1.0
158     */
159    @Override
160    public synchronized void reset() {
161        pos = 0;
162    }
163
164    /**
165     * Skips {@code n} characters in the source string. It does nothing and
166     * returns 0 if {@code n} is negative. Less than {@code n} characters are
167     * skipped if the end of the source string is reached before the operation
168     * completes.
169     *
170     * @param n
171     *            the number of characters to skip.
172     * @return the number of characters actually skipped.
173     * @since Android 1.0
174     */
175    @Override
176    public synchronized long skip(long n) {
177        if (n <= 0) {
178            return 0;
179        }
180
181        int numskipped;
182        if (this.count - pos < n) {
183            numskipped = this.count - pos;
184            pos = this.count;
185        } else {
186            numskipped = (int) n;
187            pos += n;
188        }
189        return numskipped;
190    }
191}
192