source: Include/Classes/System/Text/StringBuilder.ab@ 272

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

StringBuilderを追加。String不変へ。共通の文字列操作関数をActiveBasic.Strings内に配置(設計に検討の余地あり)。

File size: 13.8 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 If s = 0 Then
123 If startIndex = 0 And count = 0 Then
124 Return This
125 Else
126 'Throw ArgumentNullException
127 End If
128 End If
129 StringBuilder.rangeCheck2(s.Length, startIndex, count)
130 appendCore(s, startIndex, count)
131 Return This
132 End Function
133
134 Function Append(s As *StrChar, startIndex As Long, count As Long) As StringBuilder
135 If s = 0 Then
136 If startIndex = 0 And count = 0 Then
137 Return This
138 Else
139 'Throw ArgumentNullException
140 End If
141 ElseIf startIndex < 0 Or count < 0 Then
142 'Throw ArgumentOutOfRangeException
143 End If
144 appendCore(s, startIndex, count)
145 Return This
146 End Function
147Private
148 Sub appendCore(s As *StrChar, start As Long, count As Long)
149 EnsureCapacity(size + count)
150 separateBuffer()
151 ActiveBasic.Strings.ChrCopy(VarPtr(chars[size]), VarPtr(s[start]), count As SIZE_T)
152 size += count
153 End Sub
154
155 Sub appendCore(s As String, start As Long, count As Long)
156 EnsureCapacity(size + count)
157 separateBuffer()
158 s.CopyTo(start, chars, size, count)
159 size += count
160 End Sub
161Public
162 'AppendFormat
163
164 Function AppendLine() As StringBuilder
165 separateBuffer()
166 Append(Environment.NewLine)
167 Return This
168 End Function
169
170 Function AppendLine(s As String) As StringBuilder
171 EnsureCapacity(Capacity + s.Length + Environment.NewLine.Length)
172 separateBuffer()
173 Append(s)
174 Append(Environment.NewLine)
175 Return This
176 End Function
177
178 Const Sub CopyTo(sourceIndex As Long, ByRef dest[] As StrChar, destIndex As Long, count As Long)
179 If dest = 0 Then
180 'Throw ArgumentNullException
181 ElseIf size < sourceIndex + count Or sourceIndex < 0 Or destIndex < 0 Or count < 0 Then
182 'Throw ArgumentOutOfRangeException
183 End If
184
185 memcpy(VarPtr(dest[destIndex]), VarPtr(chars[sourceIndex]), count * SizeOf (StrChar))
186 End Sub
187
188 Function EnsureCapacity(c As Long) As Long
189 If c < 0 Or c > MaxCapacity Then
190 'Throw ArgumentOutOfRangeException
191 ElseIf c > Capacity Then
192 Dim p = GC_malloc_atomic((c + 1) * SizeOf (StrChar)) As *StrChar
193 If p = 0 Then
194 'Throw OutOfMemoryException
195 Debug
196 End If
197 ActiveBasic.Strings.ChrCopy(p, chars, size As SIZE_T)
198 chars = p
199 capacity = c
200 stringized = False
201 End If
202 End Function
203
204 'Override Function Equals(o As Object) As Boolean
205
206 Const Function Equals(s As StringBuilder) As Boolean
207 Return ActiveBasic.Strings.StrCmp(chars, s.chars) = 0 _
208 And capacity = s.capacity _
209 And maxCapacity = s.maxCapacity
210 End Function
211
212 Override Function GetHashCode() As Long
213#ifdef __STRING_IS_NOT_UNICODE
214 Dim n = (size + 1) >> 1
215#else
216 Dim n = size
217#endif
218 Return _System_GetHashFromWordArray(chars As *Word, n As SIZE_T) Xor capacity Xor maxCapacity
219 End Function
220
221 Function Insert(i As Long, x As Boolean) As StringBuilder
222 rangeCheck(i)
223 insertCore(i, Str$(x))
224 Return This
225 End Function
226
227 Function Insert(i As Long, x As StrChar) As StringBuilder
228 Insert(i, VarPtr(x), 0, 1)
229 Return This
230 End Function
231#ifdef __STRING_IS_NOT_UNICODE
232 Function Insert(i As Long, x As Word) As StringBuilder
233 rangeCheck(i)
234 insertCore(i, Str$(x As DWord))
235 Return This
236 End Function
237#else
238 Function Insert(i As Long, x As SByte) As StringBuilder
239 rangeCheck(i)
240 insertCore(i, Str$(x As Long))
241 Return This
242 End Function
243#endif
244
245 Function Insert(i As Long, x As Byte) 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 Integer) 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 Long) 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 DWord) As StringBuilder
264 rangeCheck(i)
265 insertCore(i, Str$(x))
266 Return This
267 End Function
268
269 Function Insert(i As Long, x As Int64) As StringBuilder
270 rangeCheck(i)
271 insertCore(i, Str$(x))
272 Return This
273 End Function
274
275 Function Insert(i As Long, x As Single) As StringBuilder
276 rangeCheck(i)
277 insertCore(i, Str$(x))
278 Return This
279 End Function
280
281 Function Insert(i As Long, x As Double) As StringBuilder
282 rangeCheck(i)
283 insertCore(i, Str$(x))
284 Return This
285 End Function
286
287 Function Insert(i As Long, s As String) As StringBuilder
288 rangeCheck(i)
289 insertCore(i, s)
290 Return This
291 End Function
292
293 Function Insert(i As Long, o As Object) As StringBuilder
294 rangeCheck(i)
295 insertCore(i, o.ToString)
296 Return This
297 End Function
298
299 Function Insert(index As Long, x As String, n As Long) As StringBuilder
300 rangeCheck(index)
301 If n < 0 Then
302 'Throw New ArgumentOutOfRangeException
303 Debug
304 End If
305 Dim len = x.Length
306 Dim lenTotal = len * n
307 Dim newSize = size + lenTotal
308 EnsureCapacity(newSize)
309 separateBuffer()
310 ActiveBasic.Strings.ChrMove(VarPtr(chars[i + lenTotal]), VarPtr(chars[i]), (size - index) As SIZE_T)
311 Dim i As Long
312 For i = 0 To ELM(n)
313 x.CopyTo(0, chars, size + i * len, len)
314 Next
315 size = newSize
316 Return This
317 End Function
318
319
320 Function Insert(i As Long, x As *StrChar, index As Long, count As Long) As StringBuilder
321 rangeCheck(i)
322 If x = 0 Then
323 'Throw New ArgumentNullException
324 Debug
325 ElseIf index < 0 Or count < 0 Then
326 'Throw New ArgumentNullException
327 Debug
328 End If
329
330 Dim newSize = size + count
331 EnsureCapacity(newSize)
332 separateBuffer()
333 ActiveBasic.Strings.ChrMove(VarPtr(chars[i + count]), VarPtr(chars[i]), (size - i) As SIZE_T)
334 ActiveBasic.Strings.ChrCopy(VarPtr(chars[i]), VarPtr(x[index]), count As SIZE_T)
335 size = newSize
336 Return This
337 End Function
338
339Private
340 Sub insertCore(i As Long, s As String)
341 Dim newSize = size + s.Length
342 EnsureCapacity(newSize)
343 separateBuffer()
344 ActiveBasic.Strings.ChrMove(VarPtr(chars[i + s.Length]), VarPtr(chars[i]), (size - i) As SIZE_T)
345 s.CopyTo(0, chars, i, s.Length)
346 size = newSize
347 End Sub
348Public
349
350 Function Remove(startIndex As Long, length As Long) As StringBuilder
351 rangeCheck(startIndex, length)
352 separateBuffer()
353
354 Dim moveStart = startIndex + length
355 ActiveBasic.Strings.ChrMove(
356 VarPtr(chars[startIndex]), VarPtr(chars[moveStart]), (size - moveStart) As SIZE_T)
357 size -= length
358 Return This
359 End Function
360
361 Function Replace(oldChar As StrChar, newChar As StrChar) As StringBuilder
362 replaceCore(oldChar, newChar, 0, size)
363 Return This
364 End Function
365
366 Function Replace(oldStr As String, newStr As String) As StringBuilder
367 replaceCore(oldStr, newStr, 0, size)
368 Return This
369 End Function
370
371 Function Replace(oldChar As StrChar, newChar As StrChar, startIndex As Long, count As Long) As StringBuilder
372 rangeCheck(startIndex, count)
373 replaceCore(oldChar, newChar, startIndex, count)
374 Return This
375 End Function
376
377 Function Replace(oldStr As String, newStr As String, startIndex As Long, count As Long) As StringBuilder
378 rangeCheck(startIndex, count)
379 replaceCore(oldStr, newStr, startIndex, count)
380 Return This
381 End Function
382Private
383 Sub replaceCore(oldChar As StrChar, newChar As StrChar, start As Long, count As Long)
384 separateBuffer()
385 Dim i As Long
386 Dim last = ELM(start + count)
387 For i = start To last
388 If chars[i] = oldChar Then
389 chars[i] = newChar
390 End If
391 Next
392 End Sub
393
394 Sub replaceCore(oldStr As String, newStr As String, start As Long, count As Long)
395 If Object.ReferenceEquals(oldStr, Nothing) Then
396 'Throw ArgumentNullException
397 Debug
398 ElseIf oldStr.Length = 0 Then
399 'Throw ArgumentException
400 Debug
401 End If
402
403 Dim s = New StringBuilder(capacity, maxCapacity)
404 Dim curPos = 0 As Long
405 Do
406 Dim nextPos = ActiveBasic.Strings.ChrFind(VarPtr(chars[curPos]) As *StrChar, size As SIZE_T, StrPtr(oldStr), oldStr.Length As SIZE_T)
407 If nextPos = -1 As SIZE_T Then
408 Exit Sub
409 End If
410
411 s.appendCore(chars, curPos, nextPos)
412 s.Append(newStr)
413 curPos += nextPos + oldStr.Length
414 Loop
415 chars = s.chars
416 size = s.size
417 End Sub
418
419Public
420 Override Function ToString() As String
421 chars[size] = 0
422 Return New String(This)
423 End Function
424
425 Const Function ToString(startIndex As Long, length As Long) As String
426 rangeCheck(startIndex, length)
427 Return New String(chars, startIndex, length)
428 End Function
429
430 Const Function Operator [](i As Long) As StrChar
431 Return Chars[i]
432 End Function
433
434 Sub Operator []=(i As Long, c As StrChar)
435 Chars[i] = c
436 End Sub
437
438 'Properties
439 Const Function Capacity() As Long
440 Return capacity
441 End Function
442
443 Sub Capacity(c As Long)
444 If c < size Or c > MaxCapacity Then 'sizeとの比較でcが負の場合も対応
445 'Throw ArgumentOutOfRangeException
446 End If
447 EnsureCapacity(c)
448 End Sub
449
450 Const Function Chars(i As Long) As StrChar
451 If i >= Length Or i < 0 Then
452 'Throw IndexOutOfRangeException
453 Debug
454 End If
455 Return chars[i]
456 End Function
457
458 Sub Chars(i As Long, c As StrChar)
459 If i >= Length Or i < 0 Then
460 'Throw ArgumentOutOfRangeException
461 Debug
462 End If
463 chars[i] = c
464 End Sub
465
466 Const Function Length() As Long
467 Return size
468 End Function
469
470 Sub Length(i As Long)
471 EnsureCapacity(i) 'iが適切な値かどうかの確認はこの中で行う
472 If size < i Then
473 ActiveBasic.Strings.ChrFill(VarPtr(chars[size]), (i - size + 1) As SIZE_T, 0 As StrChar)
474 End If
475 size = i
476 End Sub
477
478 Const Function MaxCapacity() As Long
479 Return maxCapacity
480 End Function
481
482 Function __Chars() As *StrChar
483 Return chars
484 End Function
485
486 Sub __Stringized()
487 stringized = True
488 End Sub
489
490Private
491 Sub initialize(capacity As Long, maxCapacity = LONG_MAX As Long)
492 If capacity < 0 Or maxCapacity < 1 Or maxCapacity < capacity Then
493 'Throw ArgumentOutOfRangeException
494 End If
495
496 If capacity = 0 Then
497 This.capacity = 1024
498 Else
499 This.capacity = capacity
500 End If
501
502 This.maxCapacity = maxCapacity
503 This.size = 0
504 This.chars = GC_malloc_atomic((This.capacity + 1) * SizeOf (StrChar))
505 If chars = 0 Then
506 'Throw OutOfMemoryException
507 Debug
508 End If
509
510 End Sub
511
512 Sub initialize(s As String, startIndex As Long, length As Long, capacity As Long, maxCapacity = LONG_MAX As Long)
513 StringBuilder.rangeCheck2(s.Length, startIndex, length)
514
515 initialize(Math.Max(capacity, length), maxCapacity)
516
517 If Not String.IsNullOrEmpty(s) Then
518 s.CopyTo(startIndex, chars, 0, length)
519 size = s.Length
520 End If
521 End Sub
522
523 Sub rangeCheck(index As Long)
524 If index < 0 Or index > size Then
525 'Throw ArgumentOutOfRangeException
526 Debug
527 End If
528 End Sub
529
530 Sub rangeCheck(startIndex As Long, count As Long)
531 StringBuilder.rangeCheck2(size, startIndex, count)
532 End Sub
533
534 Static Sub rangeCheck2(length As Long, startIndex As Long, count As Long)
535 'length < 0は判定に入っていないことに注意
536 If startIndex < 0 Or count < 0 Or startIndex + count > length Then
537 'Throw ArgumentOutOfRangeException
538 Debug
539 End If
540 End Sub
541
542 Sub separateBuffer()
543 If stringized Then
544 Dim newChars = GC_malloc_atomic(SizeOf (StrChar) * capacity) As *StrChar
545 ActiveBasic.Strings.ChrCopy(newChars, chars, capacity As SIZE_T)
546 chars = newChars
547 stringized = False
548 End If
549 End Sub
550
551 chars As *StrChar
552 maxCapacity As Long
553 capacity As Long
554 size As Long
555 stringized As Boolean
556End Class
557
558End Namespace 'Text
559End Namespace 'System
560
561'暫定
562Function StrPtr(sb As System.Text.StringBuilder) As *StrChar
563 Return sb.__Chars
564End Function
Note: See TracBrowser for help on using the repository browser.