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
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
[426]119 If y = 0 Then
120 Return This
121 Else
122 Return Concat(y, lstrlenA(y))
123 End If
[246]124 End Function
[139]125
[272]126 Const Function Operator + (y As PCWSTR) As String
[426]127 If y = 0 Then
128 Return This
129 Else
130 Return Concat(y, lstrlenW(y))
131 End If
[246]132 End Function
[139]133
[272]134 Const Function Operator + (y As String) As String
[426]135 If ActiveBasic.IsNothing(y) Then
136 Return This
137 Else
138 Return Concat(y.Chars, y.m_Length)
139 End If
[246]140 End Function
[1]141
[272]142 Const Function Operator & (y As PCSTR) As String
143 Return This + y
[246]144 End Function
[1]145
[272]146 Const Function Operator & (y As PCWSTR) As String
[426]147 Return This + y
[246]148 End Function
[139]149
[272]150 Const Function Operator & (y As String) As String
[426]151 Return This + y
[246]152 End Function
[1]153
[272]154 Const Function Operator == (y As String) As Boolean
155 Return String.Compare(This, y) = 0
[246]156 End Function
[1]157
[272]158 Const Function Operator == (y As *StrChar) As Boolean
159 Return String.Compare(This, y) = 0
[246]160 End Function
[1]161
[272]162 Const Function Operator <> (y As String) As Boolean
163 Return String.Compare(This, y) <> 0
[246]164 End Function
[1]165
[272]166 Const Function Operator <> (y As *StrChar) As Boolean
167 Return String.Compare(This, y) <> 0
[246]168 End Function
[1]169
[272]170 Const Function Operator < (y As String) As Boolean
171 Return String.Compare(This, y) < 0
[246]172 End Function
[1]173
[272]174 Const Function Operator < (y As *StrChar) As Boolean
175 Return String.Compare(This, y) < 0
[246]176 End Function
[1]177
[272]178 Const Function Operator > (y As String) As Boolean
179 Return String.Compare(This, y) > 0
[246]180 End Function
[1]181
[272]182 Const Function Operator > (y As *StrChar) As Boolean
183 Return String.Compare(This, y) > 0
[246]184 End Function
[1]185
[272]186 Const Function Operator <= (y As String) As Boolean
187 Return String.Compare(This, y) <= 0
[246]188 End Function
[1]189
[272]190 Const Function Operator <= (y As *StrChar) As Boolean
191 Return String.Compare(This, y) <= 0
[246]192 End Function
[1]193
[272]194 Const Function Operator >= (y As String) As Boolean
195 Return String.Compare(This, y) >= 0
[246]196 End Function
[1]197
[272]198 Const Function Operator >= (y As *StrChar) As Boolean
199 Return String.Compare(This, y) >= 0
[246]200 End Function
[1]201
[246]202 Static Function Compare(x As String, y As String) As Long
203 Return CompareOrdinal(x, y)
204 End Function
[203]205
[272]206 Public
[246]207 Static Function Compare(x As String, indexX As Long, y As String, indexY As Long, length As Long) As Long
[272]208 Return String.CompareOrdinal(x, indexX, y, indexY, length)
[246]209 End Function
[203]210
[246]211 Static Function CompareOrdinal(x As String, y As String) As Long
[272]212 Return String.CompareOrdinal(x.Chars, y.Chars)
[246]213 End Function
[203]214
[246]215 Static Function CompareOrdinal(x As String, indexX As Long, y As String, indexY As Long, length As Long) As Long
[272]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
[246]230 Return 0
231 Else
232 Return -1
233 End If
[272]234 ElseIf y = 0 Then
[246]235 Return 1
[203]236 End If
[272]237 Return ActiveBasic.Strings.StrCmp(x, y)
[246]238 End Function
[203]239
[272]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
[246]253 Function CompareTo(y As String) As Long
254 Return String.Compare(This, y)
255 End Function
[203]256
[246]257 Function CompareTo(y As Object) As Long
[388]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
[272]261 Return CompareTo(y As String)
[246]262 End Function
[203]263
[308]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
[366]269 If Object.Equals( This.GetType(), s.GetType() ) Then
[308]270 Return This.Equals(s As String)
271 End If
272 Return False
273 End Function
274
[246]275 Const Function StrPtr() As *StrChar
276 Return Chars
277 End Function
[272]278Private
[1]279
[246]280 Sub Assign(text As PCSTR, textLengthA As Long)
[175]281#ifdef __STRING_IS_NOT_UNICODE
[246]282 AssignFromStrChar(text, textLengthA)
[139]283#else
[246]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
[139]289#endif
[246]290 End Sub
[1]291
[246]292 Sub Assign(text As PCWSTR, textLengthW As Long)
[139]293#ifdef __STRING_IS_NOT_UNICODE
[246]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
[139]299#else
[246]300 AssignFromStrChar(text, textLengthW)
[139]301#endif
[246]302 End Sub
[139]303
[246]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)
[272]309 ActiveBasic.Strings.ChrCopy(.Chars, text1, text1Length As SIZE_T)
310 ActiveBasic.Strings.ChrCopy(VarPtr(.Chars[text1Length]), text2, text2Length As SIZE_T)
[246]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
[139]316#ifdef __STRING_IS_NOT_UNICODE
[246]317 Return ConcatStrChar(This.Chars, m_Length, text, len)
[139]318#else
[246]319 With Concat
320 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
[272]321 Concat = New String
[246]322 .AllocStringBuffer(m_Length + lenW)
[400]323 ActiveBasic.Strings.ChrCopy(.Chars, This.Chars, m_Length As SIZE_T)
[246]324 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
325 .Chars[m_Length + lenW] = 0
326 End With
[139]327#endif
[246]328 End Function
[132]329
[246]330 Const Function Concat(text As PCWSTR, len As Long) As String
[139]331#ifdef __STRING_IS_NOT_UNICODE
[246]332 With Concat
[272]333 Concat = New String
[246]334 Dim lenA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
335 .AllocStringBuffer(m_Length + lenA)
[272]336 ActiveBasic.Strings.ChrCopy(.Chars, This.Chars, m_Length As SIZE_T)
[246]337 WideCharToMultiByte(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
338 .Chars[m_Length + lenA] = 0
339 End With
[139]340#else
[246]341 Return ConcatStrChar(This.Chars, m_Length, text, len)
[139]342#endif
[246]343 End Function
[203]344
[246]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
[203]352
[246]353 Static Function Concat(x As Object, y As Object) As String
354 Return String.Concat(x.ToString, y.ToString)
355 End Function
[203]356
[272]357 Const Function Contains(s As String) As Boolean
358 If Object.ReferenceEquals(s, Nothing) Then
[391]359 Throw New ArgumentNullException("String.Contains: An argument is null value.", "s")
[388]360 ElseIf s = "" Then
361 Return True
362 Else
363 Return IndexOf(s, 0, m_Length) >= 0
[272]364 End If
[246]365 End Function
[1]366
[272]367 Const Function IndexOf(c As StrChar) As Long
368 Return indexOfCore(c, 0, m_Length)
[246]369 End Function
[1]370
[272]371 Const Function IndexOf(c As StrChar, start As Long) As Long
372 rangeCheck(start)
373 Return indexOfCore(c, start, m_Length - start)
[246]374 End Function
[1]375
[272]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)
[246]379 End Function
[272]380 Private
381 Const Function indexOfCore(c As StrChar, start As Long, count As Long) As Long
[370]382 indexOfCore = ActiveBasic.Strings.ChrFind(VarPtr(Chars[start]), count, c) As Long
[272]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
[1]391
[272]392 Const Function IndexOf(s As String, startIndex As Long) As Long
393 Return IndexOf(s, startIndex, m_Length - startIndex)
394 End Function
[1]395
[272]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
[388]399 Throw New ArgumentNullException("String.IndexOf: An argument is out of range value.", "s")
[272]400 End If
[1]401
[272]402 Dim length = s.Length
[246]403 If length = 0 Then Return startIndex
[1]404
[246]405 Dim i As Long, j As Long
406 For i = startIndex To startIndex + count - 1
407 For j = 0 To length - 1
[272]408 If Chars[i + j] = s[j] Then
[246]409 If j = length - 1 Then Return i
410 Else
411 Exit For
412 End If
413 Next
[1]414 Next
[246]415 Return -1
416 End Function
[1]417
[388]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
[272]448 Const Function LastIndexOf(s As String) As Long
449 Return LastIndexOf(s, m_Length - 1, m_Length)
[246]450 End Function
[1]451
[272]452 Const Function LastIndexOf(s As String, startIndex As Long) As Long
453 Return LastIndexOf(s, startIndex, startIndex + 1)
[246]454 End Function
[1]455
[388]456 Const Function LastIndexOf(s As String, start As Long, count As Long) As Long
[272]457 If Object.ReferenceEquals(s, Nothing) Then
[388]458 Throw New ArgumentNullException("String.LastIndexOf: An argument is out of range value.", "s")
[272]459 End If
[1]460
[388]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")
[272]464 End If
[388]465 Dim length = s.m_Length
[246]466 If length > m_Length Then Return -1
[388]467 If length = 0 Then Return start
[1]468
[246]469 Dim i As Long, j As Long
[388]470 For i = start To start - count + 1 Step -1
[246]471 For j = length - 1 To 0 Step -1
[272]472 If Chars[i + j] = s[j] Then
[246]473 If j = 0 Then Return i
474 Else
475 Exit For
476 End If
477 Next
[1]478 Next
[246]479 Return -1
480 End Function
[1]481
[272]482 Const Function StartsWith(s As String) As Boolean
483 Return IndexOf(s) = 0
[246]484 End Function
[1]485
[272]486 Const Function EndsWith(s As String) As Boolean
487 Return LastIndexOf(s) = m_Length - s.Length
[246]488 End Function
[1]489
[246]490 Const Function Insert(startIndex As Long, text As String) As String
[388]491 Dim sb = New Text.StringBuilder(This)
[272]492 sb.Insert(startIndex, text)
493 Return sb.ToString
[246]494 End Function
[1]495
[272]496 Const Function Substring(startIndex As Long) As String
497 rangeCheck(startIndex)
498 Return Substring(startIndex, m_Length - startIndex)
[246]499 End Function
[1]500
[272]501 Const Function Substring(startIndex As Long, length As Long) As String
502 rangeCheck(startIndex, length)
503 Return New String(Chars, startIndex, length)
[246]504 End Function
[1]505
[246]506 Const Function Remove(startIndex As Long) As String
[272]507 rangeCheck(startIndex)
508 Remove = Substring(0, startIndex)
[246]509 End Function
[1]510
[246]511 Const Function Remove(startIndex As Long, count As Long) As String
[388]512 Dim sb = New Text.StringBuilder(This)
[272]513 sb.Remove(startIndex, count)
514 Remove = sb.ToString
[246]515 End Function
[192]516
[246]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
[132]522 End If
[246]523 Return True
524 End Function
[192]525
[246]526 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
[388]527 Dim sb = New Text.StringBuilder(This)
[272]528 sb.Replace(oldChar, newChar)
529 Replace = sb.ToString
[246]530 End Function
[1]531
[272]532 Const Function Replace(oldStr As String, newStr As String) As String
[388]533 Dim sb = New Text.StringBuilder(This)
[272]534 sb.Replace(oldStr, newStr)
535 Return sb.ToString
[246]536 End Function
[1]537
[246]538 Const Function ToLower() 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.ToLower(Chars[i])
[246]544 Next
[272]545 Return sb.ToString
[246]546 End Function
[1]547
[246]548 Const Function ToUpper() As String
[388]549 Dim sb = New Text.StringBuilder(m_Length)
[272]550 sb.Length = m_Length
[246]551 Dim i As Long
552 For i = 0 To ELM(m_Length)
[388]553 sb[i] = ActiveBasic.CType.ToUpper(Chars[i])
[246]554 Next
[272]555 Return sb.ToString
[246]556 End Function
[272]557
[246]558 Override Function ToString() As String
[272]559 ToString = This
[246]560 End Function
[119]561
[272]562 Const Function Clone() As String
563 Clone = This
564 End Function
[285]565
[246]566 Static Function Copy(s As String) As String
[272]567 Copy = New String(s.Chars, s.m_Length)
[246]568 End Function
[132]569
[272]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
[246]574 Override Function GetHashCode() As Long
[143]575#ifdef __STRING_IS_NOT_UNICODE
[246]576 Dim size = (m_Length + 1) >> 1
[143]577#else
[246]578 Dim size = m_Length
[143]579#endif
[388]580 Return _System_GetHashFromWordArray(Chars As *Word, size) Xor m_Length
[246]581 End Function
[272]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
[388]589 Throw New ArgumentOutOfRangeException("String.PadLeft: An arguments is out of range value.", "total")
[272]590 End If
591 If total >= m_Length Then
592 Return This
593 End If
[388]594 Dim sb = New Text.StringBuilder(total)
[272]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
[285]601 PadRight(total, &h30 As StrChar)
[272]602 End Function
603
604 Function PadRight(total As Long, c As StrChar) As String
605 If total < 0 Then
[388]606 Throw New ArgumentOutOfRangeException("String.PadRight: An arguments is out of range value.", "total")
[272]607 End If
608 If total >= m_Length Then
609 Return This
610 End If
[388]611 Dim sb = New Text.StringBuilder(total)
[272]612 sb.Append(This)
613 sb.Append(c, total - m_Length)
614 Return sb.ToString
615 End Function
[246]616 Private
617 Function AllocStringBuffer(textLength As Long) As *StrChar
618 If textLength < 0 Then
619 Return 0
[1]620 End If
[272]621 AllocStringBuffer = GC_malloc_atomic(SizeOf(StrChar) * (textLength + 1))
622 If AllocStringBuffer = 0 Then
623 'Throw New OutOfMemoryException
[246]624 End If
[272]625 m_Length = textLength
626 Chars = AllocStringBuffer
[246]627 End Function
[132]628
[246]629 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
[272]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
[388]637 Throw New ArgumentOutOfRangeException("String: An arguments is out of range value.", "index")
[246]638 End If
639 End Sub
[383]640
[272]641 Const Sub rangeCheck(start As Long, length As Long)
642 If start < 0 Or start > This.m_Length Or length < 0 Then
[388]643 Throw New ArgumentOutOfRangeException("String: One or more arguments are out of range value.", "start or length or both")
[272]644 End If
645 End Sub
[246]646 End Class
647
648End Namespace
Note: See TracBrowser for help on using the repository browser.