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

Last change on this file since 207 was 207, checked in by dai, 17 years ago

動的型情報(Object.GetType)に対応。
戻り値やクラスメンバがオブジェクトだったとき、その初期値をNothingにした(※戻り値として関数名を使っている部分、要注意!!)。

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