]>
Commit | Line | Data |
---|---|---|
ee9dd372 TT |
1 | // StringBuffer.java - Growable strings. |
2 | ||
3 | /* Copyright (C) 1998, 1999 Cygnus Solutions | |
4 | ||
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | package java.lang; | |
12 | import java.io.Serializable; | |
13 | ||
14 | /** | |
15 | * @author Tom Tromey <tromey@cygnus.com> | |
16 | * @date October 23, 1998. | |
17 | */ | |
18 | ||
19 | /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 | |
20 | */ | |
21 | ||
22 | public final class StringBuffer implements Serializable | |
23 | { | |
24 | public StringBuffer append (boolean bool) | |
25 | { | |
26 | return append (String.valueOf(bool)); | |
27 | } | |
28 | ||
29 | public synchronized StringBuffer append (char ch) | |
30 | { | |
31 | ensureCapacity (count + 1); | |
32 | value[count++] = ch; | |
33 | return this; | |
34 | } | |
35 | ||
36 | public StringBuffer append (int inum) | |
37 | { | |
38 | return append (String.valueOf(inum)); | |
39 | } | |
40 | ||
41 | public StringBuffer append (long lnum) | |
42 | { | |
43 | return append (String.valueOf(lnum)); | |
44 | } | |
45 | ||
46 | public StringBuffer append (float fnum) | |
47 | { | |
48 | return append (String.valueOf(fnum)); | |
49 | } | |
50 | ||
51 | public StringBuffer append (double dnum) | |
52 | { | |
53 | return append (String.valueOf(dnum)); | |
54 | } | |
55 | ||
56 | public StringBuffer append (Object obj) | |
57 | { | |
58 | return append (String.valueOf(obj)); | |
59 | } | |
60 | ||
61 | public synchronized StringBuffer append (String str) | |
62 | { | |
63 | if (str == null) | |
64 | str = "null"; | |
65 | int len = str.length(); | |
66 | ensureCapacity (count + len); | |
67 | str.getChars(0, len, value, count); | |
68 | count += len; | |
69 | return this; | |
70 | } | |
71 | ||
72 | public StringBuffer append (char[] data) | |
73 | { | |
74 | return append (data, 0, data.length); | |
75 | } | |
76 | ||
77 | public synchronized StringBuffer append (char[] data, int offset, int count) | |
78 | { | |
79 | ensureCapacity (this.count + count); | |
80 | System.arraycopy(data, offset, value, this.count, count); | |
81 | this.count += count; | |
82 | return this; | |
83 | } | |
84 | ||
85 | public int capacity () | |
86 | { | |
87 | return value.length; | |
88 | } | |
89 | ||
90 | public synchronized char charAt (int index) | |
91 | { | |
92 | if (index >= count) | |
93 | throw new StringIndexOutOfBoundsException (index); | |
94 | return value[index]; | |
95 | } | |
96 | ||
97 | public synchronized void ensureCapacity (int minimumCapacity) | |
98 | { | |
99 | if (shared || minimumCapacity > value.length) | |
100 | { | |
a0e894a8 TT |
101 | // We don't want to make a larger vector when `shared' is |
102 | // set. If we do, then setLength becomes very inefficient | |
103 | // when repeatedly reusing a StringBuffer in a loop. | |
104 | int max = (minimumCapacity > value.length | |
105 | ? value.length*2+2 | |
106 | : value.length); | |
107 | minimumCapacity = Math.max(minimumCapacity, max); | |
ee9dd372 TT |
108 | char[] nb = new char[minimumCapacity]; |
109 | System.arraycopy(value, 0, nb, 0, count); | |
110 | value = nb; | |
111 | shared = false; | |
112 | } | |
113 | } | |
114 | ||
115 | public synchronized void getChars (int srcOffset, int srcEnd, | |
116 | char[] dst, int dstOffset) | |
117 | { | |
118 | if (srcOffset < 0 || srcOffset > srcEnd) | |
119 | throw new StringIndexOutOfBoundsException (srcOffset); | |
120 | int todo = srcEnd - srcOffset; | |
121 | if (srcEnd > count || dstOffset + todo > count) | |
122 | throw new StringIndexOutOfBoundsException (srcEnd); | |
123 | System.arraycopy(value, srcOffset, dst, dstOffset, todo); | |
124 | } | |
125 | ||
126 | public StringBuffer insert (int offset, boolean bool) | |
127 | { | |
128 | return insert (offset, bool ? "true" : "false"); | |
129 | } | |
130 | ||
131 | public synchronized StringBuffer insert (int offset, char ch) | |
132 | { | |
133 | if (offset < 0 || offset > count) | |
134 | throw new StringIndexOutOfBoundsException (offset); | |
135 | ensureCapacity (count+1); | |
136 | System.arraycopy(value, offset, value, offset+1, count-offset); | |
137 | value[offset] = ch; | |
138 | count++; | |
139 | return this; | |
140 | } | |
141 | ||
142 | public StringBuffer insert (int offset, int inum) | |
143 | { | |
144 | return insert (offset, String.valueOf(inum)); | |
145 | } | |
146 | ||
147 | public StringBuffer insert (int offset, long lnum) | |
148 | { | |
149 | return insert (offset, String.valueOf(lnum)); | |
150 | } | |
151 | ||
152 | public StringBuffer insert (int offset, float fnum) | |
153 | { | |
154 | return insert (offset, String.valueOf(fnum)); | |
155 | } | |
156 | ||
157 | public StringBuffer insert (int offset, double dnum) | |
158 | { | |
159 | return insert (offset, String.valueOf(dnum)); | |
160 | } | |
161 | ||
162 | public StringBuffer insert (int offset, Object obj) | |
163 | { | |
164 | return insert (offset, String.valueOf(obj)); | |
165 | } | |
166 | ||
167 | public synchronized StringBuffer insert (int offset, String str) | |
168 | { | |
169 | if (offset < 0 || offset > count) | |
170 | throw new StringIndexOutOfBoundsException (offset); | |
171 | // Note that using `null' is from JDK 1.2. | |
172 | if (str == null) | |
173 | str = "null"; | |
174 | int len = str.length(); | |
175 | ensureCapacity(count+len); | |
176 | System.arraycopy(value, offset, value, offset+len, count-offset); | |
177 | str.getChars(0, len, value, offset); | |
178 | count += len; | |
179 | return this; | |
180 | } | |
181 | ||
182 | public synchronized StringBuffer insert (int offset, char[] data) | |
183 | { | |
184 | if (offset < 0 || offset > count) | |
185 | throw new StringIndexOutOfBoundsException (offset); | |
186 | int len = data.length; | |
187 | ensureCapacity (count+len); | |
188 | System.arraycopy(value, offset, value, offset+len, count-offset); | |
189 | System.arraycopy(data, 0, value, offset, len); | |
190 | count += len; | |
191 | return this; | |
192 | } | |
193 | ||
194 | public int length () | |
195 | { | |
196 | return count; | |
197 | } | |
198 | ||
199 | public synchronized StringBuffer reverse () | |
200 | { | |
201 | for (int i = 0; i < count / 2; ++i) | |
202 | { | |
203 | char c = value[i]; | |
204 | value[i] = value[count - i - 1]; | |
205 | value[count - i - 1] = c; | |
206 | } | |
207 | return this; | |
208 | } | |
209 | ||
210 | public synchronized void setCharAt (int index, char ch) | |
211 | { | |
212 | if (index < 0 || index >= count) | |
213 | throw new StringIndexOutOfBoundsException (index); | |
214 | // Call ensureCapacity to enforce copy-on-write. | |
215 | ensureCapacity (count); | |
216 | value[index] = ch; | |
217 | } | |
218 | ||
219 | public synchronized void setLength (int newLength) | |
220 | { | |
221 | if (newLength < 0) | |
222 | throw new StringIndexOutOfBoundsException (newLength); | |
223 | ||
224 | ensureCapacity (newLength); | |
225 | for (int i = count; i < newLength; ++i) | |
226 | value[i] = '\0'; | |
227 | count = newLength; | |
228 | } | |
229 | ||
230 | public StringBuffer () | |
231 | { | |
232 | this (16); | |
233 | } | |
234 | ||
235 | public StringBuffer (int capacity) | |
236 | { | |
237 | count = 0; | |
238 | value = new char[capacity]; | |
239 | shared = false; | |
240 | } | |
241 | ||
242 | public StringBuffer (String str) | |
243 | { | |
244 | // Note: nowhere does it say that we should handle a null | |
245 | // argument here. In fact, the JCL implies that we should not. | |
246 | // But this leads to an asymmetry: `null + ""' will fail, while | |
247 | // `"" + null' will work. | |
248 | if (str == null) | |
249 | str = "null"; | |
250 | count = str.length(); | |
251 | // JLS: The initial capacity of the string buffer is 16 plus the | |
252 | // length of the argument string. | |
253 | value = new char[count + 16]; | |
254 | str.getChars(0, count, value, 0); | |
255 | shared = false; | |
256 | } | |
257 | ||
258 | public String toString () | |
259 | { | |
260 | shared = true; | |
261 | return new String (this); | |
262 | } | |
263 | ||
264 | // The buffer. Note that this has permissions set this way so that | |
265 | // String can get the value. | |
266 | char[] value; | |
267 | ||
268 | // Index of next available character. Note that this has | |
269 | // permissions set this way so that String can get the value. | |
270 | int count; | |
271 | ||
272 | // True if we need to copy the buffer before writing to it again. | |
273 | // FIXME: JDK 1.2 doesn't specify this. The new buffer-growing | |
274 | // semantics make this less useful in that case, too. | |
275 | private boolean shared; | |
276 | } |