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 java.util.Arrays;
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("str == null");
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 buffer
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[] buffer, int offset, int length) {
103        if (buffer == null) {
104            throw new NullPointerException("buffer == null");
105        }
106        Arrays.checkOffsetAndCount(buffer.length, offset, length);
107        if (length == 0) {
108            return 0;
109        }
110
111        int copylen = count - pos < length ? count - pos : length;
112        for (int i = 0; i < copylen; i++) {
113            buffer[offset + i] = (byte) this.buffer.charAt(pos + i);
114        }
115        pos += copylen;
116        return copylen;
117    }
118
119    /**
120     * Resets this stream to the beginning of the source string.
121     */
122    @Override
123    public synchronized void reset() {
124        pos = 0;
125    }
126
127    /**
128     * Skips {@code charCount} characters in the source string. It does nothing and
129     * returns 0 if {@code charCount} is negative. Less than {@code charCount} characters are
130     * skipped if the end of the source string is reached before the operation
131     * completes.
132     *
133     * @return the number of characters actually skipped.
134     */
135    @Override
136    public synchronized long skip(long charCount) {
137        if (charCount <= 0) {
138            return 0;
139        }
140
141        int numskipped;
142        if (this.count - pos < charCount) {
143            numskipped = this.count - pos;
144            pos = this.count;
145        } else {
146            numskipped = (int) charCount;
147            pos += charCount;
148        }
149        return numskipped;
150    }
151}
152