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

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

コミット漏れ

File size: 16.7 KB
RevLine 
[132]1' Classes/System/String.ab
2
3#require <basic/function.sbp>
4
[139]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#endif
13
[1]14Class String
[30]15 m_Length As Long
[1]16Public
[139]17 Chars As *StrChar
[1]18
19 Sub String()
[139]20 Chars = 0
[30]21 m_Length = 0
[1]22 End Sub
23
[139]24 Sub String(initStr As *Byte)
[1]25 String()
[139]26 Assign(initStr As PCTSTR)
27 End Sub
28
29 Sub String(initStr As PCSTR)
30 String()
[1]31 Assign(initStr)
32 End Sub
[30]33
[139]34 Sub String(initStr As PCSTR, length As Long)
[125]35 String()
36 Assign(initStr, length)
37 End Sub
38
[139]39 Sub String(initStr As PCWSTR)
40 String()
41 Assign(initStr)
42 End Sub
43
44 Sub String(initStr As PCWSTR, length As Long)
45 String()
46 Assign(initStr, length)
47 End Sub
48
[49]49 Sub String(ByRef initStr As String)
[1]50 String()
51 Assign(initStr)
52 End Sub
[49]53
[1]54 Sub String(length As Long)
[121]55 String()
[1]56 ReSize(length)
57 End Sub
[121]58
[139]59 Sub String(initChar As StrChar, length As Long)
[1]60 ReSize(length, initChar)
61 End Sub
62
63 Sub ~String()
[123]64 _System_free(Chars)
[31]65 Chars = 0
[1]66#ifdef _DEBUG
[30]67 m_Length = 0
[1]68#endif
69 End Sub
70
[121]71 Const Function Length() As Long
[30]72 Return m_Length
73 End Function
74
[139]75 Function Operator() As *StrChar
[31]76 Return Chars
[1]77 End Function
78
79 Sub Operator = (ByRef objString As String)
[31]80 Assign(objString.Chars, objString.m_Length)
[1]81 End Sub
82
[139]83 Sub Operator = (text As *Byte)
84 Assign(text As PCTSTR)
85 End Sub
86
87 Sub Operator = (text As PCSTR)
[1]88 Assign(text)
89 End Sub
90
[139]91 Sub Operator = (text As PCWSTR)
92 Assign(text)
93 End Sub
94
95 Const Function Operator [] (n As Long) As StrChar
96#ifdef _DEBUG
97 If n > Length Then
98 'Throw ArgumentOutOfRangeException
99 Debug
100 End If
101#endif
[31]102 Return Chars[n]
[1]103 End Function
104
[139]105 Sub Operator []= (n As Long, c As StrChar)
106#ifdef _DEBUG
107 If n >= Length Then
108 'Throw ArgumentOutOfRangeException
109 Debug
110 End If
111#endif
[31]112 Chars[n] = c
[1]113 End Sub
114
[139]115 Const Function Operator + (text As *Byte) As String
116 Return Concat(text As PCTSTR, lstrlen(text))
[1]117 End Function
118
[139]119 Const Function Operator + (text As PCSTR) As String
120 Return Concat(text, lstrlenA(text))
121 End Function
122
123 Const Function Operator + (text As PCWSTR) As String
124 Return Concat(text, lstrlenW(text))
125 End Function
126
[121]127 Const Function Operator + (ByRef objString As String) As String
[139]128 Return Concat(objString.Chars, objString.m_Length)
[1]129 End Function
130
[139]131 Const Function Operator & (text As PCSTR) As String
132 Dim tempString = This + text
[1]133 Return tempString
134 End Function
135
[139]136 Const Function Operator & (text As PCWSTR) As String
137 Dim tempString = This + text
138 Return tempString
139 End Function
140
[121]141 Const Function Operator & (ByRef objString As String) As String
142 Dim tempString = This + objString
[1]143 Return tempString
144 End Function
145
[132]146 Const Function Operator == (ByRef objString As String) As Boolean
147 Return _System_StrCmp(This, objString) = 0
[1]148 End Function
149
[139]150 Const Function Operator == (text As *StrChar) As Long
[132]151 Return _System_StrCmp(This, text) = 0
[1]152 End Function
153
[132]154 Const Function Operator <> (ByRef objString As String) As Boolean
[139]155 Return _System_StrCmp(This, objString) <> 0
[1]156 End Function
157
[139]158 Const Function Operator <> (text As *StrChar) As Boolean
159 Return _System_StrCmp(This, text) <> 0
[1]160 End Function
161
[132]162 Const Function Operator < (ByRef objString As String) As Boolean
163 Return _System_StrCmp(This, objString) < 0
[1]164 End Function
165
[139]166 Const Function Operator < (text As *StrChar) As Boolean
[132]167 Return _System_StrCmp(This, text) < 0
[1]168 End Function
169
[132]170 Const Function Operator > (ByRef objString As String) As Boolean
171 Return _System_StrCmp(This, objString) > 0
[1]172 End Function
173
[139]174 Const Function Operator > (text As *StrChar) As Boolean
[132]175 Return _System_StrCmp(This, text) > 0
[1]176 End Function
177
[132]178 Const Function Operator <= (ByRef objString As String) As Boolean
179 Return _System_StrCmp(This, objString) <= 0
[1]180 End Function
181
[139]182 Const Function Operator <= (text As *StrChar) As Boolean
[132]183 Return _System_StrCmp(This, text) <= 0
[1]184 End Function
185
[132]186 Const Function Operator >= (ByRef objString As String) As Boolean
[139]187 Return _System_StrCmp(This, objString) >= 0
[1]188 End Function
189
[139]190 Const Function Operator >= (text As *StrChar) As Boolean
191 Return _System_StrCmp(This, text) >= 0
[1]192 End Function
193
[139]194 Const Function StrPtr() As *StrChar
[31]195 Return Chars
[1]196 End Function
197
198 Sub ReSize(allocLength As Long)
199 If allocLength < 0 Then Exit Sub
[30]200 If allocLength > m_Length Then
[1]201 Dim oldLength As Long
[30]202 oldLength = m_Length
[1]203 If AllocStringBuffer(allocLength) <> 0 Then
[139]204 ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (StrChar) * (m_Length - oldLength + 1))
[1]205 End If
206 Else
[30]207 m_Length = allocLength
[31]208 Chars[m_Length] = 0
[1]209 End If
210 End Sub
211
[139]212 Sub ReSize(allocLength As Long, c As StrChar)
[1]213 If allocLength < 0 Then
214 Exit Sub
[30]215 ElseIf allocLength > m_Length Then
[1]216 Dim oldLength As Long
[30]217 oldLength = m_Length
[1]218 If AllocStringBuffer(allocLength) <> 0 Then
[139]219 Dim p = VarPtr(Chars[oldLength]) As *StrChar
[121]220 Dim fillLen = m_Length - oldLength
221 Dim i As Long
222 For i = 0 To ELM(fillLen)
223 p[i] = c
224 Next
[1]225 End If
226 Else
[30]227 m_Length = allocLength
[1]228 End If
[31]229 Chars[m_Length] = 0
[1]230 End Sub
231
[139]232 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
[121]233 If text = Chars Then Exit Sub
[1]234 If AllocStringBuffer(textLength) <> 0 Then
[139]235 memcpy(Chars, text, SizeOf (StrChar) * textLength)
[31]236 Chars[m_Length] = 0
[139]237 End If
[1]238 End Sub
[139]239#ifdef __STRCHAR_IS_NOT_UNICODE
240 Sub AssignFromWideChar(text As PCWSTR, textLengthW As Long)
241 Dim textLengthA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, 0, 0, 0, 0)
242 If AllocStringBuffer(textLengthA) <> 0 Then
243 WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, Chars, textLengthA, 0, 0)
244 End If
245 End Sub
246#else
247 Sub AssignFromMultiByte(text As PCSTR, textLengthA As Long)
248 Dim textLengthW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, 0, 0)
249 If AllocStringBuffer(textLengthW) <> 0 Then
250 MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, Chars, textLengthW)
251 End If
252 End Sub
253#endif
254 Sub Assign(text As PCSTR, textLength As Long)
255#ifdef __STRING_IS_NOT_UNICODE
256 AssignFromStrChar(text, textLength)
257#else
258 AssignFromMultiByte(text, textLength)
259#endif
260 End Sub
[1]261
[139]262 Sub Assign(text As PCWSTR, textLength As Long)
263#ifdef __STRING_IS_NOT_UNICODE
264 AssignFromWideChar(text, textLength)
265#else
266 AssignFromStrChar(text, textLength)
267#endif
268 End Sub
269
[1]270 Sub Assign(ByRef objString As String)
[31]271 Assign(objString.Chars, objString.m_Length)
[1]272 End Sub
273
[139]274 Sub Assign(text As PCSTR)
[121]275 If text Then
[139]276 Assign(text, lstrlenA(text))
[1]277 Else
[139]278 If Chars <> 0 Then
279 Chars[0] = 0
280 End If
[30]281 m_Length = 0
[1]282 End If
283 End Sub
284
[139]285 Sub Assign(text As PCWSTR)
286 If text Then
287 Assign(text, lstrlenW(text))
288 Else
289 If Chars <> 0 Then
290 Chars[0] = 0
291 End If
292 m_Length = 0
293 End If
294 End Sub
295
296 Sub Append(text As *StrChar, textLength As Long)
[1]297 Dim prevLen As Long
[30]298 prevLen = m_Length
299 If AllocStringBuffer(m_Length + textLength) <> 0 Then
[139]300 memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
[31]301 Chars[m_Length] = 0
[1]302 End If
303 End Sub
304
[139]305 Sub Append(text As *StrChar)
[1]306 Append(text, lstrlen(text))
307 End Sub
308
309 Sub Append(ByRef str As String)
[31]310 Append(str.Chars, str.m_Length)
[1]311 End Sub
312
[132]313 Const Function Clone() As String
314 Return This
315 End Function
[139]316Private
317 Static Const Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
318 With ConcatStrChar
319 .AllocStringBuffer(text1Length + text2Length)
320 memcpy(.Chars, text1, SizeOf (StrChar) * text1Length)
321 memcpy(VarPtr(.Chars[text1Length]), text2, SizeOf (StrChar) * text2Length)
322 .Chars[text1Length + text2Length] = 0
323 End With
324 End Function
325Public
326 Const Function Concat(text As PCSTR, len As Long) As String
327#ifdef __STRING_IS_NOT_UNICODE
328 Return ConcatStrChar(This.Chars, m_Length, text, len)
329#else
330 With Concat
331 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
332 .AllocStringBuffer(m_Length + lenW)
333 memcpy(.Chars, This.Chars, m_Length)
334 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
335 .Chars[m_Length + lenW] = 0
336 End With
337#endif
338 End Function
[132]339
[139]340 Const Function Concat(text As PCWSTR, len As Long) As String
341#ifdef __STRING_IS_NOT_UNICODE
342 With Concat
343 Dim lenA = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
344 .AllocStringBuffer(m_Length + lenA)
345 memcpy(.Chars, This.Chars, m_Length)
346 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
347 .Chars[m_Length + lenA] = 0
[1]348 End With
[139]349#else
350 Return ConcatStrChar(This.Chars, m_Length, text, len)
351#endif
[1]352 End Function
[132]353 Const Function Contains(ByRef objString As String) As Boolean
354 Return IndexOf(objString, 0, m_Length) >= 0
[1]355 End Function
356
[139]357 Const Function Contains(lpszText As *StrChar) As Boolean
[132]358 Return IndexOf(lpszText, 0, m_Length) >= 0
[1]359 End Function
360
[139]361 Const Function IndexOf(lpszText As *StrChar) As Long
[30]362 Return IndexOf(lpszText, 0, m_Length)
[1]363 End Function
364
[139]365 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
[30]366 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
[1]367 End Function
368
[139]369 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
[132]370 Dim length = lstrlen(lpszText)
[1]371
372 If startIndex < 0 Then Return -1
[30]373 If count < 1 Or count + startIndex > m_Length Then Return -1
374 If length > m_Length Then Return -1
[1]375
376 If length = 0 Then Return startIndex
377
378 Dim i As Long, j As Long
379 For i = startIndex To startIndex + count - 1
380 For j = 0 To length - 1
[31]381 If Chars[i + j] = lpszText[j] Then
[1]382 If j = length - 1 Then Return i
383 Else
384 Exit For
385 End If
386 Next
387 Next
388 Return -1
389 End Function
390
[139]391 Const Function LastIndexOf(lpszText As *StrChar) As Long
[30]392 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
[1]393 End Function
394
[139]395 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
396 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
[1]397 End Function
398
[139]399 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
[132]400 Dim length = lstrlen(lpszText)
[1]401
[30]402 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
[1]403 If count < 1 Or count > startIndex + 2 Then Return -1
[30]404 If length > m_Length Then Return -1
[1]405
406 If length = 0 Then Return startIndex
407
408 Dim i As Long, j As Long
409 For i = startIndex To startIndex - count + 1 Step -1
410 For j = length - 1 To 0 Step -1
[31]411 If Chars[i + j] = lpszText[j] Then
[1]412 If j = 0 Then Return i
413 Else
414 Exit For
415 End If
416 Next
417 Next
418 Return -1
419 End Function
420
[139]421 Const Function StartsWith(lpszText As *StrChar) As Boolean
[132]422 Return IndexOf(lpszText) = 0
[1]423 End Function
424
[139]425 Const Function EndsWith(lpszText As *StrChar) As Boolean
[132]426 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
[1]427 End Function
428
[132]429 Const Function Insert(startIndex As Long, text As String) As String
430 Return Insert(startIndex, text.Chars, text.Length)
431 End Function
[1]432
[139]433 Const Function Insert(startIndex As Long, text As *StrChar) As String
[132]434 Return Insert(startIndex, text, lstrlen(text))
435 End Function
[1]436
[139]437 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
[132]438 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
439 Debug 'ArgumentOutOfRangeException
[1]440
[132]441 End If
442 Insert.ReSize(m_Length + length)
[139]443 memcpy(Insert.Chars, Chars, SizeOf (StrChar) * startIndex)
444 memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (StrChar) * length)
445 memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (StrChar) * (m_Length - startIndex + 1))
[1]446 End Function
447
[132]448 Const Function SubString(startIndex As Long) As String
[30]449 Return SubString(startIndex, m_Length - startIndex)
[1]450 End Function
451
[132]452 Const Function SubString(startIndex As Long, length As Long) As String
[1]453 If startIndex < 0 Or length <= 0 Then Return ""
[30]454 If startIndex + length > m_Length Then Return ""
[1]455
456 Dim temp As String
457 temp.AllocStringBuffer(length)
[139]458 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
[31]459 Chars[m_Length] = 0
[1]460 Return temp
461 End Function
462
[132]463 Const Function Remove(startIndex As Long) As String
[135]464 If startIndex < 0 Or startIndex > m_Length Then
465 Debug 'ArgumentOutOfRangeException
466 End If
467
[132]468 Remove.ReSize(startIndex)
[139]469 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
[1]470 End Function
471
[132]472 Const Function Remove(startIndex As Long, count As Long) As String
[135]473 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
474 Debug 'ArgumentOutOfRangeException
475 End If
476
[132]477 Remove.ReSize(m_Length - count)
[139]478 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
479 memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (StrChar) * (m_Length - startIndex - count))
[132]480 End Function
481/*
482 Static Function IsNullOrEmpty(s As String) As Boolean
483 If s <> Nothing Then
484 If s.m_Length > 0 Then
485 Return True
486 End If
487 End If
488 Return False
489 End Function
490*/
[139]491 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
[132]492 Replace = Copy(This)
493 With Replace
494 Dim i As Long
495 For i = 0 To ELM(.m_Length)
496 If .Chars[i] = .oldChar Then
497 .Chars[i] = .newChar
498 End If
499 Next
500 End With
501 End Function
[1]502
[132]503 Const Function Replace(ByRef oldStr As String, ByRef newStr As String) As String
504' If oldStr = Nothing Then Throw ArgumentNullException
505'
506' If newStr = Nothing Then
507' Return ReplaceCore(oldStr, oldStr.m_Length, "", 0)
508' Else
509 Return ReplaceCore(oldStr, oldStr.m_Length, newStr, newStr.m_Length)
510' End If
511 End Function
[1]512
[139]513 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
[132]514 If oldStr = 0 Then Debug 'Throw ArgumentNullException
515 If newStr = 0 Then newStr = ""
516 Return ReplaceCore(oldStr, lstrlen(oldStr), newStr, lstrlen(newStr)) As String
[1]517 End Function
518
[139]519 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
[132]520 If oldStr = 0 Then Debug 'Throw ArgumentNullException
521 If newStr = 0 Then
522 newStr = ""
523 newLen = 0
[1]524 End If
[132]525 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
[1]526 End Function
527
[134]528 Const Function ToLower() As String
529 ToLower.ReSize(m_Length)
[125]530 Dim i As Long
[134]531 For i = 0 To ELM(m_Length)
532 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
[125]533 Next
[134]534 End Function
[1]535
[134]536 Const Function ToUpper() As String
537 ToUpper.ReSize(m_Length)
[125]538 Dim i As Long
[134]539 For i = 0 To ELM(m_Length)
540 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
[125]541 Next
[134]542 End Function
[1]543
544 Sub Swap(ByRef x As String)
545 Dim tempLen As Long
[139]546 Dim tempChars As *StrChar
[30]547 tempLen = x.m_Length
[31]548 tempChars = x.Chars
[30]549 x.m_Length = This.m_Length
[31]550 x.Chars = This.Chars
[30]551 This.m_Length = tempLen
[31]552 This.Chars = tempChars
[1]553 End Sub
554
[119]555 Override Function ToString() As String
556 Return This
557 End Function
558
[132]559 Static Function Copy(s As String) As String
560 Copy.Resize(s.m_Length)
[139]561 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
[132]562 End Function
563
[1]564Private
565 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
[139]566 Function AllocStringBuffer(textLength As Long) As *StrChar
[1]567 If textLength < 0 Then
568 Return 0
[30]569 ElseIf textLength > m_Length Then
[139]570 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
[1]571 If AllocStringBuffer <> 0 Then
[30]572 m_Length = textLength
[31]573 Chars = AllocStringBuffer
[1]574 End If
575 Else
[30]576 m_Length = textLength
[31]577 AllocStringBuffer = Chars
[1]578 End If
579 End Function
580
[139]581 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
[132]582 If oldLen = 0 Then
583 Debug 'Throw ArgumentException
584 End If
585 Dim tmp As String
586 With tmp
587 Dim current = 0 As Long
588 Do
589 Dim pos = IndexOf(oldStr, current)
590 If pos = -1 Then
591 Exit Do
592 End If
593 .Append(VarPtr(Chars[current]), pos - current)
594 .Append(newStr, newLen)
595 current = pos + oldLen
596 Loop
597 .Append(VarPtr(Chars[current]), m_Length - current)
598 End With
599 Return tmp
600 End Function
601
[1]602End Class
603
[139]604Function GetMultiByteStr(ByRef s As String) As PCSTR
605#ifdef __STRING_IS_NOT_UNICODE
606 GetMultiByteStr = s.Chars
607#else
608 Dim sizeA = WideCharToMultiByte(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, 0, 0, 0, 0)
609 GetMultiByteStr = GC_malloc_atomic(SizeOf (SByte) * sizeA)
610 WideCharToMultiByte(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, GetMultiByteStr, sizeA, 0, 0)
611#endif
612End Function
613
614Function GetWideCharStr(ByRef s As String) As PCSTR
615#ifdef __STRING_IS_NOT_UNICODE
616 Dim sizeW = MultiByteToWideChar(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, 0, 0)
617 GetWideCharStr = GC_malloc_atomic(SizeOf (WCHAR) * sizeW)
618 MultiByteToWideChar(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, GetWideCharStr, sizeW)
619#else
620 GetMultiByteStr = s.Chars
621#endif
622End Function
623
Note: See TracBrowser for help on using the repository browser.