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

Last change on this file since 182 was 182, checked in by dai, 17 years ago

_System_StrCmpのオーバーロードが解決できないバグを修正。

File size: 16.1 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.Chars, objString.Chars) = 0
151 End Function
152
153 Const Function Operator == (text As *StrChar) As Long
154 Return _System_StrCmp(This.Chars, text) = 0
155 End Function
156
157 Const Function Operator <> (ByRef objString As String) As Boolean
158 Return _System_StrCmp(This.Chars, objString.Chars) <> 0
159 End Function
160
161 Const Function Operator <> (text As *StrChar) As Boolean
162 Return _System_StrCmp(This.Chars, text) <> 0
163 End Function
164
165 Const Function Operator < (ByRef objString As String) As Boolean
166 Return _System_StrCmp(This.Chars, objString.Chars) < 0
167 End Function
168
169 Const Function Operator < (text As *StrChar) As Boolean
170 Return _System_StrCmp(This.Chars, text) < 0
171 End Function
172
173 Const Function Operator > (ByRef objString As String) As Boolean
174 Return _System_StrCmp(This.Chars, objString.Chars) > 0
175 End Function
176
177 Const Function Operator > (text As *StrChar) As Boolean
178 Return _System_StrCmp(This.Chars, text) > 0
179 End Function
180
181 Const Function Operator <= (ByRef objString As String) As Boolean
182 Return _System_StrCmp(This.Chars, objString.Chars) <= 0
183 End Function
184
185 Const Function Operator <= (text As *StrChar) As Boolean
186 Return _System_StrCmp(This.Chars, text) <= 0
187 End Function
188
189 Const Function Operator >= (ByRef objString As String) As Boolean
190 Return _System_StrCmp(This.Chars, objString.Chars) >= 0
191 End Function
192
193 Const Function Operator >= (text As *StrChar) As Boolean
194 Return _System_StrCmp(This.Chars, 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 Assign(text As PCSTR, textLengthA As Long)
236#ifdef __STRING_IS_NOT_UNICODE
237 AssignFromStrChar(text, textLengthA)
238#else
239 Dim textLengthW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, 0, 0)
240 If AllocStringBuffer(textLengthW) <> 0 Then
241 MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, Chars, textLengthW)
242 End If
243#endif
244 End Sub
245
246 Sub Assign(text As PCWSTR, textLengthW As Long)
247#ifdef __STRING_IS_NOT_UNICODE
248 Dim textLengthA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, 0, 0, 0, 0)
249 If AllocStringBuffer(textLengthA) <> 0 Then
250 WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, Chars, textLengthA, 0, 0)
251 End If
252#else
253 AssignFromStrChar(text, textLengthW)
254#endif
255 End Sub
256
257 Sub Assign(ByRef objString As String)
258 Assign(objString.Chars, objString.m_Length)
259 End Sub
260
261 Sub Assign(text As PCSTR)
262 If text Then
263 Assign(text, lstrlenA(text))
264 Else
265 If Chars <> 0 Then
266 Chars[0] = 0
267 End If
268 m_Length = 0
269 End If
270 End Sub
271
272 Sub Assign(text As PCWSTR)
273 If text Then
274 Assign(text, lstrlenW(text))
275 Else
276 If Chars <> 0 Then
277 Chars[0] = 0
278 End If
279 m_Length = 0
280 End If
281 End Sub
282
283 Sub Append(text As *StrChar, textLength As Long)
284 Dim prevLen As Long
285 prevLen = m_Length
286 If AllocStringBuffer(m_Length + textLength) <> 0 Then
287 memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
288 Chars[m_Length] = 0
289 End If
290 End Sub
291
292 Sub Append(text As *StrChar)
293 Append(text, lstrlen(text))
294 End Sub
295
296 Sub Append(ByRef str As String)
297 Append(str.Chars, str.m_Length)
298 End Sub
299
300 Const Function Clone() As String
301 Return This
302 End Function
303Private
304 Static Const Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
305 With ConcatStrChar
306 .AllocStringBuffer(text1Length + text2Length)
307 memcpy(.Chars, text1, SizeOf (StrChar) * text1Length)
308 memcpy(VarPtr(.Chars[text1Length]), text2, SizeOf (StrChar) * text2Length)
309 .Chars[text1Length + text2Length] = 0
310 End With
311 End Function
312Public
313 Const Function Concat(text As PCSTR, len As Long) As String
314#ifdef __STRING_IS_NOT_UNICODE
315 Return ConcatStrChar(This.Chars, m_Length, text, len)
316#else
317 With Concat
318 Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
319 .AllocStringBuffer(m_Length + lenW)
320 memcpy(.Chars, This.Chars, m_Length)
321 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
322 .Chars[m_Length + lenW] = 0
323 End With
324#endif
325 End Function
326
327 Const Function Concat(text As PCWSTR, len As Long) As String
328#ifdef __STRING_IS_NOT_UNICODE
329 With Concat
330 Dim lenA = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
331 .AllocStringBuffer(m_Length + lenA)
332 memcpy(.Chars, This.Chars, m_Length)
333 MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
334 .Chars[m_Length + lenA] = 0
335 End With
336#else
337 Return ConcatStrChar(This.Chars, m_Length, text, len)
338#endif
339 End Function
340 Const Function Contains(ByRef objString As String) As Boolean
341 Return IndexOf(objString, 0, m_Length) >= 0
342 End Function
343
344 Const Function Contains(lpszText As *StrChar) As Boolean
345 Return IndexOf(lpszText, 0, m_Length) >= 0
346 End Function
347
348 Const Function IndexOf(lpszText As *StrChar) As Long
349 Return IndexOf(lpszText, 0, m_Length)
350 End Function
351
352 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
353 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
354 End Function
355
356 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
357 Dim length = lstrlen(lpszText)
358
359 If startIndex < 0 Then Return -1
360 If count < 1 Or count + startIndex > m_Length Then Return -1
361 If length > m_Length Then Return -1
362
363 If length = 0 Then Return startIndex
364
365 Dim i As Long, j As Long
366 For i = startIndex To startIndex + count - 1
367 For j = 0 To length - 1
368 If Chars[i + j] = lpszText[j] Then
369 If j = length - 1 Then Return i
370 Else
371 Exit For
372 End If
373 Next
374 Next
375 Return -1
376 End Function
377
378 Const Function LastIndexOf(lpszText As *StrChar) As Long
379 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
380 End Function
381
382 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
383 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
384 End Function
385
386 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
387 Dim length = lstrlen(lpszText)
388
389 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
390 If count < 1 Or count > startIndex + 2 Then Return -1
391 If length > m_Length Then Return -1
392
393 If length = 0 Then Return startIndex
394
395 Dim i As Long, j As Long
396 For i = startIndex To startIndex - count + 1 Step -1
397 For j = length - 1 To 0 Step -1
398 If Chars[i + j] = lpszText[j] Then
399 If j = 0 Then Return i
400 Else
401 Exit For
402 End If
403 Next
404 Next
405 Return -1
406 End Function
407
408 Const Function StartsWith(lpszText As *StrChar) As Boolean
409 Return IndexOf(lpszText) = 0
410 End Function
411
412 Const Function EndsWith(lpszText As *StrChar) As Boolean
413 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
414 End Function
415
416 Const Function Insert(startIndex As Long, text As String) As String
417 Return Insert(startIndex, text.Chars, text.Length)
418 End Function
419
420 Const Function Insert(startIndex As Long, text As *StrChar) As String
421 Return Insert(startIndex, text, lstrlen(text))
422 End Function
423
424 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
425 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
426 Debug 'ArgumentOutOfRangeException
427
428 End If
429 Insert.ReSize(m_Length + length)
430 memcpy(Insert.Chars, Chars, SizeOf (StrChar) * startIndex)
431 memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (StrChar) * length)
432 memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (StrChar) * (m_Length - startIndex + 1))
433 End Function
434
435 Const Function SubString(startIndex As Long) As String
436 Return SubString(startIndex, m_Length - startIndex)
437 End Function
438
439 Const Function SubString(startIndex As Long, length As Long) As String
440 If startIndex < 0 Or length <= 0 Then Return ""
441 If startIndex + length > m_Length Then Return ""
442
443 Dim temp As String
444 temp.AllocStringBuffer(length)
445 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
446 Chars[m_Length] = 0
447 Return temp
448 End Function
449
450 Const Function Remove(startIndex As Long) As String
451 If startIndex < 0 Or startIndex > m_Length Then
452 Debug 'ArgumentOutOfRangeException
453 End If
454
455 Remove.ReSize(startIndex)
456 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
457 End Function
458
459 Const Function Remove(startIndex As Long, count As Long) As String
460 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
461 Debug 'ArgumentOutOfRangeException
462 End If
463
464 Remove.ReSize(m_Length - count)
465 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
466 memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (StrChar) * (m_Length - startIndex - count))
467 End Function
468/*
469 Static Function IsNullOrEmpty(s As String) As Boolean
470 If s <> Nothing Then
471 If s.m_Length > 0 Then
472 Return True
473 End If
474 End If
475 Return False
476 End Function
477*/
478 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
479 Replace = Copy(This)
480 With Replace
481 Dim i As Long
482 For i = 0 To ELM(.m_Length)
483 If .Chars[i] = oldChar Then
484 .Chars[i] = newChar
485 End If
486 Next
487 End With
488 End Function
489
490 Const Function Replace(ByRef oldStr As String, ByRef newStr As String) As String
491' If oldStr = Nothing Then Throw ArgumentNullException
492'
493' If newStr = Nothing Then
494' Return ReplaceCore(oldStr, oldStr.m_Length, "", 0)
495' Else
496 Return ReplaceCore(oldStr, oldStr.m_Length, newStr, newStr.m_Length)
497' End If
498 End Function
499
500 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
501 If oldStr = 0 Then Debug 'Throw ArgumentNullException
502 If newStr = 0 Then newStr = ""
503 Return ReplaceCore(oldStr, lstrlen(oldStr), newStr, lstrlen(newStr)) As String
504 End Function
505
506 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
507 If oldStr = 0 Then Debug 'Throw ArgumentNullException
508 If newStr = 0 Then
509 newStr = ""
510 newLen = 0
511 End If
512 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
513 End Function
514
515 Const Function ToLower() As String
516 ToLower.ReSize(m_Length)
517 Dim i As Long
518 For i = 0 To ELM(m_Length)
519 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
520 Next
521 End Function
522
523 Const Function ToUpper() As String
524 ToUpper.ReSize(m_Length)
525 Dim i As Long
526 For i = 0 To ELM(m_Length)
527 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
528 Next
529 End Function
530
531 Sub Swap(ByRef x As String)
532 Dim tempLen As Long
533 Dim tempChars As *StrChar
534 tempLen = x.m_Length
535 tempChars = x.Chars
536 x.m_Length = This.m_Length
537 x.Chars = This.Chars
538 This.m_Length = tempLen
539 This.Chars = tempChars
540 End Sub
541
542 Override Function ToString() As String
543 Return This
544 End Function
545
546 Static Function Copy(s As String) As String
547 Copy.ReSize(s.m_Length)
548 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
549 End Function
550
551 Override Function GetHashCode() As Long
552#ifdef __STRING_IS_NOT_UNICODE
553 Dim size = (m_Length + 1) >> 1
554#else
555 Dim size = m_Length
556#endif
557 Return _System_GetHashFromWordArray(Chars As *Word, size)
558 End Function
559Private
560 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
561 Function AllocStringBuffer(textLength As Long) As *StrChar
562 If textLength < 0 Then
563 Return 0
564 ElseIf textLength > m_Length Then
565 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
566 If AllocStringBuffer <> 0 Then
567 m_Length = textLength
568 Chars = AllocStringBuffer
569 End If
570 Else
571 m_Length = textLength
572 AllocStringBuffer = Chars
573 End If
574 End Function
575
576 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
577 If oldLen = 0 Then
578 Debug 'Throw ArgumentException
579 End If
580 Dim tmp As String
581 With tmp
582 Dim current = 0 As Long
583 Do
584 Dim pos = IndexOf(oldStr, current)
585 If pos = -1 Then
586 Exit Do
587 End If
588 .Append(VarPtr(Chars[current]), pos - current)
589 .Append(newStr, newLen)
590 current = pos + oldLen
591 Loop
592 .Append(VarPtr(Chars[current]), m_Length - current)
593 End With
594 Return tmp
595 End Function
596
597 Sub AssignFromStrChar(text As *StrChar, textLength As Long)
598 If text = Chars Then Exit Sub
599 If AllocStringBuffer(textLength) <> 0 Then
600 memcpy(Chars, text, SizeOf (StrChar) * textLength)
601 Chars[m_Length] = 0
602 End If
603 End Sub
604End Class
Note: See TracBrowser for help on using the repository browser.