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
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 = _System_malloc(SizeOf (StrChar)) '0
24 Chars[0] = 0
25 m_Length = 0
26 End Sub
27
28/* Sub String(initStr As *Byte)
29 String()
30 Assign(initStr As PCTSTR)
31 End Sub*/
32
33 Sub String(initStr As PCSTR)
34 String()
35 Assign(initStr)
36 End Sub
37
38 Sub String(initStr As PCSTR, length As Long)
39 String()
40 Assign(initStr, length)
41 End Sub
42
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
53 Sub String(ByRef initStr As String)
54 String()
55 Assign(initStr)
56 End Sub
57
58 Sub String(length As Long)
59 String()
60 ReSize(length)
61 End Sub
62
63 Sub String(initChar As StrChar, length As Long)
64 ReSize(length, initChar)
65 End Sub
66
67 Sub ~String()
68 _System_free(Chars)
69 Chars = 0
70#ifdef _DEBUG
71 m_Length = 0
72#endif
73 End Sub
74
75 Const Function Length() As Long
76 Return m_Length
77 End Function
78
79 Function Operator() As *StrChar
80 Return Chars
81 End Function
82
83/* Sub Operator = (ByRef objString As String)
84 Assign(objString.Chars, objString.m_Length)
85 End Sub
86
87 Sub Operator = (text As *Byte)
88 Assign(text As PCTSTR)
89 End Sub
90
91 Sub Operator = (text As PCSTR)
92 Assign(text)
93 End Sub
94
95 Sub Operator = (text As PCWSTR)
96 Assign(text)
97 End Sub*/
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
106 Return Chars[n]
107 End Function
108
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
116 Chars[n] = c
117 End Sub
118
119/* Const Function Operator + (text As *Byte) As String
120 Return Concat(text As PCTSTR, lstrlen(text))
121 End Function*/
122
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
131 Const Function Operator + (ByRef objString As String) As String
132 Return Concat(objString.Chars, objString.m_Length)
133 End Function
134
135 Const Function Operator & (text As PCSTR) As String
136 Dim tempString = This + text
137 Return tempString
138 End Function
139
140 Const Function Operator & (text As PCWSTR) As String
141 Dim tempString = This + text
142 Return tempString
143 End Function
144
145 Const Function Operator & (ByRef objString As String) As String
146 Dim tempString = This + objString
147 Return tempString
148 End Function
149
150 Const Function Operator == (ByRef objString As String) As Boolean
151 Return _System_StrCmp(This.Chars, objString.Chars) = 0
152 End Function
153
154 Const Function Operator == (text As *StrChar) As Long
155 Return _System_StrCmp(This.Chars, text) = 0
156 End Function
157
158 Const Function Operator <> (ByRef objString As String) As Boolean
159 Return _System_StrCmp(This.Chars, objString.Chars) <> 0
160 End Function
161
162 Const Function Operator <> (text As *StrChar) As Boolean
163 Return _System_StrCmp(This.Chars, text) <> 0
164 End Function
165
166 Const Function Operator < (ByRef objString As String) As Boolean
167 Return _System_StrCmp(This.Chars, objString.Chars) < 0
168 End Function
169
170 Const Function Operator < (text As *StrChar) As Boolean
171 Return _System_StrCmp(This.Chars, text) < 0
172 End Function
173
174 Const Function Operator > (ByRef objString As String) As Boolean
175 Return _System_StrCmp(This.Chars, objString.Chars) > 0
176 End Function
177
178 Const Function Operator > (text As *StrChar) As Boolean
179 Return _System_StrCmp(This.Chars, text) > 0
180 End Function
181
182 Const Function Operator <= (ByRef objString As String) As Boolean
183 Return _System_StrCmp(This.Chars, objString.Chars) <= 0
184 End Function
185
186 Const Function Operator <= (text As *StrChar) As Boolean
187 Return _System_StrCmp(This.Chars, text) <= 0
188 End Function
189
190 Const Function Operator >= (ByRef objString As String) As Boolean
191 Return _System_StrCmp(This.Chars, objString.Chars) >= 0
192 End Function
193
194 Const Function Operator >= (text As *StrChar) As Boolean
195 Return _System_StrCmp(This.Chars, text) >= 0
196 End Function
197
198 Const Function StrPtr() As *StrChar
199 Return Chars
200 End Function
201
202 Sub ReSize(allocLength As Long)
203 If allocLength < 0 Then Exit Sub
204 If allocLength > m_Length Then
205 Dim oldLength As Long
206 oldLength = m_Length
207 If AllocStringBuffer(allocLength) <> 0 Then
208 ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (StrChar) * (m_Length - oldLength + 1))
209 End If
210 Else
211 m_Length = allocLength
212 Chars[m_Length] = 0
213 End If
214 End Sub
215
216 Sub ReSize(allocLength As Long, c As StrChar)
217 If allocLength < 0 Then
218 Exit Sub
219 ElseIf allocLength > m_Length Then
220 Dim oldLength As Long
221 oldLength = m_Length
222 If AllocStringBuffer(allocLength) <> 0 Then
223 Dim p = VarPtr(Chars[oldLength]) As *StrChar
224 Dim fillLen = m_Length - oldLength
225 Dim i As Long
226 For i = 0 To ELM(fillLen)
227 p[i] = c
228 Next
229 End If
230 Else
231 m_Length = allocLength
232 End If
233 Chars[m_Length] = 0
234 End Sub
235
236 Sub Assign(text As PCSTR, textLengthA As Long)
237#ifdef __STRING_IS_NOT_UNICODE
238 AssignFromStrChar(text, textLengthA)
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)
243 Chars[textLengthW] = 0
244 End If
245#endif
246 End Sub
247
248 Sub Assign(text As PCWSTR, textLengthW As Long)
249#ifdef __STRING_IS_NOT_UNICODE
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)
253 Chars[textLengthA] = 0
254 End If
255#else
256 AssignFromStrChar(text, textLengthW)
257#endif
258 End Sub
259
260 Sub Assign(ByRef objString As String)
261 Assign(objString.Chars, objString.m_Length)
262 End Sub
263
264 Sub Assign(text As PCSTR)
265 If text Then
266 Assign(text, lstrlenA(text))
267 Else
268 If Chars <> 0 Then
269 Chars[0] = 0
270 End If
271 m_Length = 0
272 End If
273 End Sub
274
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)
287 Dim prevLen As Long
288 prevLen = m_Length
289 If AllocStringBuffer(m_Length + textLength) <> 0 Then
290 memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
291 Chars[m_Length] = 0
292 End If
293 End Sub
294
295 Sub Append(text As *StrChar)
296 Append(text, lstrlen(text))
297 End Sub
298
299 Sub Append(ByRef str As String)
300 Append(str.Chars, str.m_Length)
301 End Sub
302
303 Const Function Clone() As String
304 Return This
305 End Function
306Private
307 Static Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
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
329
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
338 End With
339#else
340 Return ConcatStrChar(This.Chars, m_Length, text, len)
341#endif
342 End Function
343 Const Function Contains(ByRef objString As String) As Boolean
344 Return IndexOf(objString, 0, m_Length) >= 0
345 End Function
346
347 Const Function Contains(lpszText As *StrChar) As Boolean
348 Return IndexOf(lpszText, 0, m_Length) >= 0
349 End Function
350
351 Const Function IndexOf(lpszText As *StrChar) As Long
352 Return IndexOf(lpszText, 0, m_Length)
353 End Function
354
355 Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
356 Return IndexOf(lpszText, startIndex, m_Length - startIndex)
357 End Function
358
359 Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
360 Dim length = lstrlen(lpszText)
361
362 If startIndex < 0 Then Return -1
363 If count < 1 Or count + startIndex > m_Length Then Return -1
364 If length > m_Length Then Return -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
371 If Chars[i + j] = lpszText[j] Then
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
381 Const Function LastIndexOf(lpszText As *StrChar) As Long
382 Return LastIndexOf(lpszText, m_Length - 1, m_Length)
383 End Function
384
385 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
386 Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
387 End Function
388
389 Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
390 Dim length = lstrlen(lpszText)
391
392 If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1
393 If count < 1 Or count > startIndex + 2 Then Return -1
394 If length > m_Length Then Return -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
401 If Chars[i + j] = lpszText[j] Then
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
411 Const Function StartsWith(lpszText As *StrChar) As Boolean
412 Return IndexOf(lpszText) = 0
413 End Function
414
415 Const Function EndsWith(lpszText As *StrChar) As Boolean
416 Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
417 End Function
418
419 Const Function Insert(startIndex As Long, text As String) As String
420 Return Insert(startIndex, text.Chars, text.Length)
421 End Function
422
423 Const Function Insert(startIndex As Long, text As *StrChar) As String
424 Return Insert(startIndex, text, lstrlen(text))
425 End Function
426
427 Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
428 If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
429 Debug 'ArgumentOutOfRangeException
430
431 End If
432 Insert.ReSize(m_Length + length)
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))
436 End Function
437
438 Const Function SubString(startIndex As Long) As String
439 Return SubString(startIndex, m_Length - startIndex)
440 End Function
441
442 Const Function SubString(startIndex As Long, length As Long) As String
443 If startIndex < 0 Or length <= 0 Then Return ""
444 If startIndex + length > m_Length Then Return ""
445
446 Dim temp As String
447 temp.AllocStringBuffer(length)
448 memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
449 Chars[m_Length] = 0
450 Return temp
451 End Function
452
453 Const Function Remove(startIndex As Long) As String
454 If startIndex < 0 Or startIndex > m_Length Then
455 Debug 'ArgumentOutOfRangeException
456 End If
457
458 Remove.ReSize(startIndex)
459 memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
460 End Function
461
462 Const Function Remove(startIndex As Long, count As Long) As String
463 If startIndex < 0 Or count < 0 Or startIndex + count > m_Length Then
464 Debug 'ArgumentOutOfRangeException
465 End If
466
467 Remove.ReSize(m_Length - count)
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))
470 End Function
471
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
480
481 Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
482 Replace = Copy(This)
483 With Replace
484 Dim i As Long
485 For i = 0 To ELM(.m_Length)
486 If .Chars[i] = oldChar Then
487 .Chars[i] = newChar
488 End If
489 Next
490 End With
491 End Function
492
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
502
503 Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
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
507 End Function
508
509 Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
510 If oldStr = 0 Then Debug 'Throw ArgumentNullException
511 If newStr = 0 Then
512 newStr = ""
513 newLen = 0
514 End If
515 Return ReplaceCore(oldStr, oldLen, newStr, newLen)
516 End Function
517
518 Const Function ToLower() As String
519 ToLower.ReSize(m_Length)
520 Dim i As Long
521 For i = 0 To ELM(m_Length)
522 ToLower.Chars[i] = _System_ASCII_ToLower(Chars[i])
523 Next
524 End Function
525
526 Const Function ToUpper() As String
527 ToUpper.ReSize(m_Length)
528 Dim i As Long
529 For i = 0 To ELM(m_Length)
530 ToUpper.Chars[i] = _System_ASCII_ToUpper(Chars[i])
531 Next
532 End Function
533
534 Sub Swap(ByRef x As String)
535 Dim tempLen As Long
536 Dim tempChars As *StrChar
537 tempLen = x.m_Length
538 tempChars = x.Chars
539 x.m_Length = This.m_Length
540 x.Chars = This.Chars
541 This.m_Length = tempLen
542 This.Chars = tempChars
543 End Sub
544
545 Override Function ToString() As String
546 Return This
547 End Function
548
549 Static Function Copy(s As String) As String
550 Copy.ReSize(s.m_Length)
551 memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
552 End Function
553
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
560 Return _System_GetHashFromWordArray(Chars As *Word, size)
561 End Function
562Private
563 ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障)
564 Function AllocStringBuffer(textLength As Long) As *StrChar
565 If textLength < 0 Then
566 Return 0
567 ElseIf textLength > m_Length Then
568 AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
569 If AllocStringBuffer <> 0 Then
570 m_Length = textLength
571 Chars = AllocStringBuffer
572 End If
573 Else
574 m_Length = textLength
575 AllocStringBuffer = Chars
576 End If
577 End Function
578
579 Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
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
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
607End Class
Note: See TracBrowser for help on using the repository browser.