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

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

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

File size: 17.5 KB
Line 
1' Classes/System/String.ab
2
3#require <basic/function.sbp>
4
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
12#ifndef UNICODE
13#define __STRING_UNICODE_WINDOWS_ANSI
14#endif
15#endif
16
17Class String
18' Inherits IComparable, ICloneable, IConvertible, IEnumerable
19
20 m_Length As Long
21Public
22 Chars As *StrChar
23
24 Sub String()
25 Chars = _System_malloc(SizeOf (StrChar))
26 Chars[0] = 0
27 m_Length = 0
28 End Sub
29
30/* Sub String(initStr As *Byte)
31 String()
32 Assign(initStr As PCTSTR)
33 End Sub*/
34
35 Sub String(initStr As PCSTR)
36 String()
37 Assign(initStr)
38 End Sub
39
40 Sub String(initStr As PCSTR, length As Long)
41 String()
42 Assign(initStr, length)
43 End Sub
44
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
55 Sub String(ByRef initStr As String)
56 String()
57 Assign(initStr)
58 End Sub
59
60 Sub String(length As Long)
61 String()
62 ReSize(length)
63 End Sub
64
65 Sub String(initChar As StrChar, length As Long)
66 ReSize(length, initChar)
67 End Sub
68
69 Sub ~String()
70 _System_free(Chars)
71 Chars = 0
72#ifdef _DEBUG
73 m_Length = 0
74#endif
75 End Sub
76
77 Const Function Length() As Long
78 Return m_Length
79 End Function
80
81 Function Operator() As *StrChar
82 Return Chars
83 End Function
84
85/* Sub Operator = (ByRef objString As String)
86 Assign(objString.Chars, objString.m_Length)
87 End Sub
88
89 Sub Operator = (text As *Byte)
90 Assign(text As PCTSTR)
91 End Sub
92
93 Sub Operator = (text As PCSTR)
94 Assign(text)
95 End Sub
96
97 Sub Operator = (text As PCWSTR)
98 Assign(text)
99 End Sub*/
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
108 Return Chars[n]
109 End Function
110
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
118 Chars[n] = c
119 End Sub
120
121/* Const Function Operator + (text As *Byte) As String
122 Return Concat(text As PCTSTR, lstrlen(text))
123 End Function*/
124
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
133 Const Function Operator + (objString As String) As String
134 Return Concat(objString.Chars, objString.m_Length)
135 End Function
136
137 Const Function Operator & (text As PCSTR) As String
138 Dim tempString = This + text
139 Return tempString
140 End Function
141
142 Const Function Operator & (text As PCWSTR) As String
143 Dim tempString = This + text
144 Return tempString
145 End Function
146
147 Const Function Operator & (objString As String) As String
148 Dim tempString = This + objString
149 Return tempString
150 End Function
151
152 Const Function Operator == (objString As String) As Boolean
153 Return String.Compare(This, objString) = 0
154 End Function
155
156 Const Function Operator == (text As *StrChar) As Long
157 Return _System_StrCmp(This.Chars, text) = 0
158 End Function
159
160 Const Function Operator <> (objString As String) As Boolean
161 Return String.Compare(This, objString) <> 0
162 End Function
163
164 Const Function Operator <> (text As *StrChar) As Boolean
165 Return _System_StrCmp(This.Chars, text) <> 0
166 End Function
167
168 Const Function Operator < (objString As String) As Boolean
169 Return String.Compare(This, objString) < 0
170 End Function
171
172 Const Function Operator < (text As *StrChar) As Boolean
173 Return _System_StrCmp(This.Chars, text) < 0
174 End Function
175
176 Const Function Operator > (objString As String) As Boolean
177 Return String.Compare(This, objString) > 0
178 End Function
179
180 Const Function Operator > (text As *StrChar) As Boolean
181 Return _System_StrCmp(This.Chars, text) > 0
182 End Function
183
184 Const Function Operator <= (objString As String) As Boolean
185 Return String.Compare(This, objString) <= 0
186 End Function
187
188 Const Function Operator <= (text As *StrChar) As Boolean
189 Return _System_StrCmp(This.Chars, text) <= 0
190 End Function
191
192 Const Function Operator >= (objString As String) As Boolean
193 Return String.Compare(This, objString) >= 0
194 End Function
195
196 Const Function Operator >= (text As *StrChar) As Boolean
197 Return _System_StrCmp(This.Chars, text) >= 0
198 End Function
199
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
237 Const Function StrPtr() As *StrChar
238 Return Chars
239 End Function
240
241 Sub ReSize(allocLength As Long)
242 If allocLength < 0 Then Exit Sub
243 If allocLength > m_Length Then
244 Dim oldLength As Long
245 oldLength = m_Length
246 If AllocStringBuffer(allocLength) <> 0 Then
247 ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (StrChar) * (m_Length - oldLength + 1))
248 End If
249 Else
250 m_Length = allocLength
251 Chars[m_Length] = 0
252 End If
253 End Sub
254
255 Sub ReSize(allocLength As Long, c As StrChar)
256 If allocLength < 0 Then
257 Exit Sub
258 ElseIf allocLength > m_Length Then
259 Dim oldLength As Long
260 oldLength = m_Length
261 If AllocStringBuffer(allocLength) <> 0 Then
262 Dim p = VarPtr(Chars[oldLength]) As *StrChar
263 Dim fillLen = m_Length - oldLength
264 Dim i As Long
265 For i = 0 To ELM(fillLen)
266 p[i] = c
267 Next
268 End If
269 Else
270 m_Length = allocLength
271 End If
272 Chars[m_Length] = 0
273 End Sub
274
275 Sub Assign(text As PCSTR, textLengthA As Long)
276#ifdef __STRING_IS_NOT_UNICODE
277 AssignFromStrChar(text, textLengthA)
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)
282 Chars[textLengthW] = 0
283 End If
284#endif
285 End Sub
286
287 Sub Assign(text As PCWSTR, textLengthW As Long)
288#ifdef __STRING_IS_NOT_UNICODE
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)
292 Chars[textLengthA] = 0
293 End If
294#else
295 AssignFromStrChar(text, textLengthW)
296#endif
297 End Sub
298
299 Sub Assign(ByRef objString As String)
300 Assign(objString.Chars, objString.m_Length)
301 End Sub
302
303 Sub Assign(text As PCSTR)
304 If text Then
305 Assign(text, lstrlenA(text))
306 Else
307 If Chars <> 0 Then
308 Chars[0] = 0
309 End If
310 m_Length = 0
311 End If
312 End Sub
313
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)
326 Dim prevLen As Long
327 prevLen = m_Length
328 If AllocStringBuffer(m_Length + textLength) <> 0 Then
329 memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
330 Chars[m_Length] = 0
331 End If
332 End Sub
333
334 Sub Append(text As *StrChar)
335 Append(text, lstrlen(text))
336 End Sub
337
338 Sub Append(ByRef str As String)
339 Append(str.Chars, str.m_Length)
340 End Sub
341
342 Const Function Clone() As String
343 Return This
344 End Function
345Private
346 Static Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
347 ConcatStrChar = New String()
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
369
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
378 End With
379#else
380 Return ConcatStrChar(This.Chars, m_Length, text, len)
381#endif
382 End Function
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
397 Return IndexOf(objString, 0, m_Length) >= 0
398 End Function
399
400 Const Function Contains(lpszText As *StrChar) As Boolean
401 Return IndexOf(lpszText, 0, m_Length) >= 0
402 End Function
403
404 Const Function IndexOf(lpszText As *StrChar) As Long
405 Return IndexOf(lpszText, 0, m_Length)
406 End Function
407
408 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
409 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
410 End Function
411
412 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
413 Dim length = lstrlen(lpszText)
414
415 If startIndex < 0 Then Return -1
416 If count < 1 Or count + startIndex > m_Length Then Return -1
417 If length > m_Length Then Return -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
424 If Chars[i + j] = lpszText[j] Then
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
434 Const Function LastIndexOf(lpszText As *StrChar) As Long
435 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
436 End Function
437
438 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
439 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
440 End Function
441
442 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
443 Dim length = lstrlen(lpszText)
444
445 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
446 If count < 1 Or count > startIndex + 2 Then Return -1
447 If length > m_Length Then Return -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
454 If Chars[i + j] = lpszText[j] Then
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
464 Const Function StartsWith(lpszText As *StrChar) As Boolean
465 Return IndexOf(lpszText) = 0
466 End Function
467
468 Const Function EndsWith(lpszText As *StrChar) As Boolean
469 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
470 End Function
471
472 Const Function Insert(startIndex As Long, text As String) As String
473 Return Insert(startIndex, text.Chars, text.Length)
474 End Function
475
476 Const Function Insert(startIndex As Long, text As *StrChar) As String
477 Return Insert(startIndex, text, lstrlen(text))
478 End Function
479
480 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
481 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
482 Debug 'ArgumentOutOfRangeException
483
484 End If
485 Insert.ReSize(m_Length + length)
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))
489 End Function
490
491 Const Function SubString(startIndex As Long) As String
492 Return SubString(startIndex, m_Length - startIndex)
493 End Function
494
495 Const Function SubString(startIndex As Long, length As Long) As String
496 If startIndex < 0 Or length <= 0 Then Return ""
497 If startIndex + length > m_Length Then Return ""
498
499 Dim temp As String
500 temp.AllocStringBuffer(length)
501 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
502 Chars[m_Length] = 0
503 Return temp
504 End Function
505
506 Const Function Remove(startIndex As Long) As String
507 If startIndex < 0 Or startIndex > m_Length Then
508 Debug 'ArgumentOutOfRangeException
509 End If
510
511 Remove.ReSize(startIndex)
512 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
513 End Function
514
515 Const Function Remove(startIndex As Long, count As Long) As String
516 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
517 Debug 'ArgumentOutOfRangeException
518 End If
519
520 Remove.ReSize(m_Length - count)
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))
523 End Function
524
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
533
534 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
535 Replace = Copy(This)
536 With Replace
537 Dim i As Long
538 For i = 0 To ELM(.m_Length)
539 If .Chars[i] = oldChar Then
540 .Chars[i] = newChar
541 End If
542 Next
543 End With
544 End Function
545
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
555
556 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
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
560 End Function
561
562 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
563 If oldStr = 0 Then Debug 'Throw ArgumentNullException
564 If newStr = 0 Then
565 newStr = ""
566 newLen = 0
567 End If
568 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
569 End Function
570
571 Const Function ToLower() As String
572 ToLower.ReSize(m_Length)
573 Dim i As Long
574 For i = 0 To ELM(m_Length)
575 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
576 Next
577 End Function
578
579 Const Function ToUpper() As String
580 ToUpper.ReSize(m_Length)
581 Dim i As Long
582 For i = 0 To ELM(m_Length)
583 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
584 Next
585 End Function
586
587 Sub Swap(ByRef x As String)
588 Dim tempLen As Long
589 Dim tempChars As *StrChar
590 tempLen = x.m_Length
591 tempChars = x.Chars
592 x.m_Length = This.m_Length
593 x.Chars = This.Chars
594 This.m_Length = tempLen
595 This.Chars = tempChars
596 End Sub
597
598 Override Function ToString() As String
599 Return This
600 End Function
601
602 Static Function Copy(s As String) As String
603 Copy.ReSize(s.m_Length)
604 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
605 End Function
606
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
613 Return _System_GetHashFromWordArray(Chars As *Word, size)
614 End Function
615Private
616 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
617 Function AllocStringBuffer(textLength As Long) As *StrChar
618 If textLength < 0 Then
619 Return 0
620 ElseIf textLength > m_Length Then
621 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
622 If AllocStringBuffer <> 0 Then
623 m_Length = textLength
624 Chars = AllocStringBuffer
625 End If
626 Else
627 m_Length = textLength
628 AllocStringBuffer = Chars
629 End If
630 End Function
631
632 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
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
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
660End Class
Note: See TracBrowser for help on using the repository browser.