source: trunk/Include/Classes/System/String.ab@ 468

Last change on this file since 468 was 468, checked in by イグトランス (egtra), 16 years ago

TextWriter, StreamWriterの追加。
SPrintfの浮動小数点数変換で、NaN, Infiniteの出力に対応。
PathとDirectoryInfoのCreateDirectoryで、対象が既に存在するときには例外を投げないように修正。
SimpleTestCase内で使用する一時フォルダの場所にGetTempPathで取得する版を追加(コメントアウト)。

File size: 19.5 KB
Line 
1' Classes/System/String.ab
2
3#require <basic/function.sbp>
4#require <Classes/System/Text/StringBuilder.ab>
5#require <Classes/ActiveBasic/Strings/Strings.ab>
6
7TypeDef StrChar = Char
8
9#ifdef UNICODE
10#define __STRING_IS_UNICODE
11#else
12#define __STRING_IS_NOT_UNICODE
13#endif
14
15Namespace System
16
17 Class String
18 Implements /*IComparable, ICloneable, IConvertible, IComparable<String>, IEnumerable, IEnumerable<Char>, IEquatable<String>*/
19
20 m_Length As Long
21 Chars As *Char
22
23 Sub validPointerCheck(p As VoidPtr, size = 1 As Long)
24 If p As ULONG_PTR < &h10000 Then
25 Throw New ArgumentException
26 ElseIf IsBadReadPtr(p, size As ULONG_PTR) Then
27 Throw New ArgumentException
28 End If
29 End Sub
30 Public
31 Static Const Empty = New String
32
33 Sub String()
34' Chars = 0
35' m_Length = 0
36 End Sub
37
38 Sub String(initStr As PCWSTR)
39 validPointerCheck(initStr)
40 Assign(initStr, lstrlenW(initStr))
41 End Sub
42
43 Sub String(initStr As PCWSTR, length As Long)
44 validPointerCheck(initStr, length)
45 Assign(initStr, length)
46 End Sub
47
48 Sub String(initStr As PCWSTR, start As Long, length As Long)
49 If start < 0 Or length Or start + length < 0 Then
50 Throw New ArgumentOutOfRangeException("String constractor: One or more arguments are out of range value.", "start or length or both")
51 End If
52 validPointerCheck(initStr + start, length)
53 Assign(initStr + start, length)
54 End Sub
55
56 Sub String(initStr As PCSTR)
57 validPointerCheck(initStr)
58 Assign(initStr, lstrlenA(initStr))
59 End Sub
60
61 Sub String(initStr As PCSTR, length As Long)
62 validPointerCheck(initStr, length)
63 Assign(initStr, length)
64 End Sub
65
66 Sub String(initStr As PCSTR, start As Long, length As Long)
67 If start < 0 Or length < 0 Then
68 Throw New ArgumentOutOfRangeException("String constructor: One or more arguments are out of range value.", "start or length or both")
69 End If
70 validPointerCheck(initStr + start, length)
71 Assign(initStr + start, length)
72 End Sub
73
74 Sub String(initStr As String)
75 If Not String.IsNullOrEmpty(initStr) Then
76 Assign(initStr.Chars, initStr.m_Length)
77 End If
78 End Sub
79
80 Sub String(initChar As Char, length As Long)
81 AllocStringBuffer(length)
82 ActiveBasic.Strings.ChrFill(Chars, length, initChar)
83 Chars[length] = 0
84 End Sub
85
86 Sub String(sb As Text.StringBuilder)
87 Chars = StrPtr(sb)
88 m_Length = sb.Length
89 sb.__Stringized()
90 End Sub
91
92 Const Function Length() As Long
93 Return m_Length
94 End Function
95
96 Function Operator() As *Char
97 Return Chars
98 End Function
99
100 Const Function Operator [] (n As Long) As Char
101 rangeCheck(n)
102 Return Chars[n]
103 End Function
104
105 Const Function Operator + (y As PCSTR) As String
106 If y = 0 Then
107 Return This
108 Else
109 Return Concat(y, lstrlenA(y))
110 End If
111 End Function
112
113 Const Function Operator + (y As PCWSTR) As String
114 If y = 0 Then
115 Return This
116 Else
117 Return Concat(y, lstrlenW(y))
118 End If
119 End Function
120
121 Const Function Operator + (y As String) As String
122 If ActiveBasic.IsNothing(y) Then
123 Return This
124 Else
125 Return Concat(y.Chars, y.m_Length)
126 End If
127 End Function
128
129 Const Function Operator & (y As PCSTR) As String
130 Return This + y
131 End Function
132
133 Const Function Operator & (y As PCWSTR) As String
134 Return This + y
135 End Function
136
137 Const Function Operator & (y As String) As String
138 Return This + y
139 End Function
140
141 Const Function Operator == (y As String) As Boolean
142 Return Compare(This, y) = 0
143 End Function
144
145 Const Function Operator == (y As *Char) As Boolean
146 Return Compare(This, y) = 0
147 End Function
148
149 Const Function Operator <> (y As String) As Boolean
150 Return Compare(This, y) <> 0
151 End Function
152
153 Const Function Operator <> (y As *Char) As Boolean
154 Return Compare(This, y) <> 0
155 End Function
156
157 Const Function Operator < (y As String) As Boolean
158 Return Compare(This, y) < 0
159 End Function
160
161 Const Function Operator < (y As *Char) As Boolean
162 Return Compare(This, y) < 0
163 End Function
164
165 Const Function Operator > (y As String) As Boolean
166 Return Compare(This, y) > 0
167 End Function
168
169 Const Function Operator > (y As *Char) As Boolean
170 Return Compare(This, y) > 0
171 End Function
172
173 Const Function Operator <= (y As String) As Boolean
174 Return Compare(This, y) <= 0
175 End Function
176
177 Const Function Operator <= (y As *Char) As Boolean
178 Return Compare(This, y) <= 0
179 End Function
180
181 Const Function Operator >= (y As String) As Boolean
182 Return Compare(This, y) >= 0
183 End Function
184
185 Const Function Operator >= (y As *Char) As Boolean
186 Return Compare(This, y) >= 0
187 End Function
188
189 Static Function Compare(x As String, y As String) As Long
190 Return CompareOrdinal(x, y)
191 End Function
192
193 Public
194 'Compareなどで、x.Charsではなく、StrPtr(x)と書く理由は、xがNothingの場合のため。
195
196 Static Function Compare(x As String, indexX As Long, y As String, indexY As Long, length As Long) As Long
197 Return CompareOrdinal(x, indexX, y, indexY, length)
198 End Function
199
200 Static Function CompareOrdinal(x As String, y As String) As Long
201 Return CompareOrdinal(StrPtr(x), StrPtr(y))
202 End Function
203
204 Static Function CompareOrdinal(x As String, indexX As Long, y As String, indexY As Long, length As Long) As Long
205 Return CompareOrdinal(StrPtr(x), indexX, StrPtr(y), indexY, length)
206 End Function
207 Private
208 Static Function Compare(x As String, y As *Char) As Long
209 Return CompareOrdinal(x, y)
210 End Function
211
212 Static Function CompareOrdinal(x As String, y As *Char) As Long
213 Return CompareOrdinal(StrPtr(x), y)
214 End Function
215
216 Static Function CompareOrdinal(x As *Char, y As *Char) As Long
217 If x = 0 Then
218 If y = 0 Then
219 Return 0
220 Else
221 Return -1
222 End If
223 ElseIf y = 0 Then
224 Return 1
225 End If
226 Return ActiveBasic.Strings.StrCmp(x, y)
227 End Function
228
229 Static Function CompareOrdinal(x As *Char, indexX As Long, y As *Char, indexY As Long, length As Long) As Long
230 If x = 0 Then
231 If y = 0 Then
232 Return 0
233 Else
234 Return -1
235 End If
236 ElseIf y = 0 Then
237 Return 1
238 End If
239 Return ActiveBasic.Strings.ChrCmp(VarPtr(x[indexX]), VarPtr(y[indexY]), length As SIZE_T)
240 End Function
241 Public
242 Function CompareTo(y As String) As Long
243 Return String.Compare(This, y)
244 End Function
245
246 Function CompareTo(y As Object) As Long
247 If Not Object.Equals(This.GetType(), y.GetType()) Then
248 Throw New ArgumentException("String.CompareTo: The type of the argument y is not String.", "y")
249 End If
250 Return CompareTo(y As String)
251 End Function
252
253 Function Equals(s As String) As Boolean
254 Return This = s
255 End Function
256
257 Override Function Equals(s As Object) As Boolean
258 If Object.Equals( This.GetType(), s.GetType() ) Then
259 Return This.Equals(s As String)
260 End If
261 Return False
262 End Function
263
264 Const Function StrPtr() As *Char
265 Return Chars
266 End Function
267Private
268
269 Sub Assign(text As PCSTR, textLengthA As Long)
270#ifdef __STRING_IS_NOT_UNICODE
271 AssignFromCharPtr(text, textLengthA)
272#else
273 Dim textLengthW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, 0, 0)
274 If AllocStringBuffer(textLengthW) <> 0 Then
275 MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, Chars, textLengthW)
276 Chars[textLengthW] = 0
277 End If
278#endif
279 End Sub
280
281 Sub Assign(text As PCWSTR, textLengthW As Long)
282#ifdef __STRING_IS_NOT_UNICODE
283 Dim textLengthA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, 0, 0, 0, 0)
284 If AllocStringBuffer(textLengthA) <> 0 Then
285 WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, Chars, textLengthA, 0, 0)
286 Chars[textLengthA] = 0
287 End If
288#else
289 AssignFromCharPtr(text, textLengthW)
290#endif
291 End Sub
292
293 Private
294 Static Function ConcatChar(text1 As *Char, text1Length As Long, text2 As *Char, text2Length As Long) As String
295 ConcatChar = New String()
296 With ConcatChar
297 .AllocStringBuffer(text1Length + text2Length)
298 ActiveBasic.Strings.ChrCopy(.Chars, text1, text1Length As SIZE_T)
299 ActiveBasic.Strings.ChrCopy(VarPtr(.Chars[text1Length]), text2, text2Length As SIZE_T)
300 .Chars[text1Length + text2Length] = 0
301 End With
302 End Function
303 Public
304 Const Function Concat(text As PCSTR, len As Long) As String
305#ifdef __STRING_IS_NOT_UNICODE
306 Return ConcatChar(This.Chars, m_Length, text, len)
307#else
308 With Concat
309 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
310 Concat = New String
311 .AllocStringBuffer(m_Length + lenW)
312 ActiveBasic.Strings.ChrCopy(.Chars, This.Chars, m_Length As SIZE_T)
313 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
314 .Chars[m_Length + lenW] = 0
315 End With
316#endif
317 End Function
318
319 Const Function Concat(text As PCWSTR, len As Long) As String
320#ifdef __STRING_IS_NOT_UNICODE
321 With Concat
322 Concat = New String
323 Dim lenA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
324 .AllocStringBuffer(m_Length + lenA)
325 ActiveBasic.Strings.ChrCopy(.Chars, This.Chars, m_Length As SIZE_T)
326 WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
327 .Chars[m_Length + lenA] = 0
328 End With
329#else
330 Return ConcatChar(This.Chars, m_Length, text, len)
331#endif
332 End Function
333
334 Static Function Concat(x As String, y As String) As String
335 If String.IsNullOrEmpty(x) Then
336 Return y
337 Else
338 Return x.Concat(y.Chars, y.m_Length)
339 End If
340 End Function
341
342 Static Function Concat(x As String, y As String, z As String) As String
343 Dim sb = New Text.StringBuilder(removeNull(x).Length + removeNull(y).Length + removeNull(z).Length)
344 sb.Append(x).Append(y).Append(z)
345 Concat = sb.ToString
346 End Function
347
348 Static Function Concat(x As String, y As String, z As String, w As String) As String
349 Dim sb = New Text.StringBuilder(removeNull(x).Length + removeNull(y).Length + removeNull(z).Length + removeNull(w).Length)
350 sb.Append(x).Append(y).Append(z).Append(w)
351 Concat = sb.ToString
352 End Function
353
354 Static Function Concat(x As Object, y As Object) As String
355 Return Concat(x.ToString, y.ToString)
356 End Function
357
358 Static Function Concat(x As Object, y As Object, z As Object) As String
359 Return Concat(x.ToString, y.ToString, z.ToString)
360 End Function
361
362 Static Function Concat(x As Object, y As Object, z As Object, w As Object) As String
363 Return Concat(x.ToString, y.ToString, z.ToString, w.ToString)
364 End Function
365
366 Const Function Contains(c As Char) As Boolean
367 Return IndexOf(c) >= 0
368 End Function
369
370 Const Function Contains(s As String) As Boolean
371 If Object.ReferenceEquals(s, Nothing) Then
372 Throw New ArgumentNullException("String.Contains: An argument is null value.", "s")
373 ElseIf s = "" Then
374 Return True
375 Else
376 Return IndexOf(s, 0, m_Length) >= 0
377 End If
378 End Function
379
380 Const Function IndexOf(c As Char) As Long
381 Return indexOfCore(c, 0, m_Length)
382 End Function
383
384 Const Function IndexOf(c As Char, start As Long) As Long
385 rangeCheck(start)
386 Return indexOfCore(c, start, m_Length - start)
387 End Function
388
389 Const Function IndexOf(c As Char, start As Long, count As Long) As Long
390 rangeCheck(start, count)
391 Return indexOfCore(c, start, count)
392 End Function
393 Private
394 Const Function indexOfCore(c As Char, start As Long, count As Long) As Long
395 indexOfCore = ActiveBasic.Strings.ChrFind(VarPtr(Chars[start]), count, c) As Long
396 If indexOfCore <> -1 Then
397 indexOfCore += start
398 End If
399 End Function
400 Public
401 Const Function IndexOf(s As String) As Long
402 Return IndexOf(s, 0, m_Length)
403 End Function
404
405 Const Function IndexOf(s As String, startIndex As Long) As Long
406 Return IndexOf(s, startIndex, m_Length - startIndex)
407 End Function
408
409 Const Function IndexOf(s As String, startIndex As Long, count As Long) As Long
410 rangeCheck(startIndex, count)
411 If Object.ReferenceEquals(s, Nothing) Then
412 Throw New ArgumentNullException("String.IndexOf: An argument is out of range value.", "s")
413 End If
414
415 Dim length = s.Length
416 If length = 0 Then Return startIndex
417
418 Dim i As Long, j As Long
419 For i = startIndex To startIndex + count - 1
420 For j = 0 To length - 1
421 If Chars[i + j] = s[j] Then
422 If j = length - 1 Then Return i
423 Else
424 Exit For
425 End If
426 Next
427 Next
428 Return -1
429 End Function
430
431 Const Function LastIndexOf(c As Char) As Long
432 Return lastIndexOf(c, m_Length - 1, m_Length)
433 End Function
434
435 Const Function LastIndexOf(c As Char, start As Long) As Long
436 rangeCheck(start)
437 Return lastIndexOf(c, start, start + 1)
438 End Function
439
440 Const Function LastIndexOf(c As Char, start As Long, count As Long) As Long
441 rangeCheck(start)
442 Dim lastFindPos = start - (count - 1)
443 If Not (m_Length > lastFindPos And lastFindPos >= 0) Then
444 Throw New ArgumentOutOfRangeException("String.LastIndexOf: An argument is out of range value.", "count")
445 End If
446 Return lastIndexOf(c, start, count)
447 End Function
448 Private
449 Const Function lastIndexOf(c As Char, start As Long, count As Long) As Long
450 Dim lastFindPos = start - (count - 1)
451 Dim i As Long
452 For i = start To lastFindPos Step -1
453 If Chars[i] = c Then
454 Return i
455 End If
456 Next
457 Return -1
458 End Function
459
460 Public
461 Const Function LastIndexOf(s As String) As Long
462 Return LastIndexOf(s, m_Length - 1, m_Length)
463 End Function
464
465 Const Function LastIndexOf(s As String, startIndex As Long) As Long
466 Return LastIndexOf(s, startIndex, startIndex + 1)
467 End Function
468
469 Const Function LastIndexOf(s As String, start As Long, count As Long) As Long
470 If Object.ReferenceEquals(s, Nothing) Then
471 Throw New ArgumentNullException("String.LastIndexOf: An argument is out of range value.", "s")
472 End If
473
474 If start < 0 Or start > m_Length - 1 Or _
475 count < 0 Or count > start + 2 Then
476 Throw New ArgumentOutOfRangeException("String.LastIndexOf: One or more arguments are out of range value.", "start or count or both")
477 End If
478 Dim length = s.m_Length
479 If length > m_Length Then Return -1
480 If length = 0 Then Return start
481
482 Dim i As Long, j As Long
483 For i = start To start - count + 1 Step -1
484 For j = length - 1 To 0 Step -1
485 If Chars[i + j] = s[j] Then
486 If j = 0 Then Return i
487 Else
488 Exit For
489 End If
490 Next
491 Next
492 Return -1
493 End Function
494
495 Const Function StartsWith(c As Char) As Boolean
496 Return IndexOf(c) = 0
497 End Function
498
499 Const Function StartsWith(s As String) As Boolean
500 Return IndexOf(s) = 0
501 End Function
502
503 Const Function EndsWith(c As Char) As Boolean
504 Return LastIndexOf(c) = m_Length - 1
505 End Function
506
507 Const Function EndsWith(s As String) As Boolean
508 Return LastIndexOf(s) = m_Length - s.Length
509 End Function
510
511 Const Function Insert(startIndex As Long, text As String) As String
512 Dim sb = New Text.StringBuilder(This)
513 sb.Insert(startIndex, text)
514 Return sb.ToString
515 End Function
516
517 Const Function Substring(startIndex As Long) As String
518 rangeCheck(startIndex)
519 Return Substring(startIndex, m_Length - startIndex)
520 End Function
521
522 Const Function Substring(startIndex As Long, length As Long) As String
523 rangeCheck(startIndex, length)
524 Return New String(Chars, startIndex, length)
525 End Function
526
527 Const Function Remove(startIndex As Long) As String
528 rangeCheck(startIndex)
529 Remove = Substring(0, startIndex)
530 End Function
531
532 Const Function Remove(startIndex As Long, count As Long) As String
533 Dim sb = New Text.StringBuilder(This)
534 sb.Remove(startIndex, count)
535 Remove = sb.ToString
536 End Function
537
538 Static Function IsNullOrEmpty(s As String) As Boolean
539 If Not Object.ReferenceEquals(s, Nothing) Then
540 If s.m_Length > 0 Then
541 Return False
542 End If
543 End If
544 Return True
545 End Function
546
547 Const Function Replace(oldChar As Char, newChar As Char) As String
548 Dim sb = New Text.StringBuilder(This)
549 sb.Replace(oldChar, newChar)
550 Replace = sb.ToString
551 End Function
552
553 Const Function Replace(oldStr As String, newStr As String) As String
554 Dim sb = New Text.StringBuilder(This)
555 sb.Replace(oldStr, newStr)
556 Return sb.ToString
557 End Function
558
559 Const Function ToLower() As String
560 Dim sb = New Text.StringBuilder(m_Length)
561 sb.Length = m_Length
562 Dim i As Long
563 For i = 0 To ELM(m_Length)
564 sb[i] = ActiveBasic.CType.ToLower(Chars[i])
565 Next
566 Return sb.ToString
567 End Function
568
569 Const Function ToUpper() As String
570 Dim sb = New Text.StringBuilder(m_Length)
571 sb.Length = m_Length
572 Dim i As Long
573 For i = 0 To ELM(m_Length)
574 sb[i] = ActiveBasic.CType.ToUpper(Chars[i])
575 Next
576 Return sb.ToString
577 End Function
578
579 Override Function ToString() As String
580 ToString = This
581 End Function
582
583 Const Function Clone() As String
584 Clone = This
585 End Function
586/*
587 Function Clone() As Object
588 Clone = This
589 End Function
590*/
591 Static Function Copy(s As String) As String
592 Copy = New String(s.Chars, s.m_Length)
593 End Function
594
595 Sub CopyTo(sourceIndex As Long, destination As *Char, destinationIndex As Long, count As Long)
596 ActiveBasic.Strings.ChrCopy(VarPtr(destination[destinationIndex]), VarPtr(Chars[sourceIndex]), count As SIZE_T)
597 End Sub
598
599 Override Function GetHashCode() As Long
600#ifdef __STRING_IS_NOT_UNICODE
601 Dim size = (m_Length + 1) >> 1
602#else
603 Dim size = m_Length
604#endif
605 Return _System_GetHashFromWordArray(Chars As *Word, size) Xor m_Length
606 End Function
607
608 Function PadLeft(total As Long) As String
609 PadLeft(total, &h30 As Char)
610 End Function
611
612 Function PadLeft(total As Long, c As Char) As String
613 If total < 0 Then
614 Throw New ArgumentOutOfRangeException("String.PadLeft: An arguments is out of range value.", "total")
615 End If
616 If total >= m_Length Then
617 Return This
618 End If
619 Dim sb = New Text.StringBuilder(total)
620 sb.Append(c, total - m_Length)
621 sb.Append(This)
622 Return sb.ToString
623 End Function
624
625 Function PadRight(total As Long) As String
626 PadRight(total, &h30 As Char)
627 End Function
628
629 Function PadRight(total As Long, c As Char) As String
630 If total < 0 Then
631 Throw New ArgumentOutOfRangeException("String.PadRight: An arguments is out of range value.", "total")
632 End If
633 If total >= m_Length Then
634 Return This
635 End If
636 Dim sb = New Text.StringBuilder(total)
637 sb.Append(This)
638 sb.Append(c, total - m_Length)
639 Return sb.ToString
640 End Function
641 Private
642 Function AllocStringBuffer(textLength As Long) As *Char
643 If textLength < 0 Then
644 Return 0
645 End If
646 AllocStringBuffer = GC_malloc_atomic(SizeOf(Char) * (textLength + 1))
647 If AllocStringBuffer = 0 Then
648 'Throw New OutOfMemoryException
649 End If
650 m_Length = textLength
651 Chars = AllocStringBuffer
652 End Function
653
654 Sub AssignFromCharPtr(text As *Char, textLength As Long)
655 AllocStringBuffer(textLength)
656 ActiveBasic.Strings.ChrCopy(Chars, text, textLength As SIZE_T)
657 Chars[m_Length] = 0
658 End Sub
659
660 Const Sub rangeCheck(index As Long)
661 If index < 0 Or index > m_Length Then
662 Throw New ArgumentOutOfRangeException("String: An arguments is out of range value.", "index")
663 End If
664 End Sub
665
666 Const Sub rangeCheck(start As Long, length As Long)
667 If start < 0 Or start > This.m_Length Or length < 0 Then
668 Throw New ArgumentOutOfRangeException("String: One or more arguments are out of range value.", "start or length or both")
669 End If
670 End Sub
671
672 Static Function removeNull(s As String) As String
673 If ActiveBasic.IsNothing(s) Then
674 removeNull = Empty
675 Else
676 removeNull = s
677 End If
678 End Function
679 End Class
680
681End Namespace
Note: See TracBrowser for help on using the repository browser.