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

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

GCHandleの追加、String.Compareなどの追加、gc.sbpの修正

File size: 17.4 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
[139]347 With ConcatStrChar
348 .AllocStringBuffer(text1Length + text2Length)
349 memcpy(.Chars, text1, SizeOf (StrChar) * text1Length)
350 memcpy(VarPtr(.Chars[text1Length]), text2, SizeOf (StrChar) * text2Length)
351 .Chars[text1Length + text2Length] = 0
352 End With
353 End Function
354Public
355 Const Function Concat(text As PCSTR, len As Long) As String
356#ifdef __STRING_IS_NOT_UNICODE
357 Return ConcatStrChar(This.Chars, m_Length, text, len)
358#else
359 With Concat
360 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
361 .AllocStringBuffer(m_Length + lenW)
362 memcpy(.Chars, This.Chars, m_Length)
363 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
364 .Chars[m_Length + lenW] = 0
365 End With
366#endif
367 End Function
[132]368
[139]369 Const Function Concat(text As PCWSTR, len As Long) As String
370#ifdef __STRING_IS_NOT_UNICODE
371 With Concat
372 Dim lenA = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
373 .AllocStringBuffer(m_Length + lenA)
374 memcpy(.Chars, This.Chars, m_Length)
375 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
376 .Chars[m_Length + lenA] = 0
[1]377 End With
[139]378#else
379 Return ConcatStrChar(This.Chars, m_Length, text, len)
380#endif
[1]381 End Function
[203]382
383 Static Function Concat(x As String, y As String) As String
384 If x = Nothing Then
385 Return y
386 Else
387 Return x.Concat(objString.Chars, objString.m_Length)
388 End If
389 End Function
390
391 Static Function Concat(x As Object, y As Object) As String
392 Return String.Concat(x.ToString, y.ToString)
393 End Function
394
395 Const Function Contains(objString As String) As Boolean
[132]396 Return IndexOf(objString, 0, m_Length) >= 0
[1]397 End Function
398
[139]399 Const Function Contains(lpszText As *StrChar) As Boolean
[132]400 Return IndexOf(lpszText, 0, m_Length) >= 0
[1]401 End Function
402
[139]403 Const Function IndexOf(lpszText As *StrChar) As Long
[30]404 Return IndexOf(lpszText, 0, m_Length)
[1]405 End Function
406
[139]407 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
[30]408 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
[1]409 End Function
410
[139]411 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
[132]412 Dim length = lstrlen(lpszText)
[1]413
414 If startIndex < 0 Then Return -1
[30]415 If count < 1 Or count + startIndex > m_Length Then Return -1
416 If length > m_Length Then Return -1
[1]417
418 If length = 0 Then Return startIndex
419
420 Dim i As Long, j As Long
421 For i = startIndex To startIndex + count - 1
422 For j = 0 To length - 1
[31]423 If Chars[i + j] = lpszText[j] Then
[1]424 If j = length - 1 Then Return i
425 Else
426 Exit For
427 End If
428 Next
429 Next
430 Return -1
431 End Function
432
[139]433 Const Function LastIndexOf(lpszText As *StrChar) As Long
[30]434 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
[1]435 End Function
436
[139]437 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
438 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
[1]439 End Function
440
[139]441 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
[132]442 Dim length = lstrlen(lpszText)
[1]443
[30]444 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
[1]445 If count < 1 Or count > startIndex + 2 Then Return -1
[30]446 If length > m_Length Then Return -1
[1]447
448 If length = 0 Then Return startIndex
449
450 Dim i As Long, j As Long
451 For i = startIndex To startIndex - count + 1 Step -1
452 For j = length - 1 To 0 Step -1
[31]453 If Chars[i + j] = lpszText[j] Then
[1]454 If j = 0 Then Return i
455 Else
456 Exit For
457 End If
458 Next
459 Next
460 Return -1
461 End Function
462
[139]463 Const Function StartsWith(lpszText As *StrChar) As Boolean
[132]464 Return IndexOf(lpszText) = 0
[1]465 End Function
466
[139]467 Const Function EndsWith(lpszText As *StrChar) As Boolean
[132]468 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
[1]469 End Function
470
[132]471 Const Function Insert(startIndex As Long, text As String) As String
472 Return Insert(startIndex, text.Chars, text.Length)
473 End Function
[1]474
[139]475 Const Function Insert(startIndex As Long, text As *StrChar) As String
[132]476 Return Insert(startIndex, text, lstrlen(text))
477 End Function
[1]478
[139]479 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
[132]480 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
481 Debug 'ArgumentOutOfRangeException
[1]482
[132]483 End If
484 Insert.ReSize(m_Length + length)
[139]485 memcpy(Insert.Chars, Chars, SizeOf (StrChar) * startIndex)
486 memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (StrChar) * length)
487 memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (StrChar) * (m_Length - startIndex + 1))
[1]488 End Function
489
[132]490 Const Function SubString(startIndex As Long) As String
[30]491 Return SubString(startIndex, m_Length - startIndex)
[1]492 End Function
493
[132]494 Const Function SubString(startIndex As Long, length As Long) As String
[1]495 If startIndex < 0 Or length <= 0 Then Return ""
[30]496 If startIndex + length > m_Length Then Return ""
[1]497
498 Dim temp As String
499 temp.AllocStringBuffer(length)
[139]500 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
[31]501 Chars[m_Length] = 0
[1]502 Return temp
503 End Function
504
[132]505 Const Function Remove(startIndex As Long) As String
[135]506 If startIndex < 0 Or startIndex > m_Length Then
507 Debug 'ArgumentOutOfRangeException
508 End If
509
[132]510 Remove.ReSize(startIndex)
[139]511 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
[1]512 End Function
513
[132]514 Const Function Remove(startIndex As Long, count As Long) As String
[135]515 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
516 Debug 'ArgumentOutOfRangeException
517 End If
518
[132]519 Remove.ReSize(m_Length - count)
[139]520 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
521 memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (StrChar) * (m_Length - startIndex - count))
[132]522 End Function
[192]523
[132]524 Static Function IsNullOrEmpty(s As String) As Boolean
525 If s <> Nothing Then
526 If s.m_Length > 0 Then
527 Return True
528 End If
529 End If
530 Return False
531 End Function
[192]532
[139]533 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
[132]534 Replace = Copy(This)
535 With Replace
536 Dim i As Long
537 For i = 0 To ELM(.m_Length)
[142]538 If .Chars[i] = oldChar Then
539 .Chars[i] = newChar
[132]540 End If
541 Next
542 End With
543 End Function
[1]544
[132]545 Const Function Replace(ByRef oldStr As String, ByRef newStr As String) As String
546' If oldStr = Nothing Then Throw ArgumentNullException
547'
548' If newStr = Nothing Then
549' Return ReplaceCore(oldStr, oldStr.m_Length, "", 0)
550' Else
551 Return ReplaceCore(oldStr, oldStr.m_Length, newStr, newStr.m_Length)
552' End If
553 End Function
[1]554
[139]555 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
[132]556 If oldStr = 0 Then Debug 'Throw ArgumentNullException
557 If newStr = 0 Then newStr = ""
558 Return ReplaceCore(oldStr, lstrlen(oldStr), newStr, lstrlen(newStr)) As String
[1]559 End Function
560
[139]561 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
[132]562 If oldStr = 0 Then Debug 'Throw ArgumentNullException
563 If newStr = 0 Then
564 newStr = ""
565 newLen = 0
[1]566 End If
[132]567 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
[1]568 End Function
569
[134]570 Const Function ToLower() As String
571 ToLower.ReSize(m_Length)
[125]572 Dim i As Long
[134]573 For i = 0 To ELM(m_Length)
574 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
[125]575 Next
[134]576 End Function
[1]577
[134]578 Const Function ToUpper() As String
579 ToUpper.ReSize(m_Length)
[125]580 Dim i As Long
[134]581 For i = 0 To ELM(m_Length)
582 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
[125]583 Next
[134]584 End Function
[1]585
586 Sub Swap(ByRef x As String)
587 Dim tempLen As Long
[139]588 Dim tempChars As *StrChar
[30]589 tempLen = x.m_Length
[31]590 tempChars = x.Chars
[30]591 x.m_Length = This.m_Length
[31]592 x.Chars = This.Chars
[30]593 This.m_Length = tempLen
[31]594 This.Chars = tempChars
[1]595 End Sub
596
[119]597 Override Function ToString() As String
598 Return This
599 End Function
600
[132]601 Static Function Copy(s As String) As String
[142]602 Copy.ReSize(s.m_Length)
[139]603 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
[132]604 End Function
605
[143]606 Override Function GetHashCode() As Long
607#ifdef __STRING_IS_NOT_UNICODE
608 Dim size = (m_Length + 1) >> 1
609#else
610 Dim size = m_Length
611#endif
[175]612 Return _System_GetHashFromWordArray(Chars As *Word, size)
[143]613 End Function
[1]614Private
615 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
[139]616 Function AllocStringBuffer(textLength As Long) As *StrChar
[1]617 If textLength < 0 Then
618 Return 0
[30]619 ElseIf textLength > m_Length Then
[139]620 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
[1]621 If AllocStringBuffer <> 0 Then
[30]622 m_Length = textLength
[31]623 Chars = AllocStringBuffer
[1]624 End If
625 Else
[30]626 m_Length = textLength
[31]627 AllocStringBuffer = Chars
[1]628 End If
629 End Function
630
[139]631 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
[132]632 If oldLen = 0 Then
633 Debug 'Throw ArgumentException
634 End If
635 Dim tmp As String
636 With tmp
637 Dim current = 0 As Long
638 Do
639 Dim pos = IndexOf(oldStr, current)
640 If pos = -1 Then
641 Exit Do
642 End If
643 .Append(VarPtr(Chars[current]), pos - current)
644 .Append(newStr, newLen)
645 current = pos + oldLen
646 Loop
647 .Append(VarPtr(Chars[current]), m_Length - current)
648 End With
649 Return tmp
650 End Function
651
[175]652 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
653 If text = Chars Then Exit Sub
654 If AllocStringBuffer(textLength) <> 0 Then
655 memcpy(Chars, text, SizeOf (StrChar) * textLength)
656 Chars[m_Length] = 0
657 End If
658 End Sub
[1]659End Class
Note: See TracBrowser for help on using the repository browser.