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

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

Stringなどで例外を投げるようにした。
#147の解決。
CType ASCII文字判定関数群の追加。

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