1 /*
2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.util.Arrays;
29
30 /**
31 * This class implements a character buffer that can be used as an Writer.
32 * The buffer automatically grows when data is written to the stream. The data
33 * can be retrieved using toCharArray() and toString().
34 * <P>
35 * Note: Invoking close() on this class has no effect, and methods
36 * of this class can be called after the stream has closed
37 * without generating an IOException.
38 *
39 * @author Herb Jellinek
40 * @since 1.1
41 */
42 public
43 class CharArrayWriter extends Writer {
44 /**
45 * The buffer where data is stored.
46 */
47 protected char buf[];
48
49 /**
50 * The number of chars in the buffer.
51 */
52 protected int count;
53
54 /**
55 * Creates a new CharArrayWriter.
56 */
57 public CharArrayWriter() {
58 this(32);
59 }
60
61 /**
62 * Creates a new CharArrayWriter with the specified initial size.
63 *
64 * @param initialSize an int specifying the initial buffer size.
65 * @exception IllegalArgumentException if initialSize is negative
66 */
67 public CharArrayWriter(int initialSize) {
68 if (initialSize < 0) {
69 throw new IllegalArgumentException("Negative initial size: "
70 + initialSize);
71 }
72 buf = new char[initialSize];
73 }
74
75 /**
76 * Writes a character to the buffer.
77 */
78 public void write(int c) {
79 synchronized (lock) {
80 int newcount = count + 1;
81 if (newcount > buf.length) {
82 buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
83 }
84 buf[count] = (char)c;
85 count = newcount;
86 }
87 }
88
89 /**
90 * Writes characters to the buffer.
91 * @param c the data to be written
92 * @param off the start offset in the data
93 * @param len the number of chars that are written
94 *
95 * @throws IndexOutOfBoundsException
96 * If {@code off} is negative, or {@code len} is negative,
97 * or {@code off + len} is negative or greater than the length
98 * of the given array
99 */
100 public void write(char c[], int off, int len) {
101 if ((off < 0) || (off > c.length) || (len < 0) ||
102 ((off + len) > c.length) || ((off + len) < 0)) {
103 throw new IndexOutOfBoundsException();
104 } else if (len == 0) {
105 return;
106 }
107 synchronized (lock) {
108 int newcount = count + len;
109 if (newcount > buf.length) {
110 buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
111 }
112 System.arraycopy(c, off, buf, count, len);
113 count = newcount;
114 }
115 }
116
117 /**
118 * Write a portion of a string to the buffer.
119 * @param str String to be written from
120 * @param off Offset from which to start reading characters
121 * @param len Number of characters to be written
122 *
123 * @throws IndexOutOfBoundsException
124 * If {@code off} is negative, or {@code len} is negative,
125 * or {@code off + len} is negative or greater than the length
126 * of the given string
127 */
128 public void write(String str, int off, int len) {
129 synchronized (lock) {
130 int newcount = count + len;
131 if (newcount > buf.length) {
132 buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
133 }
134 str.getChars(off, off + len, buf, count);
135 count = newcount;
136 }
137 }
138
139 /**
140 * Writes the contents of the buffer to another character stream.
141 *
142 * @param out the output stream to write to
143 * @throws IOException If an I/O error occurs.
144 */
145 public void writeTo(Writer out) throws IOException {
146 synchronized (lock) {
147 out.write(buf, 0, count);
148 }
149 }
150
151 /**
152 * Appends the specified character sequence to this writer.
153 *
154 * <p> An invocation of this method of the form {@code out.append(csq)}
155 * behaves in exactly the same way as the invocation
156 *
157 * <pre>
158 * out.write(csq.toString()) </pre>
159 *
160 * <p> Depending on the specification of {@code toString} for the
161 * character sequence {@code csq}, the entire sequence may not be
162 * appended. For instance, invoking the {@code toString} method of a
163 * character buffer will return a subsequence whose content depends upon
164 * the buffer's position and limit.
165 *
166 * @param csq
167 * The character sequence to append. If {@code csq} is
168 * {@code null}, then the four characters {@code "null"} are
169 * appended to this writer.
170 *
171 * @return This writer
172 *
173 * @since 1.5
174 */
175 public CharArrayWriter append(CharSequence csq) {
176 String s = String.valueOf(csq);
177 write(s, 0, s.length());
178 return this;
179 }
180
181 /**
182 * Appends a subsequence of the specified character sequence to this writer.
183 *
184 * <p> An invocation of this method of the form
185 * {@code out.append(csq, start, end)} when
186 * {@code csq} is not {@code null}, behaves in
187 * exactly the same way as the invocation
188 *
189 * <pre>
190 * out.write(csq.subSequence(start, end).toString()) </pre>
191 *
192 * @param csq
193 * The character sequence from which a subsequence will be
194 * appended. If {@code csq} is {@code null}, then characters
195 * will be appended as if {@code csq} contained the four
196 * characters {@code "null"}.
197 *
198 * @param start
199 * The index of the first character in the subsequence
200 *
201 * @param end
202 * The index of the character following the last character in the
203 * subsequence
204 *
205 * @return This writer
206 *
207 * @throws IndexOutOfBoundsException
208 * If {@code start} or {@code end} are negative, {@code start}
209 * is greater than {@code end}, or {@code end} is greater than
210 * {@code csq.length()}
211 *
212 * @since 1.5
213 */
214 public CharArrayWriter append(CharSequence csq, int start, int end) {
215 if (csq == null) csq = "null";
216 return append(csq.subSequence(start, end));
217 }
218
219 /**
220 * Appends the specified character to this writer.
221 *
222 * <p> An invocation of this method of the form {@code out.append(c)}
223 * behaves in exactly the same way as the invocation
224 *
225 * <pre>
226 * out.write(c) </pre>
227 *
228 * @param c
229 * The 16-bit character to append
230 *
231 * @return This writer
232 *
233 * @since 1.5
234 */
235 public CharArrayWriter append(char c) {
236 write(c);
237 return this;
238 }
239
240 /**
241 * Resets the buffer so that you can use it again without
242 * throwing away the already allocated buffer.
243 */
244 public void reset() {
245 count = 0;
246 }
247
248 /**
249 * Returns a copy of the input data.
250 *
251 * @return an array of chars copied from the input data.
252 */
253 public char[] toCharArray() {
254 synchronized (lock) {
255 return Arrays.copyOf(buf, count);
256 }
257 }
258
259 /**
260 * Returns the current size of the buffer.
261 *
262 * @return an int representing the current size of the buffer.
263 */
264 public int size() {
265 return count;
266 }
267
268 /**
269 * Converts input data to a string.
270 * @return the string.
271 */
272 public String toString() {
273 synchronized (lock) {
274 return new String(buf, 0, count);
275 }
276 }
277
278 /**
279 * Flush the stream.
280 */
281 public void flush() { }
282
283 /**
284 * Close the stream. This method does not release the buffer, since its
285 * contents might still be required. Note: Invoking this method in this class
286 * will have no effect.
287 */
288 public void close() { }
289
290 }
291