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

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

StreamReaderの実装開始。
Stringの+演算子で右辺がNullのときに起こるアクセス違反を回避。

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