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

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

Objectクラス、Stringクラスの定義をSystem名前空間に入れると共に、コンパイラ側で両者のクラスをSystem名前空間に依存しない特殊型として扱うようにした。
System.Diagnostics名前空間を導入した。
Namespaceステートメントのコード補間機能に対応。

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