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

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

GetHashCodeを実装

File size: 16.3 KB
Line 
1' Classes/System/String.ab
2
3#require <basic/function.sbp>
4
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#ifndef UNICODE
13#define __STRING_UNICODE_WINDOWS_ANSI
14#endif
15#endif
16
17Class String
18 m_Length As Long
19Public
20 Chars As *StrChar
21
22 Sub String()
23 Chars = 0
24 m_Length = 0
25 End Sub
26
27 Sub String(initStr As *Byte)
28 String()
29 Assign(initStr As PCTSTR)
30 End Sub
31
32 Sub String(initStr As PCSTR)
33 String()
34 Assign(initStr)
35 End Sub
36
37 Sub String(initStr As PCSTR, length As Long)
38 String()
39 Assign(initStr, length)
40 End Sub
41
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
52 Sub String(ByRef initStr As String)
53 String()
54 Assign(initStr)
55 End Sub
56
57 Sub String(length As Long)
58 String()
59 ReSize(length)
60 End Sub
61
62 Sub String(initChar As StrChar, length As Long)
63 ReSize(length, initChar)
64 End Sub
65
66 Sub ~String()
67 _System_free(Chars)
68 Chars = 0
69#ifdef _DEBUG
70 m_Length = 0
71#endif
72 End Sub
73
74 Const Function Length() As Long
75 Return m_Length
76 End Function
77
78 Function Operator() As *StrChar
79 Return Chars
80 End Function
81
82 Sub Operator = (ByRef objString As String)
83 Assign(objString.Chars, objString.m_Length)
84 End Sub
85
86 Sub Operator = (text As *Byte)
87 Assign(text As PCTSTR)
88 End Sub
89
90 Sub Operator = (text As PCSTR)
91 Assign(text)
92 End Sub
93
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
105 Return Chars[n]
106 End Function
107
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
115 Chars[n] = c
116 End Sub
117
118 Const Function Operator + (text As *Byte) As String
119 Return Concat(text As PCTSTR, lstrlen(text))
120 End Function
121
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
130 Const Function Operator + (ByRef objString As String) As String
131 Return Concat(objString.Chars, objString.m_Length)
132 End Function
133
134 Const Function Operator & (text As PCSTR) As String
135 Dim tempString = This + text
136 Return tempString
137 End Function
138
139 Const Function Operator & (text As PCWSTR) As String
140 Dim tempString = This + text
141 Return tempString
142 End Function
143
144 Const Function Operator & (ByRef objString As String) As String
145 Dim tempString = This + objString
146 Return tempString
147 End Function
148
149 Const Function Operator == (ByRef objString As String) As Boolean
150 Return _System_StrCmp(This, objString) = 0
151 End Function
152
153 Const Function Operator == (text As *StrChar) As Long
154 Return _System_StrCmp(This, text) = 0
155 End Function
156
157 Const Function Operator <> (ByRef objString As String) As Boolean
158 Return _System_StrCmp(This, objString) <> 0
159 End Function
160
161 Const Function Operator <> (text As *StrChar) As Boolean
162 Return _System_StrCmp(This, text) <> 0
163 End Function
164
165 Const Function Operator < (ByRef objString As String) As Boolean
166 Return _System_StrCmp(This, objString) < 0
167 End Function
168
169 Const Function Operator < (text As *StrChar) As Boolean
170 Return _System_StrCmp(This, text) < 0
171 End Function
172
173 Const Function Operator > (ByRef objString As String) As Boolean
174 Return _System_StrCmp(This, objString) > 0
175 End Function
176
177 Const Function Operator > (text As *StrChar) As Boolean
178 Return _System_StrCmp(This, text) > 0
179 End Function
180
181 Const Function Operator <= (ByRef objString As String) As Boolean
182 Return _System_StrCmp(This, objString) <= 0
183 End Function
184
185 Const Function Operator <= (text As *StrChar) As Boolean
186 Return _System_StrCmp(This, text) <= 0
187 End Function
188
189 Const Function Operator >= (ByRef objString As String) As Boolean
190 Return _System_StrCmp(This, objString) >= 0
191 End Function
192
193 Const Function Operator >= (text As *StrChar) As Boolean
194 Return _System_StrCmp(This, text) >= 0
195 End Function
196
197 Const Function StrPtr() As *StrChar
198 Return Chars
199 End Function
200
201 Sub ReSize(allocLength As Long)
202 If allocLength < 0 Then Exit Sub
203 If allocLength > m_Length Then
204 Dim oldLength As Long
205 oldLength = m_Length
206 If AllocStringBuffer(allocLength) <> 0 Then
207 ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (StrChar) * (m_Length - oldLength + 1))
208 End If
209 Else
210 m_Length = allocLength
211 Chars[m_Length] = 0
212 End If
213 End Sub
214
215 Sub ReSize(allocLength As Long, c As StrChar)
216 If allocLength < 0 Then
217 Exit Sub
218 ElseIf allocLength > m_Length Then
219 Dim oldLength As Long
220 oldLength = m_Length
221 If AllocStringBuffer(allocLength) <> 0 Then
222 Dim p = VarPtr(Chars[oldLength]) As *StrChar
223 Dim fillLen = m_Length - oldLength
224 Dim i As Long
225 For i = 0 To ELM(fillLen)
226 p[i] = c
227 Next
228 End If
229 Else
230 m_Length = allocLength
231 End If
232 Chars[m_Length] = 0
233 End Sub
234
235 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
236 If text = Chars Then Exit Sub
237 If AllocStringBuffer(textLength) <> 0 Then
238 memcpy(Chars, text, SizeOf (StrChar) * textLength)
239 Chars[m_Length] = 0
240 End If
241 End Sub
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
264
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
273 Sub Assign(ByRef objString As String)
274 Assign(objString.Chars, objString.m_Length)
275 End Sub
276
277 Sub Assign(text As PCSTR)
278 If text Then
279 Assign(text, lstrlenA(text))
280 Else
281 If Chars <> 0 Then
282 Chars[0] = 0
283 End If
284 m_Length = 0
285 End If
286 End Sub
287
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)
300 Dim prevLen As Long
301 prevLen = m_Length
302 If AllocStringBuffer(m_Length + textLength) <> 0 Then
303 memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
304 Chars[m_Length] = 0
305 End If
306 End Sub
307
308 Sub Append(text As *StrChar)
309 Append(text, lstrlen(text))
310 End Sub
311
312 Sub Append(ByRef str As String)
313 Append(str.Chars, str.m_Length)
314 End Sub
315
316 Const Function Clone() As String
317 Return This
318 End Function
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
342
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
351 End With
352#else
353 Return ConcatStrChar(This.Chars, m_Length, text, len)
354#endif
355 End Function
356 Const Function Contains(ByRef objString As String) As Boolean
357 Return IndexOf(objString, 0, m_Length) >= 0
358 End Function
359
360 Const Function Contains(lpszText As *StrChar) As Boolean
361 Return IndexOf(lpszText, 0, m_Length) >= 0
362 End Function
363
364 Const Function IndexOf(lpszText As *StrChar) As Long
365 Return IndexOf(lpszText, 0, m_Length)
366 End Function
367
368 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
369 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
370 End Function
371
372 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
373 Dim length = lstrlen(lpszText)
374
375 If startIndex < 0 Then Return -1
376 If count < 1 Or count + startIndex > m_Length Then Return -1
377 If length > m_Length Then Return -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
384 If Chars[i + j] = lpszText[j] Then
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
394 Const Function LastIndexOf(lpszText As *StrChar) As Long
395 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
396 End Function
397
398 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
399 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
400 End Function
401
402 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
403 Dim length = lstrlen(lpszText)
404
405 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
406 If count < 1 Or count > startIndex + 2 Then Return -1
407 If length > m_Length Then Return -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
414 If Chars[i + j] = lpszText[j] Then
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
424 Const Function StartsWith(lpszText As *StrChar) As Boolean
425 Return IndexOf(lpszText) = 0
426 End Function
427
428 Const Function EndsWith(lpszText As *StrChar) As Boolean
429 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
430 End Function
431
432 Const Function Insert(startIndex As Long, text As String) As String
433 Return Insert(startIndex, text.Chars, text.Length)
434 End Function
435
436 Const Function Insert(startIndex As Long, text As *StrChar) As String
437 Return Insert(startIndex, text, lstrlen(text))
438 End Function
439
440 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
441 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
442 Debug 'ArgumentOutOfRangeException
443
444 End If
445 Insert.ReSize(m_Length + length)
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))
449 End Function
450
451 Const Function SubString(startIndex As Long) As String
452 Return SubString(startIndex, m_Length - startIndex)
453 End Function
454
455 Const Function SubString(startIndex As Long, length As Long) As String
456 If startIndex < 0 Or length <= 0 Then Return ""
457 If startIndex + length > m_Length Then Return ""
458
459 Dim temp As String
460 temp.AllocStringBuffer(length)
461 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
462 Chars[m_Length] = 0
463 Return temp
464 End Function
465
466 Const Function Remove(startIndex As Long) As String
467 If startIndex < 0 Or startIndex > m_Length Then
468 Debug 'ArgumentOutOfRangeException
469 End If
470
471 Remove.ReSize(startIndex)
472 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
473 End Function
474
475 Const Function Remove(startIndex As Long, count As Long) As String
476 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
477 Debug 'ArgumentOutOfRangeException
478 End If
479
480 Remove.ReSize(m_Length - count)
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))
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*/
494 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
495 Replace = Copy(This)
496 With Replace
497 Dim i As Long
498 For i = 0 To ELM(.m_Length)
499 If .Chars[i] = oldChar Then
500 .Chars[i] = newChar
501 End If
502 Next
503 End With
504 End Function
505
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
515
516 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
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
520 End Function
521
522 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
523 If oldStr = 0 Then Debug 'Throw ArgumentNullException
524 If newStr = 0 Then
525 newStr = ""
526 newLen = 0
527 End If
528 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
529 End Function
530
531 Const Function ToLower() As String
532 ToLower.ReSize(m_Length)
533 Dim i As Long
534 For i = 0 To ELM(m_Length)
535 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
536 Next
537 End Function
538
539 Const Function ToUpper() As String
540 ToUpper.ReSize(m_Length)
541 Dim i As Long
542 For i = 0 To ELM(m_Length)
543 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
544 Next
545 End Function
546
547 Sub Swap(ByRef x As String)
548 Dim tempLen As Long
549 Dim tempChars As *StrChar
550 tempLen = x.m_Length
551 tempChars = x.Chars
552 x.m_Length = This.m_Length
553 x.Chars = This.Chars
554 This.m_Length = tempLen
555 This.Chars = tempChars
556 End Sub
557
558 Override Function ToString() As String
559 Return This
560 End Function
561
562 Static Function Copy(s As String) As String
563 Copy.ReSize(s.m_Length)
564 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
565 End Function
566
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
581Private
582 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
583 Function AllocStringBuffer(textLength As Long) As *StrChar
584 If textLength < 0 Then
585 Return 0
586 ElseIf textLength > m_Length Then
587 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
588 If AllocStringBuffer <> 0 Then
589 m_Length = textLength
590 Chars = AllocStringBuffer
591 End If
592 Else
593 m_Length = textLength
594 AllocStringBuffer = Chars
595 End If
596 End Function
597
598 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
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
619End Class
Note: See TracBrowser for help on using the repository browser.