' Classes/System/String.ab #require Class String m_Length As Long Public Chars As *Char Sub String() Chars = _System_calloc(SizeOf (Char) * 1) m_Length = 0 End Sub Sub String(initStr As *Char) String() Assign(initStr) End Sub Sub String(initStr As *Char, length As Long) String() Assign(initStr, length) End Sub Sub String(ByRef initStr As String) String() Assign(initStr) End Sub Sub String(length As Long) String() ReSize(length) End Sub Sub String(initChar As Char, length As Long) ReSize(length, initChar) End Sub Sub ~String() _System_free(Chars) Chars = 0 #ifdef _DEBUG m_Length = 0 #endif End Sub Const Function Length() As Long Return m_Length End Function Function Operator() As *Char Return Chars End Function Sub Operator = (ByRef objString As String) Assign(objString.Chars, objString.m_Length) End Sub Sub Operator = (text As *Char) Assign(text) End Sub Const Function Operator [] (n As Long) As Char Return Chars[n] End Function Sub Operator []= (n As Long, c As Char) Chars[n] = c End Sub Const Function Operator + (pszText As *Char) As String Return Concat(pszText, lstrlen(pszText)) End Function Const Function Operator + (ByRef objString As String) As String Return Concat(objString, objString.m_Length) End Function Const Function Operator & (pszText As *Char) As String Dim tempString = This + pszText Return tempString End Function Const Function Operator & (ByRef objString As String) As String Dim tempString = This + objString Return tempString End Function Const Function Operator == (ByRef objString As String) As Boolean Return _System_StrCmp(This, objString) = 0 End Function Const Function Operator == (text As *Char) As Long Return _System_StrCmp(This, text) = 0 End Function Const Function Operator <> (ByRef objString As String) As Boolean Return _System_StrCmp(This, objString) End Function Const Function Operator <> (text As *Char) As Boolean Return _System_StrCmp(This, text) End Function Const Function Operator < (ByRef objString As String) As Boolean Return _System_StrCmp(This, objString) < 0 End Function Const Function Operator < (text As *Char) As Boolean Return _System_StrCmp(This, text) < 0 End Function Const Function Operator > (ByRef objString As String) As Boolean Return _System_StrCmp(This, objString) > 0 End Function Const Function Operator > (text As *Char) As Boolean Return _System_StrCmp(This, text) > 0 End Function Const Function Operator <= (ByRef objString As String) As Boolean Return _System_StrCmp(This, objString) <= 0 End Function Const Function Operator <= (text As *Char) As Boolean Return _System_StrCmp(This, text) <= 0 End Function Const Function Operator >= (ByRef objString As String) As Boolean Return _System_StrCmp(This, objString) => 0 End Function Const Function Operator >= (text As *Char) As Boolean Return _System_StrCmp(This, text) => 0 End Function Const Function StrPtr() As *Char Return Chars End Function Sub ReSize(allocLength As Long) If allocLength < 0 Then Exit Sub If allocLength > m_Length Then Dim oldLength As Long oldLength = m_Length If AllocStringBuffer(allocLength) <> 0 Then ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (Char) * (m_Length - oldLength + 1)) End If Else m_Length = allocLength Chars[m_Length] = 0 End If End Sub Sub ReSize(allocLength As Long, c As Char) If allocLength < 0 Then Exit Sub ElseIf allocLength > m_Length Then Dim oldLength As Long oldLength = m_Length If AllocStringBuffer(allocLength) <> 0 Then Dim p = VarPtr(Chars[oldLength]) As *Char Dim fillLen = m_Length - oldLength Dim i As Long For i = 0 To ELM(fillLen) p[i] = c Next End If Else m_Length = allocLength End If Chars[m_Length] = 0 End Sub Sub Assign(text As *Char, textLength As Long) If text = Chars Then Exit Sub If AllocStringBuffer(textLength) <> 0 Then memcpy(Chars, text, SizeOf (Char) * textLength) Chars[m_Length] = 0 End If End Sub Sub Assign(ByRef objString As String) Assign(objString.Chars, objString.m_Length) End Sub Sub Assign(text As *Char) If text Then Assign(text, lstrlen(text)) Else 'Chars=_System_realloc(Chars,1) Chars[0] = 0 m_Length = 0 End If End Sub Sub Append(text As *Char, textLength As Long) Dim prevLen As Long prevLen = m_Length If AllocStringBuffer(m_Length + textLength) <> 0 Then memcpy(VarPtr(Chars[prevLen]), text, SizeOf (Char) * textLength) Chars[m_Length] = 0 End If End Sub Sub Append(text As *Char) Append(text, lstrlen(text)) End Sub Sub Append(ByRef str As String) Append(str.Chars, str.m_Length) End Sub Const Function Clone() As String Return This End Function Const Function Concat(lpszText As *Char, textLength As Long) As String Dim tempString As String With tempString .AllocStringBuffer(This.m_Length + textLength) memcpy(.Chars, This.Chars, SizeOf (Char) * This.m_Length) memcpy(VarPtr(.Chars[This.m_Length]), lpszText, SizeOf (Char) * textLength) .Chars[.m_Length] = 0 End With Return tempString End Function Const Function Contains(ByRef objString As String) As Boolean Return IndexOf(objString, 0, m_Length) >= 0 End Function Const Function Contains(lpszText As *Char) As Boolean Return IndexOf(lpszText, 0, m_Length) >= 0 End Function Const Function IndexOf(lpszText As *Char) As Long Return IndexOf(lpszText, 0, m_Length) End Function Const Function IndexOf(lpszText As *Char, startIndex As Long) As Long Return IndexOf(lpszText, startIndex, m_Length - startIndex) End Function Const Function IndexOf(lpszText As *Char, startIndex As Long, count As Long) As Long Dim length = lstrlen(lpszText) If startIndex < 0 Then Return -1 If count < 1 Or count + startIndex > m_Length Then Return -1 If length > m_Length Then Return -1 If length = 0 Then Return startIndex Dim i As Long, j As Long For i = startIndex To startIndex + count - 1 For j = 0 To length - 1 If Chars[i + j] = lpszText[j] Then If j = length - 1 Then Return i Else Exit For End If Next Next Return -1 End Function Const Function LastIndexOf(lpszText As *Char) As Long Return LastIndexOf(lpszText, m_Length - 1, m_Length) End Function Const Function LastIndexOf(lpszText As *Char, startIndex As Long) As Long Return LastIndexOf(lpszText As *Char, startIndex, startIndex + 1) End Function Const Function LastIndexOf(lpszText As *Char, startIndex As Long, count As Long) As Long Dim length = lstrlen(lpszText) If startIndex < 0 Or startIndex > m_Length - 1 Then Return -1 If count < 1 Or count > startIndex + 2 Then Return -1 If length > m_Length Then Return -1 If length = 0 Then Return startIndex Dim i As Long, j As Long For i = startIndex To startIndex - count + 1 Step -1 For j = length - 1 To 0 Step -1 If Chars[i + j] = lpszText[j] Then If j = 0 Then Return i Else Exit For End If Next Next Return -1 End Function Const Function StartsWith(lpszText As *Char) As Boolean Return IndexOf(lpszText) = 0 End Function Const Function EndsWith(lpszText As *Char) As Boolean Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText) End Function Const Function Insert(startIndex As Long, text As String) As String Return Insert(startIndex, text.Chars, text.Length) End Function Const Function Insert(startIndex As Long, text As *Char) As String Return Insert(startIndex, text, lstrlen(text)) End Function Const Function Insert(startIndex As Long, text As *Char, length As Long) As String If startIndex < 0 Or startIndex > m_Length Or length < 0 Then Debug 'ArgumentOutOfRangeException End If Insert.ReSize(m_Length + length) memcpy(Insert.Chars, Chars, SizeOf (Char) * startIndex) memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (Char) * length) memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (Char) * (m_Length - startIndex + 1)) End Function Const Function SubString(startIndex As Long) As String Return SubString(startIndex, m_Length - startIndex) End Function Const Function SubString(startIndex As Long, length As Long) As String If startIndex < 0 Or length <= 0 Then Return "" If startIndex + length > m_Length Then Return "" Dim temp As String temp.AllocStringBuffer(length) memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (Char) * length) Chars[m_Length] = 0 Return temp End Function Const Function Remove(startIndex As Long) As String Remove.ReSize(startIndex) memcpy(Remove.Chars, This.Chars, SizeOf (Char) * startIndex) End Function Const Function Remove(startIndex As Long, count As Long) As String Remove.ReSize(m_Length - count) memcpy(Remove.Chars, This.Chars, SizeOf (Char) * startIndex) memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (Char) * startIndex) End Function /* Static Function IsNullOrEmpty(s As String) As Boolean If s <> Nothing Then If s.m_Length > 0 Then Return True End If End If Return False End Function */ Const Function Replace(oldChar As Char, newChar As Char) As String Replace = Copy(This) With Replace Dim i As Long For i = 0 To ELM(.m_Length) If .Chars[i] = .oldChar Then .Chars[i] = .newChar End If Next End With End Function Const Function Replace(ByRef oldStr As String, ByRef newStr As String) As String ' If oldStr = Nothing Then Throw ArgumentNullException ' ' If newStr = Nothing Then ' Return ReplaceCore(oldStr, oldStr.m_Length, "", 0) ' Else Return ReplaceCore(oldStr, oldStr.m_Length, newStr, newStr.m_Length) ' End If End Function Const Function Replace(oldStr As *Char, newStr As *Char) If oldStr = 0 Then Debug 'Throw ArgumentNullException If newStr = 0 Then newStr = "" Return ReplaceCore(oldStr, lstrlen(oldStr), newStr, lstrlen(newStr)) As String End Function Const Function Replace(oldStr As *Char, oldLen As Long, newStr As *Char, newLen As Long) As String If oldStr = 0 Then Debug 'Throw ArgumentNullException If newStr = 0 Then newStr = "" newLen = 0 End If Return ReplaceCore(oldStr, oldLen, newStr, newLen) End Function Sub ToLower() Dim i As Long For i = 0 To m_Length Chars[i] = _System_ASCII_ToLower(Chars[i]) Next End Sub Sub ToUpper() Dim i As Long For i = 0 To m_Length Chars[i] = _System_ASCII_ToUpper(Chars[i]) Next End Sub Sub Swap(ByRef x As String) Dim tempLen As Long Dim tempChars As *Char tempLen = x.m_Length tempChars = x.Chars x.m_Length = This.m_Length x.Chars = This.Chars This.m_Length = tempLen This.Chars = tempChars End Sub Override Function ToString() As String Return This End Function Static Function Copy(s As String) As String Copy.Resize(s.m_Length) memcpy(Copy.Chars, This.Chars, SizeOf (Char) * m_Length) End Function Private ' メモリ確保に失敗すると元の文字列は失われない。(例外安全でいう強い保障) Function AllocStringBuffer(textLength As Long) As *Char If textLength < 0 Then Return 0 ElseIf textLength > m_Length Then AllocStringBuffer = _System_realloc(Chars, SizeOf(Char) * (textLength + 1)) If AllocStringBuffer <> 0 Then m_Length = textLength Chars = AllocStringBuffer End If Else m_Length = textLength AllocStringBuffer = Chars End If End Function Function ReplaceCore(oldStr As *Char, oldLen As Long, newStr As *Char, newLen As Long) As String If oldLen = 0 Then Debug 'Throw ArgumentException End If Dim tmp As String With tmp Dim current = 0 As Long Do Dim pos = IndexOf(oldStr, current) If pos = -1 Then Exit Do End If .Append(VarPtr(Chars[current]), pos - current) .Append(newStr, newLen) current = pos + oldLen Loop .Append(VarPtr(Chars[current]), m_Length - current) End With Return tmp End Function End Class