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
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 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
368
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
377 End With
378#else
379 Return ConcatStrChar(This.Chars, m_Length, text, len)
380#endif
381 End Function
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
396 Return IndexOf(objString, 0, m_Length) >= 0
397 End Function
398
399 Const Function Contains(lpszText As *StrChar) As Boolean
400 Return IndexOf(lpszText, 0, m_Length) >= 0
401 End Function
402
403 Const Function IndexOf(lpszText As *StrChar) As Long
404 Return IndexOf(lpszText, 0, m_Length)
405 End Function
406
407 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
408 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
409 End Function
410
411 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
412 Dim length = lstrlen(lpszText)
413
414 If startIndex < 0 Then Return -1
415 If count < 1 Or count + startIndex > m_Length Then Return -1
416 If length > m_Length Then Return -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
423 If Chars[i + j] = lpszText[j] Then
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
433 Const Function LastIndexOf(lpszText As *StrChar) As Long
434 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
435 End Function
436
437 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
438 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
439 End Function
440
441 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
442 Dim length = lstrlen(lpszText)
443
444 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
445 If count < 1 Or count > startIndex + 2 Then Return -1
446 If length > m_Length Then Return -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
453 If Chars[i + j] = lpszText[j] Then
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
463 Const Function StartsWith(lpszText As *StrChar) As Boolean
464 Return IndexOf(lpszText) = 0
465 End Function
466
467 Const Function EndsWith(lpszText As *StrChar) As Boolean
468 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
469 End Function
470
471 Const Function Insert(startIndex As Long, text As String) As String
472 Return Insert(startIndex, text.Chars, text.Length)
473 End Function
474
475 Const Function Insert(startIndex As Long, text As *StrChar) As String
476 Return Insert(startIndex, text, lstrlen(text))
477 End Function
478
479 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
480 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
481 Debug 'ArgumentOutOfRangeException
482
483 End If
484 Insert.ReSize(m_Length + length)
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))
488 End Function
489
490 Const Function SubString(startIndex As Long) As String
491 Return SubString(startIndex, m_Length - startIndex)
492 End Function
493
494 Const Function SubString(startIndex As Long, length As Long) As String
495 If startIndex < 0 Or length <= 0 Then Return ""
496 If startIndex + length > m_Length Then Return ""
497
498 Dim temp As String
499 temp.AllocStringBuffer(length)
500 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
501 Chars[m_Length] = 0
502 Return temp
503 End Function
504
505 Const Function Remove(startIndex As Long) As String
506 If startIndex < 0 Or startIndex > m_Length Then
507 Debug 'ArgumentOutOfRangeException
508 End If
509
510 Remove.ReSize(startIndex)
511 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
512 End Function
513
514 Const Function Remove(startIndex As Long, count As Long) As String
515 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
516 Debug 'ArgumentOutOfRangeException
517 End If
518
519 Remove.ReSize(m_Length - count)
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))
522 End Function
523
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
532
533 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
534 Replace = Copy(This)
535 With Replace
536 Dim i As Long
537 For i = 0 To ELM(.m_Length)
538 If .Chars[i] = oldChar Then
539 .Chars[i] = newChar
540 End If
541 Next
542 End With
543 End Function
544
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
554
555 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
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
559 End Function
560
561 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
562 If oldStr = 0 Then Debug 'Throw ArgumentNullException
563 If newStr = 0 Then
564 newStr = ""
565 newLen = 0
566 End If
567 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
568 End Function
569
570 Const Function ToLower() As String
571 ToLower.ReSize(m_Length)
572 Dim i As Long
573 For i = 0 To ELM(m_Length)
574 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
575 Next
576 End Function
577
578 Const Function ToUpper() As String
579 ToUpper.ReSize(m_Length)
580 Dim i As Long
581 For i = 0 To ELM(m_Length)
582 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
583 Next
584 End Function
585
586 Sub Swap(ByRef x As String)
587 Dim tempLen As Long
588 Dim tempChars As *StrChar
589 tempLen = x.m_Length
590 tempChars = x.Chars
591 x.m_Length = This.m_Length
592 x.Chars = This.Chars
593 This.m_Length = tempLen
594 This.Chars = tempChars
595 End Sub
596
597 Override Function ToString() As String
598 Return This
599 End Function
600
601 Static Function Copy(s As String) As String
602 Copy.ReSize(s.m_Length)
603 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
604 End Function
605
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
612 Return _System_GetHashFromWordArray(Chars As *Word, size)
613 End Function
614Private
615 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
616 Function AllocStringBuffer(textLength As Long) As *StrChar
617 If textLength < 0 Then
618 Return 0
619 ElseIf textLength > m_Length Then
620 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
621 If AllocStringBuffer <> 0 Then
622 m_Length = textLength
623 Chars = AllocStringBuffer
624 End If
625 Else
626 m_Length = textLength
627 AllocStringBuffer = Chars
628 End If
629 End Function
630
631 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
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
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
659End Class
Note: See TracBrowser for help on using the repository browser.