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

Last change on this file since 270 was 270, checked in by OverTaker, 18 years ago

SubStringのバグ修整。

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
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 Dim oldLength = m_Length
219 If AllocStringBuffer(allocLength) <> 0 Then
220 If allocLength > oldLength Then
221 ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (StrChar) * (m_Length - oldLength + 1))
222 Else
223 Chars[m_Length] = 0
224 End If
225 End If
226 End Sub
227
228 Sub ReSize(allocLength As Long, c As StrChar)
229 If allocLength < 0 Then Exit Sub
230 Dim oldLength = m_Length
231 If AllocStringBuffer(allocLength) <> 0 Then
232 If allocLength > oldLength Then
233 _System_FillChar(VarPtr(Chars[oldLength]), (m_Length - oldLength) As SIZE_T, c)
234 End If
235 Chars[m_Length] = 0
236 End If
237 End Sub
238
239 Sub Assign(text As PCSTR, textLengthA As Long)
240#ifdef __STRING_IS_NOT_UNICODE
241 AssignFromStrChar(text, textLengthA)
242#else
243 Dim textLengthW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, 0, 0)
244 If AllocStringBuffer(textLengthW) <> 0 Then
245 MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, Chars, textLengthW)
246 Chars[textLengthW] = 0
247 End If
248#endif
249 End Sub
250
251 Sub Assign(text As PCWSTR, textLengthW As Long)
252#ifdef __STRING_IS_NOT_UNICODE
253 Dim textLengthA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, 0, 0, 0, 0)
254 If AllocStringBuffer(textLengthA) <> 0 Then
255 WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, Chars, textLengthA, 0, 0)
256 Chars[textLengthA] = 0
257 End If
258#else
259 AssignFromStrChar(text, textLengthW)
260#endif
261 End Sub
262
263 Sub Assign(ByRef objString As String)
264 Assign(objString.Chars, objString.m_Length)
265 End Sub
266
267 Sub Assign(text As PCSTR)
268 If text Then
269 Assign(text, lstrlenA(text))
270 Else
271 If Chars <> 0 Then
272 Chars[0] = 0
273 End If
274 m_Length = 0
275 End If
276 End Sub
277
278 Sub Assign(text As PCWSTR)
279 If text Then
280 Assign(text, lstrlenW(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 Append(text As *StrChar, textLength As Long)
290 Dim prevLen As Long
291 prevLen = m_Length
292 If AllocStringBuffer(m_Length + textLength) <> 0 Then
293 memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
294 Chars[m_Length] = 0
295 End If
296 End Sub
297
298 Sub Append(text As *StrChar)
299 Append(text, lstrlen(text))
300 End Sub
301
302 Sub Append(ByRef str As String)
303 Append(str.Chars, str.m_Length)
304 End Sub
305
306 Const Function Clone() As String
307 Return This
308 End Function
309 Private
310 Static Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
311 ConcatStrChar = New String()
312 With ConcatStrChar
313 .AllocStringBuffer(text1Length + text2Length)
314 memcpy(.Chars, text1, SizeOf (StrChar) * text1Length)
315 memcpy(VarPtr(.Chars[text1Length]), text2, SizeOf (StrChar) * text2Length)
316 .Chars[text1Length + text2Length] = 0
317 End With
318 End Function
319 Public
320 Const Function Concat(text As PCSTR, len As Long) As String
321#ifdef __STRING_IS_NOT_UNICODE
322 Return ConcatStrChar(This.Chars, m_Length, text, len)
323#else
324 With Concat
325 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
326 .AllocStringBuffer(m_Length + lenW)
327 memcpy(.Chars, This.Chars, m_Length)
328 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
329 .Chars[m_Length + lenW] = 0
330 End With
331#endif
332 End Function
333
334 Const Function Concat(text As PCWSTR, len As Long) As String
335#ifdef __STRING_IS_NOT_UNICODE
336 With Concat
337 Dim lenA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
338 .AllocStringBuffer(m_Length + lenA)
339 memcpy(.Chars, This.Chars, m_Length)
340 WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
341 .Chars[m_Length + lenA] = 0
342 End With
343#else
344 Return ConcatStrChar(This.Chars, m_Length, text, len)
345#endif
346 End Function
347
348 Static Function Concat(x As String, y As String) As String
349 If String.IsNullOrEmpty(x) Then
350 Return y
351 Else
352 Return x.Concat(y.Chars, y.m_Length)
353 End If
354 End Function
355
356 Static Function Concat(x As Object, y As Object) As String
357 Return String.Concat(x.ToString, y.ToString)
358 End Function
359
360 Const Function Contains(objString As String) As Boolean
361 Return IndexOf(objString, 0, m_Length) >= 0
362 End Function
363
364 Const Function Contains(lpszText As *StrChar) As Boolean
365 Return IndexOf(lpszText, 0, m_Length) >= 0
366 End Function
367
368 Const Function IndexOf(lpszText As *StrChar) As Long
369 Return IndexOf(lpszText, 0, m_Length)
370 End Function
371
372 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
373 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
374 End Function
375
376 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
377 Dim length = lstrlen(lpszText)
378
379 If startIndex < 0 Then Return -1
380 If count < 1 Or count + startIndex > m_Length Then Return -1
381 If length > m_Length Then Return -1
382
383 If length = 0 Then Return startIndex
384
385 Dim i As Long, j As Long
386 For i = startIndex To startIndex + count - 1
387 For j = 0 To length - 1
388 If Chars[i + j] = lpszText[j] Then
389 If j = length - 1 Then Return i
390 Else
391 Exit For
392 End If
393 Next
394 Next
395 Return -1
396 End Function
397
398 Const Function LastIndexOf(lpszText As *StrChar) As Long
399 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
400 End Function
401
402 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
403 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
404 End Function
405
406 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
407 Dim length = lstrlen(lpszText)
408
409 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
410 If count < 1 Or count > startIndex + 2 Then Return -1
411 If length > m_Length Then Return -1
412
413 If length = 0 Then Return startIndex
414
415 Dim i As Long, j As Long
416 For i = startIndex To startIndex - count + 1 Step -1
417 For j = length - 1 To 0 Step -1
418 If Chars[i + j] = lpszText[j] Then
419 If j = 0 Then Return i
420 Else
421 Exit For
422 End If
423 Next
424 Next
425 Return -1
426 End Function
427
428 Const Function StartsWith(lpszText As *StrChar) As Boolean
429 Return IndexOf(lpszText) = 0
430 End Function
431
432 Const Function EndsWith(lpszText As *StrChar) As Boolean
433 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
434 End Function
435
436 Const Function Insert(startIndex As Long, text As String) As String
437 Return Insert(startIndex, text.Chars, text.Length)
438 End Function
439
440 Const Function Insert(startIndex As Long, text As *StrChar) As String
441 Return Insert(startIndex, text, lstrlen(text))
442 End Function
443
444 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
445 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
446 Debug 'ArgumentOutOfRangeException
447
448 End If
449 Insert = New String(m_Length + length)
450 memcpy(Insert.Chars, Chars, SizeOf (StrChar) * startIndex)
451 memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (StrChar) * length)
452 memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (StrChar) * (m_Length - startIndex + 1))
453 End Function
454
455 Const Function SubString(startIndex As Long) As String
456 Return SubString(startIndex, m_Length - startIndex)
457 End Function
458
459 Const Function SubString(startIndex As Long, length As Long) As String
460 If startIndex < 0 Or length <= 0 Then Return ""
461 If startIndex + length > m_Length Then Return ""
462
463 Dim temp As String
464 temp.AllocStringBuffer(length)
465 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
466 temp.Chars[length] = 0
467 Return temp
468 End Function
469
470 Const Function Remove(startIndex As Long) As String
471 If startIndex < 0 Or startIndex > m_Length Then
472 Debug 'ArgumentOutOfRangeException
473 End If
474
475 Remove = New String(startIndex)
476 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
477 End Function
478
479 Const Function Remove(startIndex As Long, count As Long) As String
480 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
481 Debug 'ArgumentOutOfRangeException
482 End If
483
484 Remove = New String(m_Length - count)
485 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
486 memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (StrChar) * (m_Length - startIndex - count))
487 End Function
488
489 Static Function IsNullOrEmpty(s As String) As Boolean
490 If Not Object.ReferenceEquals(s, Nothing) Then
491 If s.m_Length > 0 Then
492 Return False
493 End If
494 End If
495 Return True
496 End Function
497
498 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
499 Replace = Copy(This)
500 With Replace
501 Dim i As Long
502 For i = 0 To ELM(.m_Length)
503 If .Chars[i] = oldChar Then
504 .Chars[i] = newChar
505 End If
506 Next
507 End With
508 End Function
509
510 Const Function Replace(ByRef oldStr As String, ByRef newStr As String) As String
511 ' If oldStr = Nothing Then Throw ArgumentNullException
512 '
513 ' If newStr = Nothing Then
514 ' Return ReplaceCore(oldStr, oldStr.m_Length, "", 0)
515 ' Else
516 Return ReplaceCore(oldStr, oldStr.m_Length, newStr, newStr.m_Length)
517 ' End If
518 End Function
519
520 Const Function Replace(oldStr As *StrChar, newStr As *StrChar) As String
521 If oldStr = 0 Then Debug 'Throw ArgumentNullException
522 If newStr = 0 Then newStr = ""
523 Return ReplaceCore(oldStr, lstrlen(oldStr), newStr, lstrlen(newStr))
524 End Function
525
526 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
527 If oldStr = 0 Then Debug 'Throw ArgumentNullException
528 If newStr = 0 Then
529 newStr = ""
530 newLen = 0
531 End If
532 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
533 End Function
534
535 Const Function ToLower() As String
536 ToLower.ReSize(m_Length)
537 Dim i As Long
538 For i = 0 To ELM(m_Length)
539 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
540 Next
541 End Function
542
543 Const Function ToUpper() As String
544 ToUpper.ReSize(m_Length)
545 Dim i As Long
546 For i = 0 To ELM(m_Length)
547 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
548 Next
549 End Function
550 /*
551 Sub Swap(ByRef x As String)
552 Dim tempLen As Long
553 Dim tempChars As *StrChar
554 tempLen = x.m_Length
555 tempChars = x.Chars
556 x.m_Length = This.m_Length
557 x.Chars = This.Chars
558 This.m_Length = tempLen
559 This.Chars = tempChars
560 End Sub
561 */
562 Override Function ToString() As String
563 Return This
564 End Function
565
566 Static Function Copy(s As String) As String
567 Copy.ReSize(s.m_Length)
568 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
569 End Function
570
571 Override Function GetHashCode() As Long
572#ifdef __STRING_IS_NOT_UNICODE
573 Dim size = (m_Length + 1) >> 1
574#else
575 Dim size = m_Length
576#endif
577 Return _System_GetHashFromWordArray(Chars As *Word, size)
578 End Function
579 Private
580 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
581 Function AllocStringBuffer(textLength As Long) As *StrChar
582 If textLength < 0 Then
583 Return 0
584 ElseIf textLength > m_Length or Chars = 0 Then
585 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
586 If AllocStringBuffer <> 0 Then
587 m_Length = textLength
588 Chars = AllocStringBuffer
589 End If
590 Else
591 m_Length = textLength
592 AllocStringBuffer = Chars
593 End If
594 End Function
595
596 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
597 If oldLen = 0 Then
598 Debug 'Throw ArgumentException
599 End If
600 Dim tmp As String
601 With tmp
602 Dim current = 0 As Long
603 Do
604 Dim pos = IndexOf(oldStr, current)
605 If pos = -1 Then
606 Exit Do
607 End If
608 .Append(VarPtr(Chars[current]), pos - current)
609 .Append(newStr, newLen)
610 current = pos + oldLen
611 Loop
612 .Append(VarPtr(Chars[current]), m_Length - current)
613 End With
614 Return tmp
615 End Function
616
617 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
618 If text = Chars Then Exit Sub
619 If AllocStringBuffer(textLength) <> 0 Then
620 memcpy(Chars, text, SizeOf (StrChar) * textLength)
621 Chars[m_Length] = 0
622 End If
623 End Sub
624 End Class
625
626End Namespace
Note: See TracBrowser for help on using the repository browser.