source: trunk/ab5.0/ablib/src/Classes/System/Text/StringBuilder.ab @ 521

Last change on this file since 521 was 521, checked in by イグトランス (egtra), 15 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 = start + count - 1'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.