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

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

GetHashCodeを実装

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