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

Last change on this file since 253 was 253, checked in by OverTaker, 17 years ago

Remove,Insertメソッドのバグ修整。時間がないので適当な修整になってしまいました。

File size: 17.7 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
17Namespace System
18
19 Class String
20 ' Inherits IComparable, ICloneable, IConvertible, IEnumerable
21
22 m_Length As Long
23 Public
24 Chars As *StrChar
25
26 Sub String()
27 Chars = _System_malloc(SizeOf (StrChar))
28 Chars[0] = 0
29 m_Length = 0
30 End Sub
31
32 Sub String(initStr As PCSTR)
33 Assign(initStr)
34 End Sub
35
36 Sub String(initStr As PCSTR, length As Long)
37 Assign(initStr, length)
38 End Sub
39
40 Sub String(initStr As PCWSTR)
41 Assign(initStr)
42 End Sub
43
44 Sub String(initStr As PCWSTR, length As Long)
45 Assign(initStr, length)
46 End Sub
47
48 Sub String(ByRef initStr As String)
49 Assign(initStr)
50 End Sub
51
52 Sub String(length As Long)
53 ReSize(length)
54 End Sub
55
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
63#ifdef _DEBUG
64 m_Length = 0
65#endif
66 End Sub
67
68 Const Function Length() As Long
69 Return m_Length
70 End Function
71
72 Function Operator() As *StrChar
73 Return Chars
74 End Function
75
76 Const Function Operator [] (n As Long) As StrChar
77#ifdef _DEBUG
78 If n > Length Then
79 'Throw ArgumentOutOfRangeException
80 Debug
81 End If
82#endif
83 Return Chars[n]
84 End Function
85
86 Sub Operator []= (n As Long, c As StrChar)
87#ifdef _DEBUG
88 If n >= Length Then
89 'Throw ArgumentOutOfRangeException
90 Debug
91 End If
92#endif
93 Chars[n] = c
94 End Sub
95
96 /* Const Function Operator + (text As *Byte) As String
97 Return Concat(text As PCTSTR, lstrlen(text))
98 End Function*/
99
100 Const Function Operator + (text As PCSTR) As String
101 Return Concat(text, lstrlenA(text))
102 End Function
103
104 Const Function Operator + (text As PCWSTR) As String
105 Return Concat(text, lstrlenW(text))
106 End Function
107
108 Const Function Operator + (objString As String) As String
109 Return Concat(objString.Chars, objString.m_Length)
110 End Function
111
112 Const Function Operator & (text As PCSTR) As String
113 Dim tempString = This + text
114 Return tempString
115 End Function
116
117 Const Function Operator & (text As PCWSTR) As String
118 Dim tempString = This + text
119 Return tempString
120 End Function
121
122 Const Function Operator & (objString As String) As String
123 Dim tempString = This + objString
124 Return tempString
125 End Function
126
127 Const Function Operator == (objString As String) As Boolean
128 Return String.Compare(This, objString) = 0
129 End Function
130
131 Const Function Operator == (text As *StrChar) As Boolean
132 Return _System_StrCmp(This.Chars, text) = 0
133 End Function
134
135 Const Function Operator <> (objString As String) As Boolean
136 Return String.Compare(This, objString) <> 0
137 End Function
138
139 Const Function Operator <> (text As *StrChar) As Boolean
140 Return _System_StrCmp(This.Chars, text) <> 0
141 End Function
142
143 Const Function Operator < (objString As String) As Boolean
144 Return String.Compare(This, objString) < 0
145 End Function
146
147 Const Function Operator < (text As *StrChar) As Boolean
148 Return _System_StrCmp(This.Chars, text) < 0
149 End Function
150
151 Const Function Operator > (objString As String) As Boolean
152 Return String.Compare(This, objString) > 0
153 End Function
154
155 Const Function Operator > (text As *StrChar) As Boolean
156 Return _System_StrCmp(This.Chars, text) > 0
157 End Function
158
159 Const Function Operator <= (objString As String) As Boolean
160 Return String.Compare(This, objString) <= 0
161 End Function
162
163 Const Function Operator <= (text As *StrChar) As Boolean
164 Return _System_StrCmp(This.Chars, text) <= 0
165 End Function
166
167 Const Function Operator >= (objString As String) As Boolean
168 Return String.Compare(This, objString) >= 0
169 End Function
170
171 Const Function Operator >= (text As *StrChar) As Boolean
172 Return _System_StrCmp(This.Chars, text) >= 0
173 End Function
174
175 Static Function Compare(x As String, y As String) As Long
176 Return CompareOrdinal(x, y)
177 End Function
178
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
182
183 Static Function CompareOrdinal(x As String, y As String) As Long
184 Return _System_StrCmp(x.Chars, y.Chars)
185 End Function
186
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
196 End If
197 Return _System_StrCmpN(VarPtr(x.Chars[indexX]), VarPtr(y.Chars[indexY]), length As SIZE_T)
198 End Function
199
200 Function CompareTo(y As String) As Long
201 Return String.Compare(This, y)
202 End Function
203
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
211
212 Const Function StrPtr() As *StrChar
213 Return Chars
214 End Function
215
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
227 End If
228 End Sub
229
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
246 End If
247 Chars[m_Length] = 0
248 End Sub
249
250 Sub Assign(text As PCSTR, textLengthA As Long)
251#ifdef __STRING_IS_NOT_UNICODE
252 AssignFromStrChar(text, textLengthA)
253#else
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
259#endif
260 End Sub
261
262 Sub Assign(text As PCWSTR, textLengthW As Long)
263#ifdef __STRING_IS_NOT_UNICODE
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
269#else
270 AssignFromStrChar(text, textLengthW)
271#endif
272 End Sub
273
274 Sub Assign(ByRef objString As String)
275 Assign(objString.Chars, objString.m_Length)
276 End Sub
277
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
286 End If
287 End Sub
288
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
297 End If
298 End Sub
299
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
308
309 Sub Append(text As *StrChar)
310 Append(text, lstrlen(text))
311 End Sub
312
313 Sub Append(ByRef str As String)
314 Append(str.Chars, str.m_Length)
315 End Sub
316
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
332#ifdef __STRING_IS_NOT_UNICODE
333 Return ConcatStrChar(This.Chars, m_Length, text, len)
334#else
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
342#endif
343 End Function
344
345 Const Function Concat(text As PCWSTR, len As Long) As String
346#ifdef __STRING_IS_NOT_UNICODE
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
354#else
355 Return ConcatStrChar(This.Chars, m_Length, text, len)
356#endif
357 End Function
358
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
366
367 Static Function Concat(x As Object, y As Object) As String
368 Return String.Concat(x.ToString, y.ToString)
369 End Function
370
371 Const Function Contains(objString As String) As Boolean
372 Return IndexOf(objString, 0, m_Length) >= 0
373 End Function
374
375 Const Function Contains(lpszText As *StrChar) As Boolean
376 Return IndexOf(lpszText, 0, m_Length) >= 0
377 End Function
378
379 Const Function IndexOf(lpszText As *StrChar) As Long
380 Return IndexOf(lpszText, 0, m_Length)
381 End Function
382
383 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
384 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
385 End Function
386
387 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
388 Dim length = lstrlen(lpszText)
389
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
393
394 If length = 0 Then Return startIndex
395
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
405 Next
406 Return -1
407 End Function
408
409 Const Function LastIndexOf(lpszText As *StrChar) As Long
410 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
411 End Function
412
413 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
414 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
415 End Function
416
417 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
418 Dim length = lstrlen(lpszText)
419
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
423
424 If length = 0 Then Return startIndex
425
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
435 Next
436 Return -1
437 End Function
438
439 Const Function StartsWith(lpszText As *StrChar) As Boolean
440 Return IndexOf(lpszText) = 0
441 End Function
442
443 Const Function EndsWith(lpszText As *StrChar) As Boolean
444 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
445 End Function
446
447 Const Function Insert(startIndex As Long, text As String) As String
448 Return Insert(startIndex, text.Chars, text.Length)
449 End Function
450
451 Const Function Insert(startIndex As Long, text As *StrChar) As String
452 Return Insert(startIndex, text, lstrlen(text))
453 End Function
454
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
458
459 End If
460 Insert = New String(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
465
466 Const Function SubString(startIndex As Long) As String
467 Return SubString(startIndex, m_Length - startIndex)
468 End Function
469
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 ""
473
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
480
481 Const Function Remove(startIndex As Long) As String
482 If startIndex < 0 Or startIndex > m_Length Then
483 Debug 'ArgumentOutOfRangeException
484 End If
485
486 Remove = New String(startIndex)
487 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
488 End Function
489
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
494
495 Remove = New String(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
499
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
505 End If
506 Return True
507 End Function
508
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
520
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
530
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
536
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
545
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
553
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
576
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
581
582 Override Function GetHashCode() As Long
583#ifdef __STRING_IS_NOT_UNICODE
584 Dim size = (m_Length + 1) >> 1
585#else
586 Dim size = m_Length
587#endif
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
602 m_Length = textLength
603 AllocStringBuffer = Chars
604 End If
605 End Function
606
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
627
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.