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

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

FileStream非同期読み書きの修正、例外処理の追加。

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