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

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

コミット漏れ

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