1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.commons.csv;
20
21 /**
22 * A simple StringBuffer replacement that aims to
23 * reduce copying as much as possible. The buffer
24 * grows as necessary.
25 * This class is not thread safe.
26 *
27 * @author Ortwin Gl�ck
28 */
29 public class CharBuffer {
30
31 private char[] c;
32
33 /**
34 * Actually used number of characters in the array.
35 * It is also the index at which
36 * a new character will be inserted into <code>c</code>.
37 */
38 private int length;
39
40 /**
41 * Creates a new CharBuffer with an initial capacity of 32 characters.
42 */
43 public CharBuffer() {
44 this(32);
45 }
46
47 /**
48 * Creates a new CharBuffer with an initial capacity
49 * of <code>length</code> characters.
50 */
51 public CharBuffer(final int length) {
52 if (length == 0) {
53 throw new IllegalArgumentException("Can't create an empty CharBuffer");
54 }
55 this.c = new char[length];
56 }
57
58 /**
59 * Empties the buffer. The capacity still remains the same, so no memory is freed.
60 */
61 public void clear() {
62 length = 0;
63 }
64
65 /**
66 * Returns the number of characters in the buffer.
67 * @return the number of characters
68 */
69 public int length() {
70 return length;
71 }
72
73 /**
74 * Returns the current capacity of the buffer.
75 * @return the maximum number of characters that can be stored in this buffer without
76 * resizing it.
77 */
78 public int capacity() {
79 return c.length;
80 }
81
82
83 /**
84 * Appends the contents of <code>cb</code> to the end of this CharBuffer.
85 * @param cb the CharBuffer to append or null
86 */
87 public void append(final CharBuffer cb) {
88 if (cb == null) {
89 return;
90 }
91 provideCapacity(length + cb.length);
92 System.arraycopy(cb.c, 0, c, length, cb.length);
93 length += cb.length;
94 }
95
96 /**
97 * Appends <code>s</code> to the end of this CharBuffer.
98 * This method involves copying the new data once!
99 * @param s the String to append or null
100 */
101 public void append(final String s) {
102 if (s == null) {
103 return;
104 }
105 append(s.toCharArray());
106 }
107
108 /**
109 * Appends <code>sb</code> to the end of this CharBuffer.
110 * This method involves copying the new data once!
111 * @param sb the StringBuffer to append or null
112 */
113 public void append(final StringBuffer sb) {
114 if (sb == null) {
115 return;
116 }
117 provideCapacity(length + sb.length());
118 sb.getChars(0, sb.length(), c, length);
119 length += sb.length();
120 }
121
122 /**
123 * Appends <code>data</code> to the end of this CharBuffer.
124 * This method involves copying the new data once!
125 * @param data the char[] to append or null
126 */
127 public void append(final char[] data) {
128 if (data == null) {
129 return;
130 }
131 provideCapacity(length + data.length);
132 System.arraycopy(data, 0, c, length, data.length);
133 length += data.length;
134 }
135
136 /**
137 * Appends a single character to the end of this CharBuffer.
138 * This method involves copying the new data once!
139 * @param data the char to append
140 */
141 public void append(final char data) {
142 provideCapacity(length + 1);
143 c[length] = data;
144 length++;
145 }
146
147 /**
148 * Shrinks the capacity of the buffer to the current length if necessary.
149 * This method involves copying the data once!
150 */
151 public void shrink() {
152 if (c.length == length) {
153 return;
154 }
155 char[] newc = new char[length];
156 System.arraycopy(c, 0, newc, 0, length);
157 c = newc;
158 }
159
160 /**
161 * Removes trailing whitespace.
162 */
163 public void trimTrailingWhitespace() {
164 while (length>0 && Character.isWhitespace(c[length-1])) {
165 length--;
166 }
167 }
168
169 /**
170 * Returns the contents of the buffer as a char[]. The returned array may
171 * be the internal array of the buffer, so the caller must take care when
172 * modifying it.
173 * This method allows to avoid copying if the caller knows the exact capacity
174 * before.
175 * @return
176 */
177 public char[] getCharacters() {
178 if (c.length == length) {
179 return c;
180 }
181 char[] chars = new char[length];
182 System.arraycopy(c, 0, chars, 0, length);
183 return chars;
184 }
185
186 /**
187 * Returns the character at the specified position.
188 */
189 public char charAt(int pos) {
190 return c[pos];
191 }
192
193 /**
194 * Converts the contents of the buffer into a StringBuffer.
195 * This method involves copying the new data once!
196 * @return
197 */
198 public StringBuffer toStringBuffer() {
199 StringBuffer sb = new StringBuffer(length);
200 sb.append(c, 0, length);
201 return sb;
202 }
203
204 /**
205 * Converts the contents of the buffer into a StringBuffer.
206 * This method involves copying the new data once!
207 * @return
208 */
209 public String toString() {
210 return new String(c, 0, length);
211 }
212
213 /**
214 * Copies the data into a new array of at least <code>capacity</code> size.
215 * @param capacity
216 */
217 public void provideCapacity(final int capacity) {
218 if (c.length >= capacity) {
219 return;
220 }
221 int newcapacity = ((capacity*3)>>1) + 1;
222 char[] newc = new char[newcapacity];
223 System.arraycopy(c, 0, newc, 0, length);
224 c = newc;
225 }
226 }