001: /*
002: * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.io;
027:
028: import java.util.Arrays;
029:
030: /**
031: * This class implements a character buffer that can be used as an Writer.
032: * The buffer automatically grows when data is written to the stream. The data
033: * can be retrieved using toCharArray() and toString().
034: * <P>
035: * Note: Invoking close() on this class has no effect, and methods
036: * of this class can be called after the stream has closed
037: * without generating an IOException.
038: *
039: * @author Herb Jellinek
040: * @version 1.31, 05/05/07
041: * @since JDK1.1
042: */
043: public class CharArrayWriter extends Writer {
044: /**
045: * The buffer where data is stored.
046: */
047: protected char buf[];
048:
049: /**
050: * The number of chars in the buffer.
051: */
052: protected int count;
053:
054: /**
055: * Creates a new CharArrayWriter.
056: */
057: public CharArrayWriter() {
058: this (32);
059: }
060:
061: /**
062: * Creates a new CharArrayWriter with the specified initial size.
063: *
064: * @param initialSize an int specifying the initial buffer size.
065: * @exception IllegalArgumentException if initialSize is negative
066: */
067: public CharArrayWriter(int initialSize) {
068: if (initialSize < 0) {
069: throw new IllegalArgumentException(
070: "Negative initial size: " + initialSize);
071: }
072: buf = new char[initialSize];
073: }
074:
075: /**
076: * Writes a character to the buffer.
077: */
078: public void write(int c) {
079: synchronized (lock) {
080: int newcount = count + 1;
081: if (newcount > buf.length) {
082: buf = Arrays.copyOf(buf, Math.max(buf.length << 1,
083: newcount));
084: }
085: buf[count] = (char) c;
086: count = newcount;
087: }
088: }
089:
090: /**
091: * Writes characters to the buffer.
092: * @param c the data to be written
093: * @param off the start offset in the data
094: * @param len the number of chars that are written
095: */
096: public void write(char c[], int off, int len) {
097: if ((off < 0) || (off > c.length) || (len < 0)
098: || ((off + len) > c.length) || ((off + len) < 0)) {
099: throw new IndexOutOfBoundsException();
100: } else if (len == 0) {
101: return;
102: }
103: synchronized (lock) {
104: int newcount = count + len;
105: if (newcount > buf.length) {
106: buf = Arrays.copyOf(buf, Math.max(buf.length << 1,
107: newcount));
108: }
109: System.arraycopy(c, off, buf, count, len);
110: count = newcount;
111: }
112: }
113:
114: /**
115: * Write a portion of a string to the buffer.
116: * @param str String to be written from
117: * @param off Offset from which to start reading characters
118: * @param len Number of characters to be written
119: */
120: public void write(String str, int off, int len) {
121: synchronized (lock) {
122: int newcount = count + len;
123: if (newcount > buf.length) {
124: buf = Arrays.copyOf(buf, Math.max(buf.length << 1,
125: newcount));
126: }
127: str.getChars(off, off + len, buf, count);
128: count = newcount;
129: }
130: }
131:
132: /**
133: * Writes the contents of the buffer to another character stream.
134: *
135: * @param out the output stream to write to
136: * @throws IOException If an I/O error occurs.
137: */
138: public void writeTo(Writer out) throws IOException {
139: synchronized (lock) {
140: out.write(buf, 0, count);
141: }
142: }
143:
144: /**
145: * Appends the specified character sequence to this writer.
146: *
147: * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
148: * behaves in exactly the same way as the invocation
149: *
150: * <pre>
151: * out.write(csq.toString()) </pre>
152: *
153: * <p> Depending on the specification of <tt>toString</tt> for the
154: * character sequence <tt>csq</tt>, the entire sequence may not be
155: * appended. For instance, invoking the <tt>toString</tt> method of a
156: * character buffer will return a subsequence whose content depends upon
157: * the buffer's position and limit.
158: *
159: * @param csq
160: * The character sequence to append. If <tt>csq</tt> is
161: * <tt>null</tt>, then the four characters <tt>"null"</tt> are
162: * appended to this writer.
163: *
164: * @return This writer
165: *
166: * @since 1.5
167: */
168: public CharArrayWriter append(CharSequence csq) {
169: String s = (csq == null ? "null" : csq.toString());
170: write(s, 0, s.length());
171: return this ;
172: }
173:
174: /**
175: * Appends a subsequence of the specified character sequence to this writer.
176: *
177: * <p> An invocation of this method of the form <tt>out.append(csq, start,
178: * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
179: * exactly the same way as the invocation
180: *
181: * <pre>
182: * out.write(csq.subSequence(start, end).toString()) </pre>
183: *
184: * @param csq
185: * The character sequence from which a subsequence will be
186: * appended. If <tt>csq</tt> is <tt>null</tt>, then characters
187: * will be appended as if <tt>csq</tt> contained the four
188: * characters <tt>"null"</tt>.
189: *
190: * @param start
191: * The index of the first character in the subsequence
192: *
193: * @param end
194: * The index of the character following the last character in the
195: * subsequence
196: *
197: * @return This writer
198: *
199: * @throws IndexOutOfBoundsException
200: * If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
201: * is greater than <tt>end</tt>, or <tt>end</tt> is greater than
202: * <tt>csq.length()</tt>
203: *
204: * @since 1.5
205: */
206: public CharArrayWriter append(CharSequence csq, int start, int end) {
207: String s = (csq == null ? "null" : csq).subSequence(start, end)
208: .toString();
209: write(s, 0, s.length());
210: return this ;
211: }
212:
213: /**
214: * Appends the specified character to this writer.
215: *
216: * <p> An invocation of this method of the form <tt>out.append(c)</tt>
217: * behaves in exactly the same way as the invocation
218: *
219: * <pre>
220: * out.write(c) </pre>
221: *
222: * @param c
223: * The 16-bit character to append
224: *
225: * @return This writer
226: *
227: * @since 1.5
228: */
229: public CharArrayWriter append(char c) {
230: write(c);
231: return this ;
232: }
233:
234: /**
235: * Resets the buffer so that you can use it again without
236: * throwing away the already allocated buffer.
237: */
238: public void reset() {
239: count = 0;
240: }
241:
242: /**
243: * Returns a copy of the input data.
244: *
245: * @return an array of chars copied from the input data.
246: */
247: public char toCharArray()[] {
248: synchronized (lock) {
249: return Arrays.copyOf(buf, count);
250: }
251: }
252:
253: /**
254: * Returns the current size of the buffer.
255: *
256: * @return an int representing the current size of the buffer.
257: */
258: public int size() {
259: return count;
260: }
261:
262: /**
263: * Converts input data to a string.
264: * @return the string.
265: */
266: public String toString() {
267: synchronized (lock) {
268: return new String(buf, 0, count);
269: }
270: }
271:
272: /**
273: * Flush the stream.
274: */
275: public void flush() {
276: }
277:
278: /**
279: * Close the stream. This method does not release the buffer, since its
280: * contents might still be required. Note: Invoking this method in this class
281: * will have no effect.
282: */
283: public void close() {
284: }
285:
286: }
|