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

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

Stringのデフォルトコンストラクタでもメモリ確保するように戻す、api_imm.sbpの修正

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