001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.io;
019:
020: import org.apache.harmony.luni.util.Msg;
021:
022: /**
023: * CharArrayWriter is used as a character output stream on a character array.
024: * The buffer used to store the written characters will grow as needed to
025: * accommodate more characters as they are written.
026: */
027: public class CharArrayWriter extends Writer {
028:
029: /**
030: * Buffer for characters
031: */
032: protected char[] buf;
033:
034: /**
035: * The ending index of the buffer.
036: */
037: protected int count;
038:
039: /**
040: * Constructs a new CharArrayWriter which has a buffer allocated with the
041: * default size of 32 characters. The buffer is also the <code>lock</code>
042: * used to synchronize access to this Writer.
043: */
044: public CharArrayWriter() {
045: super ();
046: buf = new char[32];
047: lock = buf;
048: }
049:
050: /**
051: * Constructs a new CharArrayWriter which has a buffer allocated with the
052: * size of <code>initialSize</code> characters. The buffer is also the
053: * <code>lock</code> used to synchronize access to this Writer.
054: *
055: * @param initialSize
056: * the initial size of this CharArrayWriters buffer.
057: */
058: public CharArrayWriter(int initialSize) {
059: super ();
060: if (initialSize < 0) {
061: throw new IllegalArgumentException(Msg.getString("K005e")); //$NON-NLS-1$
062: }
063: buf = new char[initialSize];
064: lock = buf;
065: }
066:
067: /**
068: * Close this Writer. This is the concrete implementation required. This
069: * particular implementation does nothing.
070: */
071: @Override
072: public void close() {
073: /* empty */
074: }
075:
076: private void expand(int i) {
077: /* Can the buffer handle @i more chars, if not expand it */
078: if (count + i <= buf.length) {
079: return;
080: }
081:
082: int newLen = Math.max(2 * buf.length, count + i);
083: char[] newbuf = new char[newLen];
084: System.arraycopy(buf, 0, newbuf, 0, count);
085: buf = newbuf;
086: }
087:
088: /**
089: * Flush this Writer. This is the concrete implementation required. This
090: * particular implementation does nothing.
091: */
092: @Override
093: public void flush() {
094: /* empty */
095: }
096:
097: /**
098: * Reset this Writer. The current write position is reset to the beginning
099: * of the buffer. All written characters are lost and the size of this
100: * writer is now 0.
101: */
102: public void reset() {
103: synchronized (lock) {
104: count = 0;
105: }
106: }
107:
108: /**
109: * Answer the size of this Writer in characters. This number changes if this
110: * Writer is reset or as more characters are written to it.
111: *
112: * @return int this CharArrayWriters current size in characters.
113: */
114: public int size() {
115: synchronized (lock) {
116: return count;
117: }
118: }
119:
120: /**
121: * Answer the contents of the receiver as a char array. The array returned
122: * is a copy and any modifications made to this Writer after are not
123: * reflected in the result.
124: *
125: * @return char[] this CharArrayWriters contents as a new char array.
126: */
127: public char[] toCharArray() {
128: synchronized (lock) {
129: char[] result = new char[count];
130: System.arraycopy(buf, 0, result, 0, count);
131: return result;
132: }
133: }
134:
135: /**
136: * Answer the contents of this CharArrayWriter as a String. The String
137: * returned is a copy and any modifications made to this Writer after are
138: * not reflected in the result.
139: *
140: * @return String this CharArrayWriters contents as a new String.
141: */
142: @Override
143: public String toString() {
144: synchronized (lock) {
145: return new String(buf, 0, count);
146: }
147: }
148:
149: /**
150: * Writes <code>count</code> characters starting at <code>offset</code>
151: * in <code>buf</code> to this CharArrayWriter.
152: *
153: * @param c
154: * the non-null array containing characters to write.
155: * @param offset
156: * offset in buf to retrieve characters
157: * @param len
158: * maximum number of characters to write
159: */
160: @Override
161: public void write(char[] c, int offset, int len) {
162: // avoid int overflow
163: if (offset < 0 || offset > c.length || len < 0
164: || len > c.length - offset) {
165: throw new IndexOutOfBoundsException();
166: }
167: synchronized (lock) {
168: expand(len);
169: System.arraycopy(c, offset, this .buf, this .count, len);
170: this .count += len;
171: }
172: }
173:
174: /**
175: * Writes the specified character <code>oneChar</code> to this
176: * CharArrayWriter. This implementation writes the low order two bytes to
177: * the Stream.
178: *
179: * @param oneChar
180: * The character to write
181: */
182: @Override
183: public void write(int oneChar) {
184: synchronized (lock) {
185: expand(1);
186: buf[count++] = (char) oneChar;
187: }
188: }
189:
190: /**
191: * Writes <code>count</code> number of characters starting at
192: * <code>offset</code> from the String <code>str</code> to this
193: * CharArrayWriter.
194: *
195: * @param str
196: * the non-null String containing the characters to write.
197: * @param offset
198: * the starting point to retrieve characters.
199: * @param len
200: * the number of characters to retrieve and write.
201: */
202: @Override
203: public void write(String str, int offset, int len) {
204: if (str == null) {
205: throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
206: }
207: // avoid int overflow
208: if (offset < 0 || offset > str.length() || len < 0
209: || len > str.length() - offset) {
210: throw new StringIndexOutOfBoundsException();
211: }
212: synchronized (lock) {
213: expand(len);
214: str.getChars(offset, offset + len, buf, this .count);
215: this .count += len;
216: }
217: }
218:
219: /**
220: * Writes the contents of this CharArrayWriter to another Writer. The output
221: * is all the characters that have been written to the receiver since the
222: * last reset or since the creation.
223: *
224: * @param out
225: * the non-null Writer on which to write the contents.
226: *
227: * @throws IOException
228: * If an error occurs attempting to write the contents out.
229: */
230: public void writeTo(Writer out) throws IOException {
231: synchronized (lock) {
232: out.write(buf, 0, count);
233: }
234: }
235:
236: /**
237: * Append a char <code>c</code>to the CharArrayWriter. The
238: * CharArrayWriter.append(<code>c</code>) works the same way as
239: * CharArrayWriter.write(<code>c</code>).
240: *
241: * @param c
242: * The character appended to the CharArrayWriter.
243: * @return The CharArrayWriter.
244: * @see Writer#append(char)
245: */
246: @Override
247: public CharArrayWriter append(char c) {
248: write(c);
249: return this ;
250: }
251:
252: /**
253: * Append a CharSequence <code>csq</code> to the CharArrayWriter. The
254: * CharArrayWriter.append(<code>csq</code>) works the same way as
255: * CharArrayWriter.write(<code>csq</code>.toString()). If
256: * <code>csq</code> is null, then then "null" will be substituted for
257: * <code>csq</code>.
258: *
259: * @param csq
260: * The CharSequence appended to the CharArrayWriter.
261: * @return The CharArrayWriter
262: * @see Writer#append(CharSequence)
263: */
264: @Override
265: public CharArrayWriter append(CharSequence csq) {
266: if (null == csq) {
267: append(TOKEN_NULL, 0, TOKEN_NULL.length());
268: } else {
269: append(csq, 0, csq.length());
270: }
271: return this ;
272: }
273:
274: /**
275: * Append a subsequence of a CharSequence <code>csq</code> to the
276: * CharArrayWriter. The first char and the last char of the subsequnce is
277: * specified by the parameter <code>start</code> and <code>end</code>.
278: * The CharArrayWriter.append(<code>csq</code>) works the same way as
279: * CharArrayWriter.write(<code>csq</code>.subSequence(<code>start</code>,<code>end</code>).toString).
280: * If <code>csq</code> is null, then "null" will be substituted for
281: * <code>csq</code>.
282: *
283: * @param csq
284: * The CharSequence appended to the CharArrayWriter.
285: * @param start
286: * The index of the first char in the CharSequence appended to
287: * the CharArrayWriter.
288: * @param end
289: * The index of the char after the last one in the CharSequence
290: * appended to the CharArrayWriter.
291: * @return The CharArrayWriter.
292: * @throws IndexOutOfBoundsException
293: * If start is less than end, end is greater than the length of
294: * the CharSequence, or start or end is negative.
295: * @see Writer#append(CharSequence, int, int)
296: */
297: @Override
298: public CharArrayWriter append(CharSequence csq, int start, int end) {
299: if (null == csq) {
300: csq = TOKEN_NULL;
301: }
302: String output = csq.subSequence(start, end).toString();
303: write(output, 0, output.length());
304: return this;
305: }
306: }
|