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

Last change on this file since 233 was 227, checked in by dai, 18 years ago

文字列の比較演算子の戻り値がLong型になっていたので、Booleanに修正した。
String.GetTypeのテストケースを修正。

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