source: Include/Classes/System/String.ab@ 272

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

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

File size: 16.3 KB
RevLine 
[132]1' Classes/System/String.ab
2
3#require <basic/function.sbp>
[272]4#require <Classes/System/Text/StringBuilder.ab>
5#require <Classes/ActiveBasic/Strings/Strings.ab>
[132]6
[139]7#ifdef __STRING_IS_NOT_ALWAYS_UNICODE
8TypeDef StrChar = Char
9#ifndef UNICODE
10#define __STRING_IS_NOT_UNICODE
11#endif
12#else
13TypeDef StrChar = WCHAR
[142]14#ifndef UNICODE
15#define __STRING_UNICODE_WINDOWS_ANSI
[139]16#endif
[142]17#endif
[139]18
[246]19Namespace System
[203]20
[246]21 Class String
22 ' Inherits IComparable, ICloneable, IConvertible, IEnumerable
[1]23
[246]24 m_Length As Long
25 Chars As *StrChar
[1]26
[272]27 Sub validPointerCheck(p As VoidPtr, size = 1 As Long)
28 If p As ULONG_PTR < &h10000 Then
29 'Throw ArgumentException
30 Debug
31 ElseIf IsBadReadPtr(p, size As ULONG_PTR) Then
32 'Throw ArgumentException
33 Debug
34 End If
35 End Sub
36 Public
37 Static Const Empty = New String
38
[246]39 Sub String()
[272]40' Chars = 0
41' m_Length = 0
[246]42 End Sub
[30]43
[272]44 Sub String(initStr As PCWSTR)
45 validPointerCheck(initStr)
46 Assign(initStr, lstrlenW(initStr))
[246]47 End Sub
[125]48
[272]49 Sub String(initStr As PCWSTR, length As Long)
50 validPointerCheck(initStr, length)
[246]51 Assign(initStr, length)
52 End Sub
[139]53
[272]54 Sub String(initStr As PCWSTR, start As Long, length As Long)
55 If start < 0 Or length Or start + length < 0 Then
56 'Throw New ArgumentOutOfRangeException
57 End If
58 validPointerCheck(initStr + start, length)
59 Assign(initStr + start, length)
[246]60 End Sub
[139]61
[272]62 Sub String(initStr As PCSTR)
63 validPointerCheck(initStr)
64 Assign(initStr, lstrlenA(initStr))
[246]65 End Sub
[49]66
[272]67 Sub String(initStr As PCSTR, length As Long)
68 validPointerCheck(initStr, length)
69 Assign(initStr, length)
[246]70 End Sub
[121]71
[272]72 Sub String(initStr As PCSTR, start As Long, length As Long)
73 If start < 0 Or length Or start + length < 0 Then
74 'Throw New ArgumentOutOfRangeException
75 End If
76 validPointerCheck(initStr + start, length)
77 Assign(initStr + start, length)
[246]78 End Sub
[272]79
80 Sub String(initStr As String)
81 If Not String.IsNullOrEmpty(initStr) Then
82 Assign(initStr.Chars, initStr.m_Length)
83 End If
84 End Sub
[1]85
[246]86 Sub String(initChar As StrChar, length As Long)
[272]87 AllocStringBuffer(length)
88 ActiveBasic.Strings.ChrFill(Chars, length, initChar)
89 Chars[length] = 0
[246]90 End Sub
91
[272]92 Sub String(sb As System.Text.StringBuilder)
93 Chars = StrPtr(sb)
94 m_Length = sb.Length
95 sb.__Stringized()
[246]96 End Sub
[1]97
[246]98 Const Function Length() As Long
99 Return m_Length
100 End Function
[30]101
[246]102 Function Operator() As *StrChar
103 Return Chars
104 End Function
[1]105
[246]106 Const Function Operator [] (n As Long) As StrChar
[272]107 rangeCheck(n)
[246]108 Return Chars[n]
109 End Function
[1]110
[272]111 Const Function Operator + (y As PCSTR) As String
112 Return Concat(y, lstrlenA(y))
[246]113 End Function
[139]114
[272]115 Const Function Operator + (y As PCWSTR) As String
116 Return Concat(y, lstrlenW(y))
[246]117 End Function
[139]118
[272]119 Const Function Operator + (y As String) As String
120 Return Concat(y.Chars, y.m_Length)
[246]121 End Function
[1]122
[272]123 Const Function Operator & (y As PCSTR) As String
124 Return This + y
[246]125 End Function
[1]126
[272]127 Const Function Operator & (y As PCWSTR) As String
128 Dim tempString = This + y
[246]129 Return tempString
130 End Function
[139]131
[272]132 Const Function Operator & (y As String) As String
133 Dim tempString = This + y
[246]134 Return tempString
135 End Function
[1]136
[272]137 Const Function Operator == (y As String) As Boolean
138 Return String.Compare(This, y) = 0
[246]139 End Function
[1]140
[272]141 Const Function Operator == (y As *StrChar) As Boolean
142 Return String.Compare(This, y) = 0
[246]143 End Function
[1]144
[272]145 Const Function Operator <> (y As String) As Boolean
146 Return String.Compare(This, y) <> 0
[246]147 End Function
[1]148
[272]149 Const Function Operator <> (y As *StrChar) As Boolean
150 Return String.Compare(This, y) <> 0
[246]151 End Function
[1]152
[272]153 Const Function Operator < (y As String) As Boolean
154 Return String.Compare(This, y) < 0
[246]155 End Function
[1]156
[272]157 Const Function Operator < (y As *StrChar) As Boolean
158 Return String.Compare(This, y) < 0
[246]159 End Function
[1]160
[272]161 Const Function Operator > (y As String) As Boolean
162 Return String.Compare(This, y) > 0
[246]163 End Function
[1]164
[272]165 Const Function Operator > (y As *StrChar) As Boolean
166 Return String.Compare(This, y) > 0
[246]167 End Function
[1]168
[272]169 Const Function Operator <= (y As String) As Boolean
170 Return String.Compare(This, y) <= 0
[246]171 End Function
[1]172
[272]173 Const Function Operator <= (y As *StrChar) As Boolean
174 Return String.Compare(This, y) <= 0
[246]175 End Function
[1]176
[272]177 Const Function Operator >= (y As String) As Boolean
178 Return String.Compare(This, y) >= 0
[246]179 End Function
[1]180
[272]181 Const Function Operator >= (y As *StrChar) As Boolean
182 Return String.Compare(This, y) >= 0
[246]183 End Function
[1]184
[246]185 Static Function Compare(x As String, y As String) As Long
186 Return CompareOrdinal(x, y)
187 End Function
[203]188
[272]189 Public
[246]190 Static Function Compare(x As String, indexX As Long, y As String, indexY As Long, length As Long) As Long
[272]191 Return String.CompareOrdinal(x, indexX, y, indexY, length)
[246]192 End Function
[203]193
[246]194 Static Function CompareOrdinal(x As String, y As String) As Long
[272]195 Return String.CompareOrdinal(x.Chars, y.Chars)
[246]196 End Function
[203]197
[246]198 Static Function CompareOrdinal(x As String, indexX As Long, y As String, indexY As Long, length As Long) As Long
[272]199 Return String.CompareOrdinal(x.Chars, indexX, y.Chars, indexY, length)
200 End Function
201 Private
202 Static Function Compare(x As String, y As *StrChar) As Long
203 Return String.CompareOrdinal(x, y)
204 End Function
205
206 Static Function CompareOrdinal(x As String, y As *StrChar) As Long
207 Return String.CompareOrdinal(x.Chars, y)
208 End Function
209
210 Static Function CompareOrdinal(x As *StrChar, y As *StrChar) As Long
211 If x = 0 Then
212 If y = 0 Then
[246]213 Return 0
214 Else
215 Return -1
216 End If
[272]217 ElseIf y = 0 Then
[246]218 Return 1
[203]219 End If
[272]220 Return ActiveBasic.Strings.StrCmp(x, y)
[246]221 End Function
[203]222
[272]223 Static Function CompareOrdinal(x As *StrChar, indexX As Long, y As *StrChar, indexY As Long, length As Long) As Long
224 If x = 0 Then
225 If y = 0 Then
226 Return 0
227 Else
228 Return -1
229 End If
230 ElseIf y = 0 Then
231 Return 1
232 End If
233 Return ActiveBasic.Strings.ChrCmp(VarPtr(x[indexX]), VarPtr(y[indexY]), length As SIZE_T)
234 End Function
235 Public
[246]236 Function CompareTo(y As String) As Long
237 Return String.Compare(This, y)
238 End Function
[203]239
[246]240 Function CompareTo(y As Object) As Long
241 Dim s = y As String
242 ' If y is not String Then
243 ' Throw New ArgumentException
244 ' End If
[272]245 Return CompareTo(y As String)
[246]246 End Function
[203]247
[246]248 Const Function StrPtr() As *StrChar
249 Return Chars
250 End Function
[272]251Private
[1]252
[246]253 Sub Assign(text As PCSTR, textLengthA As Long)
[175]254#ifdef __STRING_IS_NOT_UNICODE
[246]255 AssignFromStrChar(text, textLengthA)
[139]256#else
[246]257 Dim textLengthW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, 0, 0)
258 If AllocStringBuffer(textLengthW) <> 0 Then
259 MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, Chars, textLengthW)
260 Chars[textLengthW] = 0
261 End If
[139]262#endif
[246]263 End Sub
[1]264
[246]265 Sub Assign(text As PCWSTR, textLengthW As Long)
[139]266#ifdef __STRING_IS_NOT_UNICODE
[246]267 Dim textLengthA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, 0, 0, 0, 0)
268 If AllocStringBuffer(textLengthA) <> 0 Then
269 WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, Chars, textLengthA, 0, 0)
270 Chars[textLengthA] = 0
271 End If
[139]272#else
[246]273 AssignFromStrChar(text, textLengthW)
[139]274#endif
[246]275 End Sub
[139]276
[246]277 Private
278 Static Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
279 ConcatStrChar = New String()
280 With ConcatStrChar
281 .AllocStringBuffer(text1Length + text2Length)
[272]282 ActiveBasic.Strings.ChrCopy(.Chars, text1, text1Length As SIZE_T)
283 ActiveBasic.Strings.ChrCopy(VarPtr(.Chars[text1Length]), text2, text2Length As SIZE_T)
[246]284 .Chars[text1Length + text2Length] = 0
285 End With
286 End Function
287 Public
288 Const Function Concat(text As PCSTR, len As Long) As String
[139]289#ifdef __STRING_IS_NOT_UNICODE
[246]290 Return ConcatStrChar(This.Chars, m_Length, text, len)
[139]291#else
[246]292 With Concat
293 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
[272]294 Concat = New String
[246]295 .AllocStringBuffer(m_Length + lenW)
[272]296 ActiveBasic.Strings.ChrCopy(.Chars, This.Chars, m_Length)
[246]297 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
298 .Chars[m_Length + lenW] = 0
299 End With
[139]300#endif
[246]301 End Function
[132]302
[246]303 Const Function Concat(text As PCWSTR, len As Long) As String
[139]304#ifdef __STRING_IS_NOT_UNICODE
[246]305 With Concat
[272]306 Concat = New String
[246]307 Dim lenA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
308 .AllocStringBuffer(m_Length + lenA)
[272]309 ActiveBasic.Strings.ChrCopy(.Chars, This.Chars, m_Length As SIZE_T)
[246]310 WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
311 .Chars[m_Length + lenA] = 0
312 End With
[139]313#else
[246]314 Return ConcatStrChar(This.Chars, m_Length, text, len)
[139]315#endif
[246]316 End Function
[203]317
[246]318 Static Function Concat(x As String, y As String) As String
319 If String.IsNullOrEmpty(x) Then
320 Return y
321 Else
322 Return x.Concat(y.Chars, y.m_Length)
323 End If
324 End Function
[203]325
[246]326 Static Function Concat(x As Object, y As Object) As String
327 Return String.Concat(x.ToString, y.ToString)
328 End Function
[203]329
[272]330 Const Function Contains(s As String) As Boolean
331 If Object.ReferenceEquals(s, Nothing) Then
332 'Throw New ArgumentNullException
333 End If
334 Return IndexOf(s, 0, m_Length) >= 0
[246]335 End Function
[1]336
[272]337 Const Function IndexOf(c As StrChar) As Long
338 Return indexOfCore(c, 0, m_Length)
[246]339 End Function
[1]340
[272]341 Const Function IndexOf(c As StrChar, start As Long) As Long
342 rangeCheck(start)
343 Return indexOfCore(c, start, m_Length - start)
[246]344 End Function
[1]345
[272]346 Const Function IndexOf(c As StrChar, start As Long, count As Long) As Long
347 rangeCheck(start, count)
348 Return indexOfCore(c, start, count)
[246]349 End Function
[272]350 Private
351 Const Function indexOfCore(c As StrChar, start As Long, count As Long) As Long
352 indexOfCore = ActiveBasic.Strings.ChrFind(VarPtr(Chars[start]), count, c)
353 If indexOfCore <> -1 Then
354 indexOfCore += start
355 End If
356 End Function
357 Public
358 Const Function IndexOf(s As String) As Long
359 Return IndexOf(s, 0, m_Length)
360 End Function
[1]361
[272]362 Const Function IndexOf(s As String, startIndex As Long) As Long
363 Return IndexOf(s, startIndex, m_Length - startIndex)
364 End Function
[1]365
[272]366 Const Function IndexOf(s As String, startIndex As Long, count As Long) As Long
367 rangeCheck(startIndex, count)
368 If Object.ReferenceEquals(s, Nothing) Then
369 'Throw New ArgumentNullException
370 Debug
371 End If
[1]372
[272]373 Dim length = s.Length
[246]374 If length = 0 Then Return startIndex
[1]375
[246]376 Dim i As Long, j As Long
377 For i = startIndex To startIndex + count - 1
378 For j = 0 To length - 1
[272]379 If Chars[i + j] = s[j] Then
[246]380 If j = length - 1 Then Return i
381 Else
382 Exit For
383 End If
384 Next
[1]385 Next
[246]386 Return -1
387 End Function
[1]388
[272]389 Const Function LastIndexOf(s As String) As Long
390 Return LastIndexOf(s, m_Length - 1, m_Length)
[246]391 End Function
[1]392
[272]393 Const Function LastIndexOf(s As String, startIndex As Long) As Long
394 Return LastIndexOf(s, startIndex, startIndex + 1)
[246]395 End Function
[1]396
[272]397 Const Function LastIndexOf(s As String, startIndex As Long, count As Long) As Long
398 If Object.ReferenceEquals(s, Nothing) Then
399 'Throw New ArgumentNullException
400 Debug
401 End If
[1]402
[272]403 If startIndex < 0 Or startIndex > m_Length - 1 Or _
404 count < 0 Or count > startIndex + 2 Then
405 'Throw New ArgumentOutOfRangeException
406 Debug
407 End If
408 Dim length = s.Length
[246]409 If length > m_Length Then Return -1
410 If length = 0 Then Return startIndex
[1]411
[246]412 Dim i As Long, j As Long
413 For i = startIndex To startIndex - count + 1 Step -1
414 For j = length - 1 To 0 Step -1
[272]415 If Chars[i + j] = s[j] Then
[246]416 If j = 0 Then Return i
417 Else
418 Exit For
419 End If
420 Next
[1]421 Next
[246]422 Return -1
423 End Function
[1]424
[272]425 Const Function StartsWith(s As String) As Boolean
426 Return IndexOf(s) = 0
[246]427 End Function
[1]428
[272]429 Const Function EndsWith(s As String) As Boolean
430 Return LastIndexOf(s) = m_Length - s.Length
[246]431 End Function
[1]432
[246]433 Const Function Insert(startIndex As Long, text As String) As String
[272]434 Dim sb = New System.Text.StringBuilder(This)
435 sb.Insert(startIndex, text)
436 Return sb.ToString
[246]437 End Function
[1]438
[272]439 Const Function Substring(startIndex As Long) As String
440 rangeCheck(startIndex)
441 Return Substring(startIndex, m_Length - startIndex)
[246]442 End Function
[1]443
[272]444 Const Function Substring(startIndex As Long, length As Long) As String
445 rangeCheck(startIndex, length)
446 Return New String(Chars, startIndex, length)
[246]447 End Function
[1]448
[246]449 Const Function Remove(startIndex As Long) As String
[272]450 rangeCheck(startIndex)
451 Remove = Substring(0, startIndex)
[246]452 End Function
[1]453
[246]454 Const Function Remove(startIndex As Long, count As Long) As String
[272]455 Dim sb = New System.Text.StringBuilder(This)
456 sb.Remove(startIndex, count)
457 Remove = sb.ToString
[246]458 End Function
[192]459
[246]460 Static Function IsNullOrEmpty(s As String) As Boolean
461 If Not Object.ReferenceEquals(s, Nothing) Then
462 If s.m_Length > 0 Then
463 Return False
464 End If
[132]465 End If
[246]466 Return True
467 End Function
[192]468
[246]469 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
[272]470 Dim sb = New System.Text.StringBuilder(This)
471 sb.Replace(oldChar, newChar)
472 Replace = sb.ToString
[246]473 End Function
[1]474
[272]475 Const Function Replace(oldStr As String, newStr As String) As String
476 Dim sb = New System.Text.StringBuilder(This)
477 sb.Replace(oldStr, newStr)
478 Return sb.ToString
[246]479 End Function
[1]480
[246]481 Const Function ToLower() As String
[272]482 Dim sb = New System.Text.StringBuilder(m_Length)
483 sb.Length = m_Length
[246]484 Dim i As Long
485 For i = 0 To ELM(m_Length)
[272]486 sb[i] = _System_ASCII_ToLower(Chars[i])
[246]487 Next
[272]488 Return sb.ToString
[246]489 End Function
[1]490
[246]491 Const Function ToUpper() As String
[272]492 Dim sb = New System.Text.StringBuilder(m_Length)
493 sb.Length = m_Length
[246]494 Dim i As Long
495 For i = 0 To ELM(m_Length)
[272]496 sb[i] = _System_ASCII_ToUpper(Chars[i])
[246]497 Next
[272]498 Return sb.ToString
[246]499 End Function
[272]500
[246]501 Override Function ToString() As String
[272]502 ToString = This
[246]503 End Function
[119]504
[272]505 Const Function Clone() As String
506 Clone = This
507 End Function
[246]508 Static Function Copy(s As String) As String
[272]509 Copy = New String(s.Chars, s.m_Length)
[246]510 End Function
[132]511
[272]512 Sub CopyTo(sourceIndex As Long, destination As *StrChar, destinationIndex As Long, count As Long)
513 ActiveBasic.Strings.ChrCopy(VarPtr(destination[destinationIndex]), VarPtr(Chars[sourceIndex]), count As SIZE_T)
514 End Sub
515
[246]516 Override Function GetHashCode() As Long
[143]517#ifdef __STRING_IS_NOT_UNICODE
[246]518 Dim size = (m_Length + 1) >> 1
[143]519#else
[246]520 Dim size = m_Length
[143]521#endif
[246]522 Return _System_GetHashFromWordArray(Chars As *Word, size)
523 End Function
[272]524
525 Function PadLeft(total As Long) As String
526 PadLeft(total, &h30 As StrChar)
527 End Function
528
529 Function PadLeft(total As Long, c As StrChar) As String
530 If total < 0 Then
531 'Throw New ArgumentException
532 End If
533 If total >= m_Length Then
534 Return This
535 End If
536 Dim sb = New System.Text.StringBuilder(total)
537 sb.Append(c, total - m_Length)
538 sb.Append(This)
539 Return sb.ToString
540 End Function
541
542 Function PadRight(total As Long) As String
543 PadLeft(total, &h30 As StrChar)
544 End Function
545
546 Function PadRight(total As Long, c As StrChar) As String
547 If total < 0 Then
548 'Throw New ArgumentException
549 End If
550 If total >= m_Length Then
551 Return This
552 End If
553 Dim sb = New System.Text.StringBuilder(total)
554 sb.Append(This)
555 sb.Append(c, total - m_Length)
556 Return sb.ToString
557 End Function
[246]558 Private
559 Function AllocStringBuffer(textLength As Long) As *StrChar
560 If textLength < 0 Then
561 Return 0
[1]562 End If
[272]563 AllocStringBuffer = GC_malloc_atomic(SizeOf(StrChar) * (textLength + 1))
564 If AllocStringBuffer = 0 Then
565 'Throw New OutOfMemoryException
[246]566 End If
[272]567 m_Length = textLength
568 Chars = AllocStringBuffer
[246]569 End Function
[132]570
[246]571 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
[272]572 AllocStringBuffer(textLength)
573 ActiveBasic.Strings.ChrCopy(Chars, text, textLength As SIZE_T)
574 Chars[m_Length] = 0
575 End Sub
576
577 Const Sub rangeCheck(index As Long)
578 If index < 0 Or index > m_Length Then
579 Debug 'ArgumentOutOfRangeException
[246]580 End If
581 End Sub
[272]582
583 Const Sub rangeCheck(start As Long, length As Long)
584 If start < 0 Or start > This.m_Length Or length < 0 Then
585 Debug 'ArgumentOutOfRangeException
586 End If
587 End Sub
[246]588 End Class
589
590End Namespace
Note: See TracBrowser for help on using the repository browser.