source: trunk/Include/Classes/System/Text/StringBuilder.ab@ 497

Last change on this file since 497 was 497, checked in by イグトランス (egtra), 16 years ago

インクルードガードとその他不要な前処理定義などの削除

File size: 14.8 KB
Line 
1'Classes/System/Text/StringBuilder.ab
2
3Namespace System
4Namespace Text
5
6Class StringBuilder
7Public
8 Sub StringBuilder()
9 initialize(1024)
10 End Sub
11
12 Sub StringBuilder(capacity As Long)
13 initialize(capacity)
14 End Sub
15
16 Sub StringBuilder(s As String)
17 initialize(s, 0, s.Length, s.Length * 2)
18 End Sub
19
20 Sub StringBuilder(capacity As Long, maxCapacity As Long)
21 initialize(capacity, maxCapacity)
22 End Sub
23
24 Sub StringBuilder(s As String, capacity As Long)
25 initialize(s, 0, s.Length, capacity)
26 End Sub
27
28 Sub StringBuilder(s As String, startIndex As Long, length As Long, capacity As Long)
29 initialize(s, startIndex, length, capacity)
30 End Sub
31
32 'Methods
33
34 Function Append(x As Boolean) As StringBuilder
35 Append(Str$(x))
36 Return This
37 End Function
38
39 Function Append(x As Char) As StringBuilder
40 EnsureCapacity(size + 1)
41 separateBuffer()
42 chars[size] = x
43 size++
44 Return This
45 End Function
46#ifdef UNICODE
47 Function Append(x As SByte) As StringBuilder
48 ActiveBasic.Strings.Detail.FormatIntegerD(This, x, DWORD_MAX, 0, 0)
49 Return This
50 End Function
51#endif
52 Function Append(x As Byte) As StringBuilder
53 ActiveBasic.Strings.Detail.FormatIntegerU(This, x, DWORD_MAX, 0, 0)
54 Return This
55 End Function
56
57 Function Append(x As Integer) As StringBuilder
58 ActiveBasic.Strings.Detail.FormatIntegerD(This, x, DWORD_MAX, 0, 0)
59 Return This
60 End Function
61#ifndef UNICODE
62 Function Append(x As Word) As StringBuilder
63 ActiveBasic.Strings.Detail.FormatIntegerU(This, x, DWORD_MAX, 0, 0)
64 Return This
65 End Function
66#endif
67 Function Append(x As Long) As StringBuilder
68 ActiveBasic.Strings.Detail.FormatIntegerD(This, x, DWORD_MAX, 0, 0)
69 Return This
70 End Function
71
72 Function Append(x As DWord) As StringBuilder
73 ActiveBasic.Strings.Detail.FormatIntegerU(This, x, DWORD_MAX, 0, 0)
74 Return This
75 End Function
76
77 Function Append(x As Int64) As StringBuilder
78 ActiveBasic.Strings.Detail.FormatIntegerLD(This, x, DWORD_MAX, 0, 0)
79 Return This
80 End Function
81
82 Function Append(x As QWord) As StringBuilder
83 ActiveBasic.Strings.Detail.FormatIntegerLU(This, x, DWORD_MAX, 0, 0)
84 Return This
85 End Function
86
87 Function Append(x As Single) As StringBuilder
88 ActiveBasic.Strings.Detail.FormatFloatG(This, x, DWORD_MAX, 0, 0)
89 Return This
90 End Function
91
92 Function Append(x As Double) As StringBuilder
93 ActiveBasic.Strings.Detail.FormatFloatG(This, x, DWORD_MAX, 0, 0)
94 Return This
95 End Function
96
97 Function Append(x As Object) As StringBuilder
98 Append(x.ToString)
99 Return This
100 End Function
101
102 Function Append(c As Char, n As Long) As StringBuilder
103 EnsureCapacity(size + n)
104 ActiveBasic.Strings.ChrFill(VarPtr(chars[size]), n As SIZE_T, c)
105 size += n
106 Return This
107 End Function
108
109 Function Append(s As String) As StringBuilder
110 If Not String.IsNullOrEmpty(s) Then
111 appendCore(s, 0, s.Length)
112 End If
113 Return This
114 End Function
115
116 Function Append(s As String, startIndex As Long, count As Long) As StringBuilder
117 Return Append(StrPtr(s), startIndex, count)
118 End Function
119
120 Function Append(s As *Char, startIndex As Long, count As Long) As StringBuilder
121 If s = 0 Then
122 If startIndex = 0 And count = 0 Then
123 Return This
124 Else
125 Throw New ArgumentNullException("StringBuilder.Append: An argument is null", "s")
126 End If
127 ElseIf startIndex < 0 Or count < 0 Then
128 Throw New ArgumentOutOfRangeException("StringBuilder.Append: One or more arguments are out of range value.", "startIndex or count or both")
129 End If
130 appendCore(s, startIndex, count)
131 Return This
132 End Function
133Private
134 Sub appendCore(s As *Char, start As Long, count As Long)
135 EnsureCapacity(size + count)
136 separateBuffer()
137 ActiveBasic.Strings.ChrCopy(VarPtr(chars[size]), VarPtr(s[start]), count As SIZE_T)
138 size += count
139 End Sub
140
141 Sub appendCore(s As String, start As Long, count As Long)
142 EnsureCapacity(size + count)
143 separateBuffer()
144 s.CopyTo(start, chars, size, count)
145 size += count
146 End Sub
147Public
148 'AppendFormat
149
150 Function AppendLine() As StringBuilder
151 separateBuffer()
152 Append(Environment.NewLine)
153 Return This
154 End Function
155
156 Function AppendLine(s As String) As StringBuilder
157 EnsureCapacity(Capacity + s.Length + Environment.NewLine.Length)
158 separateBuffer()
159 Append(s)
160 Append(Environment.NewLine)
161 Return This
162 End Function
163
164 Const Sub CopyTo(sourceIndex As Long, ByRef dest[] As Char, destIndex As Long, count As Long)
165 If dest = 0 Then
166 Throw New ArgumentNullException("StringBuilder.CopyTo: An argument is null", "sourceIndex")
167 ElseIf size < sourceIndex + count Or sourceIndex < 0 Or destIndex < 0 Or count < 0 Then
168 Throw New ArgumentOutOfRangeException("StringBuilder.CopyTo: One or more arguments are out of range value.", "startIndex or count or both")
169 End If
170
171 memcpy(VarPtr(dest[destIndex]), VarPtr(chars[sourceIndex]), count * SizeOf (Char))
172 End Sub
173
174 Function EnsureCapacity(c As Long) As Long
175 If c < 0 Or c > MaxCapacity Then
176 Throw New ArgumentOutOfRangeException("StringBuilder.Append: An argument is out of range value.", "c")
177 ElseIf c > Capacity Then
178 Dim p = GC_malloc_atomic((c + 1) * SizeOf (Char)) As *Char
179 ActiveBasic.Strings.ChrCopy(p, chars, size As SIZE_T)
180 chars = p
181 capacity = c
182 stringized = False
183 End If
184 End Function
185
186 'Override Function Equals(o As Object) As Boolean
187
188 Const Function Equals(s As StringBuilder) As Boolean
189 Return ActiveBasic.Strings.StrCmp(chars, s.chars) = 0 _
190 And capacity = s.capacity _
191 And maxCapacity = s.maxCapacity
192 End Function
193
194 Override Function GetHashCode() As Long
195#ifdef UNICODE
196 Dim n = size
197#else
198 Dim n = (size + 1) >> 1
199#endif
200 Return _System_GetHashFromWordArray(chars As *Word, n As SIZE_T) Xor capacity Xor maxCapacity
201 End Function
202
203 Function Insert(i As Long, x As Boolean) As StringBuilder
204 rangeCheck(i)
205 insertCore(i, Str$(x))
206 Return This
207 End Function
208
209 Function Insert(i As Long, x As Char) As StringBuilder
210 Insert(i, VarPtr(x), 0, 1)
211 Return This
212 End Function
213#ifdef UNICODE
214 Function Insert(i As Long, x As SByte) As StringBuilder
215 rangeCheck(i)
216 insertCore(i, Str$(x As Long))
217 Return This
218 End Function
219#else
220 Function Insert(i As Long, x As Word) As StringBuilder
221 rangeCheck(i)
222 insertCore(i, Str$(x As DWord))
223 Return This
224 End Function
225#endif
226
227 Function Insert(i As Long, x As Byte) As StringBuilder
228 rangeCheck(i)
229 insertCore(i, Str$(x))
230 Return This
231 End Function
232
233 Function Insert(i As Long, x As Integer) As StringBuilder
234 rangeCheck(i)
235 insertCore(i, Str$(x))
236 Return This
237 End Function
238
239 Function Insert(i As Long, x As Long) As StringBuilder
240 rangeCheck(i)
241 insertCore(i, Str$(x))
242 Return This
243 End Function
244
245 Function Insert(i As Long, x As DWord) As StringBuilder
246 rangeCheck(i)
247 insertCore(i, Str$(x))
248 Return This
249 End Function
250
251 Function Insert(i As Long, x As Int64) As StringBuilder
252 rangeCheck(i)
253 insertCore(i, Str$(x))
254 Return This
255 End Function
256
257 Function Insert(i As Long, x As Single) As StringBuilder
258 rangeCheck(i)
259 insertCore(i, Str$(x))
260 Return This
261 End Function
262
263 Function Insert(i As Long, x As Double) As StringBuilder
264 rangeCheck(i)
265 insertCore(i, Str$(x))
266 Return This
267 End Function
268
269 Function Insert(i As Long, s As String) As StringBuilder
270 rangeCheck(i)
271 insertCore(i, s)
272 Return This
273 End Function
274
275 Function Insert(i As Long, o As Object) As StringBuilder
276 rangeCheck(i)
277 insertCore(i, o.ToString)
278 Return This
279 End Function
280
281 Function Insert(index As Long, x As String, n As Long) As StringBuilder
282 rangeCheck(index)
283 If n < 0 Then
284 Throw New ArgumentOutOfRangeException("StringBuilder.Insert: An argument is out of range value.", "n")
285 End If
286 Dim len = x.Length
287 Dim lenTotal = len * n
288 Dim newSize = size + lenTotal
289 EnsureCapacity(newSize)
290 separateBuffer()
291
292 Dim i As Long
293 For i = 0 To ELM(n)
294 x.CopyTo(0, chars, size + i * len, len)
295 Next
296 size = newSize
297 Return This
298 End Function
299
300 Function Insert(i As Long, x As *Char, index As Long, count As Long) As StringBuilder
301 rangeCheck(i)
302 If x = 0 Then
303 Throw New ArgumentNullException("StringBuilder.Insert: An argument is null", "x")
304 ElseIf index < 0 Or count < 0 Then
305 Throw New ArgumentOutOfRangeException("StringBuilder.Append: One or more arguments are out of range value.", "index or count or both")
306 End If
307
308 Dim newSize = size + count
309 EnsureCapacity(newSize)
310 separateBuffer()
311 ActiveBasic.Strings.ChrMove(VarPtr(chars[i + count]), VarPtr(chars[i]), (size - i) As SIZE_T)
312 ActiveBasic.Strings.ChrCopy(VarPtr(chars[i]), VarPtr(x[index]), count As SIZE_T)
313 size = newSize
314 Return This
315 End Function
316
317Private
318 Sub insertCore(i As Long, s As String)
319 Dim newSize = size + s.Length
320 EnsureCapacity(newSize)
321 separateBuffer()
322 ActiveBasic.Strings.ChrMove(VarPtr(chars[i + s.Length]), VarPtr(chars[i]), (size - i) As SIZE_T)
323 s.CopyTo(0, chars, i, s.Length)
324 size = newSize
325 End Sub
326Public
327
328 Function Remove(startIndex As Long, length As Long) As StringBuilder
329 rangeCheck(startIndex, length)
330 separateBuffer()
331
332 Dim moveStart = startIndex + length
333 ActiveBasic.Strings.ChrMove(
334 VarPtr(chars[startIndex]), VarPtr(chars[moveStart]), (size - moveStart) As SIZE_T)
335 size -= length
336 Return This
337 End Function
338
339 Function Replace(oldChar As Char, newChar As Char) As StringBuilder
340 replaceCore(oldChar, newChar, 0, size)
341 Return This
342 End Function
343
344 Function Replace(oldStr As String, newStr As String) As StringBuilder
345 replaceCore(oldStr, newStr, 0, size)
346 Return This
347 End Function
348
349 Function Replace(oldChar As Char, newChar As Char, startIndex As Long, count As Long) As StringBuilder
350 rangeCheck(startIndex, count)
351 replaceCore(oldChar, newChar, startIndex, count)
352 Return This
353 End Function
354
355 Function Replace(oldStr As String, newStr As String, startIndex As Long, count As Long) As StringBuilder
356 rangeCheck(startIndex, count)
357 replaceCore(oldStr, newStr, startIndex, count)
358 Return This
359 End Function
360Private
361 Sub replaceCore(oldChar As Char, newChar As Char, start As Long, count As Long)
362 separateBuffer()
363 Dim i As Long
364 Dim last = ELM(start + count)
365 For i = start To last
366 If chars[i] = oldChar Then
367 chars[i] = newChar
368 End If
369 Next
370 End Sub
371
372 Sub replaceCore(oldStr As String, newStr As String, start As Long, count As Long)
373 If ActiveBasic.IsNothing(oldStr) Then
374 Throw New ArgumentNullException("StringBuilder.Replace: An argument is null", "oldStr")
375 ElseIf oldStr.Length = 0 Then
376 Throw New ArgumentException("StringBuilder.Replace: The argument 'oldStr' is empty string. ", "oldStr")
377 End If
378
379 Dim s = New StringBuilder(capacity, maxCapacity)
380 Dim curPos = start
381 Dim last = start + count
382 Do
383 Dim nextPos = ActiveBasic.Strings.ChrFind(VarPtr(chars[curPos]) As *Char, size As SIZE_T, StrPtr(oldStr), oldStr.Length As SIZE_T) As Long
384 If nextPos = -1 As SIZE_T Or curPos > last Then
385 s.appendCore(chars, curPos, size - curPos)
386 Exit Do
387 End If
388
389 s.appendCore(chars, curPos, nextPos As Long)
390 s.Append(newStr)
391 curPos += nextPos As Long + oldStr.Length
392 Loop
393 chars = s.chars
394 size = s.size
395 End Sub
396
397Public
398 Override Function ToString() As String
399 chars[size] = 0
400 Return New String(This)
401 End Function
402
403 Const Function ToString(startIndex As Long, length As Long) As String
404 rangeCheck(startIndex, length)
405 Return New String(chars, startIndex, length)
406 End Function
407
408 Const Function Operator [](i As Long) As Char
409 Return Chars[i]
410 End Function
411
412 Sub Operator []=(i As Long, c As Char)
413 Chars[i] = c
414 End Sub
415
416 'Properties
417 Const Function Capacity() As Long
418 Return capacity
419 End Function
420
421 Sub Capacity(c As Long)
422 If c < size Or c > MaxCapacity Then 'sizeとの比較でcが負の場合も対応
423 Throw New ArgumentOutOfRangeException("StringBuilder.Capacity: An argument is out of range value.", "c")
424 End If
425 EnsureCapacity(c)
426 End Sub
427
428 Const Function Chars(i As Long) As Char
429 If i >= Length Or i < 0 Then
430 Throw New IndexOutOfRangeException("StringBuilder.Chars: The index argument 'i' is out of range value.")
431 End If
432 Return chars[i]
433 End Function
434
435 Sub Chars(i As Long, c As Char)
436 If i >= Length Or i < 0 Then
437 Throw New ArgumentOutOfRangeException("StringBuilder.Chars: An argument is out of range value.", "i")
438 End If
439 chars[i] = c
440 End Sub
441
442 Const Function Length() As Long
443 Return size
444 End Function
445
446 Sub Length(i As Long)
447 EnsureCapacity(i) 'iが適切な値かどうかの確認はこの中で行う
448 If size < i Then
449 ActiveBasic.Strings.ChrFill(VarPtr(chars[size]), (i - size + 1) As SIZE_T, 0 As Char)
450 End If
451 size = i
452 End Sub
453
454 Const Function MaxCapacity() As Long
455 Return maxCapacity
456 End Function
457
458 Function __Chars() As *Char
459 Return chars
460 End Function
461
462 Sub __Stringized()
463 stringized = True
464 End Sub
465
466Private
467 Sub initialize(capacity As Long, maxCapacity = LONG_MAX As Long)
468 If capacity < 0 Or maxCapacity < 1 Or maxCapacity < capacity Then
469 Throw New ArgumentOutOfRangeException("StringBuilder constructor: One or more arguments are out of range value.", "capacity or maxCapacity or both")
470 End If
471
472 If capacity = 0 Then
473 This.capacity = 1024
474 Else
475 This.capacity = capacity
476 End If
477
478 This.maxCapacity = maxCapacity
479 This.size = 0
480 This.chars = GC_malloc_atomic((This.capacity + 1) * SizeOf (Char))
481 End Sub
482
483 Sub initialize(s As String, startIndex As Long, length As Long, capacity As Long, maxCapacity = LONG_MAX As Long)
484 StringBuilder.rangeCheck2(s.Length, startIndex, length)
485
486 initialize(Math.Max(capacity, length), maxCapacity)
487
488 If Not String.IsNullOrEmpty(s) Then
489 s.CopyTo(startIndex, chars, 0, length)
490 size = length
491 End If
492 End Sub
493
494 Sub rangeCheck(index As Long)
495 If index < 0 Or index > size Then
496 Throw New ArgumentOutOfRangeException("StringBuilder: Index argument is out of range value.")
497 End If
498 End Sub
499
500 Sub rangeCheck(startIndex As Long, count As Long)
501 StringBuilder.rangeCheck2(size, startIndex, count)
502 End Sub
503
504 Static Sub rangeCheck2(length As Long, startIndex As Long, count As Long)
505 'length < 0は判定に入っていないことに注意
506 If startIndex < 0 Or count < 0 Or startIndex + count > length Then
507 Throw New ArgumentOutOfRangeException("StringBuilder: One or more arguments are out of range value.", "startIndex or count or both")
508 End If
509 End Sub
510
511 Sub separateBuffer()
512 If stringized Then
513 Dim newChars = GC_malloc_atomic(SizeOf (Char) * capacity) As *Char
514 ActiveBasic.Strings.ChrCopy(newChars, chars, capacity As SIZE_T)
515 chars = newChars
516 stringized = False
517 End If
518 End Sub
519
520 chars As *Char
521 maxCapacity As Long
522 capacity As Long
523 size As Long
524 stringized As Boolean
525End Class
526
527End Namespace 'Text
528End Namespace 'System
529
530'暫定
531Function StrPtr(sb As System.Text.StringBuilder) As *Char
532 Return sb.__Chars
533End Function
Note: See TracBrowser for help on using the repository browser.