1 |
/* |
2 |
* $Id: StringBuffer.h,v 1.4 2007-08-18 08:52:18 maya Exp $ |
3 |
*/ |
4 |
|
5 |
#ifndef _YCL_STRINGBUFFER_H_ |
6 |
#define _YCL_STRINGBUFFER_H_ |
7 |
|
8 |
#if _MSC_VER >= 1000 |
9 |
#pragma once |
10 |
#endif // _MSC_VER >= 1000 |
11 |
|
12 |
#include <YCL/common.h> |
13 |
|
14 |
#include <YCL/String.h> |
15 |
|
16 |
#include <malloc.h> |
17 |
|
18 |
namespace yebisuya { |
19 |
|
20 |
// 可変長の文字列を扱うためのクラス。 |
21 |
class StringBuffer { |
22 |
private: |
23 |
// 文字列を格納するバッファ。 |
24 |
char* buffer; |
25 |
// 現在有効な文字列の長さ。 |
26 |
size_t validLength; |
27 |
// バッファの大きさ。 |
28 |
size_t bufferSize; |
29 |
enum { |
30 |
// バッファを広げる際に使用するサイズ。 |
31 |
INIT_CAPACITY = 16, |
32 |
}; |
33 |
// バッファを初期化する。 |
34 |
// 引数: |
35 |
// source 初期文字列。 |
36 |
// length 初期文字列の長さ。 |
37 |
// capacity バッファの初期サイズ。 |
38 |
void init(const char* source, size_t length, size_t capacity) { |
39 |
if ((capacity != 0 || length != 0) && capacity < length + INIT_CAPACITY) |
40 |
capacity = length + INIT_CAPACITY; |
41 |
validLength = length; |
42 |
bufferSize = capacity; |
43 |
if (bufferSize == 0) { |
44 |
buffer = NULL; |
45 |
}else{ |
46 |
buffer = new char[bufferSize]; |
47 |
} |
48 |
memcpy(buffer, source, validLength); |
49 |
memset(buffer + validLength, '\0', bufferSize - validLength); |
50 |
} |
51 |
public: |
52 |
// デフォルトコンストラクタ。 |
53 |
StringBuffer() { |
54 |
init(NULL, 0, 0); |
55 |
} |
56 |
// バッファの初期サイズを指定するコンストラクタ。 |
57 |
// 引数: |
58 |
// capacity バッファの初期サイズ。 |
59 |
StringBuffer(size_t capacity) { |
60 |
init(NULL, 0, capacity); |
61 |
} |
62 |
// バッファの初期文字列を指定するコンストラクタ。 |
63 |
// 引数: |
64 |
// source 初期文字列。 |
65 |
StringBuffer(const char* source) { |
66 |
init(source, strlen(source), 0); |
67 |
} |
68 |
// コピーコンストラクタ。 |
69 |
// 引数: |
70 |
// source 初期文字列。 |
71 |
StringBuffer(const StringBuffer& source) { |
72 |
init(source.buffer, source.validLength, source.bufferSize); |
73 |
} |
74 |
// デストラクタ。 |
75 |
~StringBuffer() { |
76 |
delete[] buffer; |
77 |
} |
78 |
|
79 |
// 現在有効な文字列の長さを取得する。 |
80 |
// 返値: |
81 |
// 有効な文字列の長さ。 |
82 |
size_t length()const { |
83 |
return validLength; |
84 |
} |
85 |
// バッファのサイズを取得する。 |
86 |
// 返値: |
87 |
// バッファのサイズ。 |
88 |
size_t capacity()const { |
89 |
return bufferSize; |
90 |
} |
91 |
// バッファのサイズを指定の長さが収まるように調節する。 |
92 |
// 引数: |
93 |
// newLength 調節する長さ。 |
94 |
void ensureCapacity(size_t newLength) { |
95 |
if (bufferSize < newLength) { |
96 |
char* oldBuffer = buffer; |
97 |
init(oldBuffer, validLength, newLength + INIT_CAPACITY); |
98 |
delete[] oldBuffer; |
99 |
} |
100 |
} |
101 |
// 有効な文字列長を変更する。 |
102 |
// 引数: |
103 |
// newLength 新しい文字列長。 |
104 |
void setLength(size_t newLength) { |
105 |
if (validLength < newLength) |
106 |
ensureCapacity(newLength); |
107 |
validLength = newLength; |
108 |
} |
109 |
// 指定の位置の文字を取得する。 |
110 |
// 引数: |
111 |
// index 文字の位置。 |
112 |
// 返値: |
113 |
// 指定の位置の文字。 |
114 |
char charAt(size_t index)const { |
115 |
return index >= 0 && index < validLength ? buffer[index] : '\0'; |
116 |
} |
117 |
// 指定の位置の文字を取得する。 |
118 |
// 引数: |
119 |
// index 文字の位置。 |
120 |
// 返値: |
121 |
// 指定の位置の文字の参照。 |
122 |
char& charAt(size_t index) { |
123 |
if (index < 0) { |
124 |
index = 0; |
125 |
}else if (index >= validLength) { |
126 |
ensureCapacity(validLength + 1); |
127 |
index = validLength++; |
128 |
} |
129 |
return buffer[index]; |
130 |
} |
131 |
// 指定の位置の文字を変更する。 |
132 |
// 引数: |
133 |
// index 変更する文字の位置。 |
134 |
// chr 変更する文字。 |
135 |
void setCharAt(int index, char chr) { |
136 |
charAt(index) = chr; |
137 |
} |
138 |
// 文字を追加する。 |
139 |
// 引数: |
140 |
// chr 追加する文字。 |
141 |
// 返値: |
142 |
// 追加結果。 |
143 |
StringBuffer& append(char chr) { |
144 |
charAt(validLength) = chr; |
145 |
return *this; |
146 |
} |
147 |
// 文字列を追加する。 |
148 |
// 引数: |
149 |
// source 追加する文字列。 |
150 |
// 返値: |
151 |
// 追加結果。 |
152 |
StringBuffer& append(const char* source) { |
153 |
return append(source, strlen(source)); |
154 |
} |
155 |
// 文字列を追加する。 |
156 |
// 引数: |
157 |
// source 追加する文字列。 |
158 |
// length 追加する文字列の長さ。 |
159 |
// 返値: |
160 |
// 追加結果。 |
161 |
StringBuffer& append(const char* source, size_t length) { |
162 |
size_t oldLength = validLength; |
163 |
ensureCapacity(validLength + length); |
164 |
memcpy(buffer + oldLength, source, length); |
165 |
validLength += length; |
166 |
return *this; |
167 |
} |
168 |
// 指定の位置の文字を削除する。 |
169 |
// 引数: |
170 |
// start 削除する位置。 |
171 |
// 返値: |
172 |
// 削除結果。 |
173 |
StringBuffer& remove(size_t index) { |
174 |
return remove(index, index + 1); |
175 |
} |
176 |
// 指定の位置の文字列を削除する。 |
177 |
// 引数: |
178 |
// start 削除する先頭位置。 |
179 |
// end 削除する終わりの位置。 |
180 |
// 返値: |
181 |
// 削除結果。 |
182 |
StringBuffer& remove(size_t start, size_t end) { |
183 |
if (start <= 0) |
184 |
start = 0; |
185 |
if (start < end) { |
186 |
if (end < validLength){ |
187 |
memcpy(buffer + start, buffer + end, validLength - end); |
188 |
validLength -= end - start; |
189 |
}else{ |
190 |
validLength = start; |
191 |
} |
192 |
} |
193 |
return *this; |
194 |
} |
195 |
// 指定の位置の文字列を置換する。 |
196 |
// 引数: |
197 |
// start 置換する先頭位置。 |
198 |
// end 置換する終わりの位置。 |
199 |
// source 置換する文字列。 |
200 |
// 返値: |
201 |
// 置換結果。 |
202 |
StringBuffer& replace(size_t start, size_t end, const char* source) { |
203 |
if (start < 0) |
204 |
start = 0; |
205 |
if (end > validLength) |
206 |
end = validLength; |
207 |
if (start < end) { |
208 |
size_t length = strlen(source); |
209 |
size_t oldLength = validLength; |
210 |
ensureCapacity(validLength += length - (end - start)); |
211 |
memcpy(buffer + start + length, buffer + end, oldLength - end); |
212 |
memcpy(buffer + start, source, length); |
213 |
} |
214 |
return *this; |
215 |
} |
216 |
// 指定の位置の文字列を取得する。 |
217 |
// 引数: |
218 |
// start 取得する文字列の先頭位置。 |
219 |
// 返値: |
220 |
// 指定の位置の文字列。 |
221 |
String substring(size_t index)const { |
222 |
if (index < 0) |
223 |
index = 0; |
224 |
return String(buffer + index, validLength - index); |
225 |
} |
226 |
// 指定の位置の文字列を取得する。 |
227 |
// 引数: |
228 |
// start 取得する文字列の先頭位置。 |
229 |
// end 取得する文字列の終わりの位置。 |
230 |
// 返値: |
231 |
// 指定の位置の文字列。 |
232 |
String substring(size_t start, size_t end)const { |
233 |
if (start < 0) |
234 |
start = 0; |
235 |
if (end > validLength) |
236 |
end = validLength; |
237 |
return String(buffer + start, end - start); |
238 |
} |
239 |
// 指定の位置に文字を挿入する。 |
240 |
// 引数: |
241 |
// index 挿入する位置。 |
242 |
// source 挿入する文字。 |
243 |
// 返値: |
244 |
// 挿入結果。 |
245 |
StringBuffer& insert(size_t index, char chr) { |
246 |
return insert(index, &chr, 1); |
247 |
} |
248 |
// 指定の位置に文字列を挿入する。 |
249 |
// 引数: |
250 |
// index 挿入する位置。 |
251 |
// source 挿入する文字列。 |
252 |
// 返値: |
253 |
// 挿入結果。 |
254 |
StringBuffer& insert(size_t index, const char* source) { |
255 |
return insert(index, source, strlen(source)); |
256 |
} |
257 |
// 指定の位置に文字列を挿入する。 |
258 |
// 引数: |
259 |
// index 挿入する位置。 |
260 |
// source 挿入する文字列。 |
261 |
// length 文字列の長さ。 |
262 |
// 返値: |
263 |
// 挿入結果。 |
264 |
StringBuffer& insert(size_t index, const char* source, size_t length) { |
265 |
if (index < 0) |
266 |
index = 0; |
267 |
else if (index >= validLength) |
268 |
index = validLength; |
269 |
size_t oldLength = validLength; |
270 |
ensureCapacity(validLength + length); |
271 |
char* temp = (char*) alloca(oldLength - index); |
272 |
memcpy(temp, buffer + index, oldLength - index); |
273 |
memcpy(buffer + index, source, length); |
274 |
memcpy(buffer + index + length, temp, oldLength - index); |
275 |
validLength += length; |
276 |
return *this; |
277 |
} |
278 |
// 文字列を反転する。 |
279 |
// 返値: |
280 |
// 反転結果。 |
281 |
StringBuffer& reverse() { |
282 |
char* temporary = (char*) alloca(sizeof (char) * validLength); |
283 |
char* dst = temporary + validLength; |
284 |
char* src = buffer; |
285 |
while (temporary < dst) { |
286 |
if (String::isLeadByte(*src)) { |
287 |
char pre = *src++; |
288 |
*--dst = *src++; |
289 |
*--dst = pre; |
290 |
}else{ |
291 |
*--dst = *src++; |
292 |
} |
293 |
} |
294 |
memcpy(buffer, temporary, validLength); |
295 |
return *this; |
296 |
} |
297 |
// 文字列を取得する。 |
298 |
// 返値: |
299 |
// 現在設定されている文字列。 |
300 |
String toString()const { |
301 |
return String(buffer, validLength); |
302 |
} |
303 |
|
304 |
// 一文字だけの文字列に変更する。 |
305 |
// 引数: |
306 |
// 変更する一文字。 |
307 |
// 返値: |
308 |
// 変更結果。 |
309 |
StringBuffer& set(char chr) { |
310 |
ensureCapacity(1); |
311 |
buffer[0] = chr; |
312 |
validLength = 1; |
313 |
return *this; |
314 |
} |
315 |
// 指定の文字列に変更する。 |
316 |
// 引数: |
317 |
// source 変更する文字列。 |
318 |
// 返値: |
319 |
// 変更結果。 |
320 |
StringBuffer& set(const char* source) { |
321 |
size_t length = strlen(source); |
322 |
ensureCapacity(validLength = length); |
323 |
memcpy(buffer, source, length); |
324 |
return *this; |
325 |
} |
326 |
|
327 |
// char*に変換するキャスト演算子。 |
328 |
// バッファのアドレスを取得する。 |
329 |
// 返値: |
330 |
// バッファのアドレス。 |
331 |
operator char*() { |
332 |
return buffer; |
333 |
} |
334 |
// Stringに変換するキャスト演算子。 |
335 |
// 文字列を取得する。 |
336 |
// 返値: |
337 |
// 現在設定されている文字列。 |
338 |
operator String()const { |
339 |
return toString(); |
340 |
} |
341 |
// 代入演算子。 |
342 |
// 一文字だけの文字列に変更する。 |
343 |
// 引数: |
344 |
// ch 変更する一文字。 |
345 |
// 返値: |
346 |
// 代入結果。 |
347 |
StringBuffer& operator=(char ch) { |
348 |
return set(ch); |
349 |
} |
350 |
// 代入演算子。 |
351 |
// 指定の文字列に変更する。 |
352 |
// 引数: |
353 |
// source 変更する文字列。 |
354 |
// 返値: |
355 |
// 代入結果。 |
356 |
StringBuffer& operator=(const char* source) { |
357 |
return set(source); |
358 |
} |
359 |
// 連結代入演算子。 |
360 |
// 文字を追加する。 |
361 |
// 引数: |
362 |
// ch 追加する文字。 |
363 |
// 返値: |
364 |
// 代入結果。 |
365 |
StringBuffer& operator+=(char ch) { |
366 |
return append(ch); |
367 |
} |
368 |
// 連結代入演算子。 |
369 |
// 文字列を追加する。 |
370 |
// 引数: |
371 |
// source 追加する文字列。 |
372 |
// 返値: |
373 |
// 代入結果。 |
374 |
StringBuffer& operator+=(const char* source) { |
375 |
return append(source); |
376 |
} |
377 |
}; |
378 |
|
379 |
} |
380 |
|
381 |
#endif//_YCL_STRINGBUFFER_H_ |