diff --git a/include/final/fstring.h b/include/final/fstring.h index e6c90cae..b253a4ec 100644 --- a/include/final/fstring.h +++ b/include/final/fstring.h @@ -352,16 +352,19 @@ class FString FString removeDel() const; FString removeBackspaces() const; - const FString& overwrite (const FString&, uInt); - const FString& overwrite (const wchar_t[], uInt); - const FString& overwrite (const wchar_t, uInt); + const FString& overwrite (const FString&, int); + const FString& overwrite (const FString&, uInt = 0); + const FString& overwrite (const wchar_t[], int); + const FString& overwrite (const wchar_t[], uInt = 0); + const FString& overwrite (const wchar_t, int); + const FString& overwrite (const wchar_t, uInt = 0); const FString& remove (uInt, uInt); - bool includes (const FString&); - bool includes (const wchar_t[]); - bool includes (const char[]); - bool includes (const wchar_t); - bool includes (const char); + bool includes (const FString&) const; + bool includes (const wchar_t[]) const; + bool includes (const char[]) const; + bool includes (const wchar_t) const; + bool includes (const char) const; private: // Constants diff --git a/src/fstring.cpp b/src/fstring.cpp index e498bdd6..a3cb37df 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -2408,9 +2408,21 @@ FString FString::removeBackspaces() const return s; } +//---------------------------------------------------------------------- +const FString& FString::overwrite (const FString& s, int pos) +{ + if ( pos < 0 ) + return overwrite (s, 0); + + return overwrite (s, uInt(pos)); +} + //---------------------------------------------------------------------- const FString& FString::overwrite (const FString& s, uInt pos) { + if ( pos > length ) + pos = length; + if ( length >= (pos + s.length) ) { std::wcsncpy (string + pos, s.string, s.length); @@ -2424,12 +2436,24 @@ const FString& FString::overwrite (const FString& s, uInt pos) return *this; } +//---------------------------------------------------------------------- +const FString& FString::overwrite (const wchar_t s[], int pos) +{ + if ( pos < 0 ) + return overwrite (s, 0); + + return overwrite (s, uInt(pos)); +} + //---------------------------------------------------------------------- const FString& FString::overwrite (const wchar_t s[], uInt pos) { uInt len = uInt(std::wcslen(s)); - if ( length >= (pos +len) ) + if ( pos > length ) + pos = length; + + if ( length >= (pos + len) ) { std::wcsncpy (string + pos, s, len); } @@ -2442,12 +2466,29 @@ const FString& FString::overwrite (const wchar_t s[], uInt pos) return *this; } +//---------------------------------------------------------------------- +const FString& FString::overwrite (const wchar_t c, int pos) +{ + if ( pos < 0 ) + return overwrite (c, 0); + + return overwrite (c, uInt(pos)); +} + //---------------------------------------------------------------------- const FString& FString::overwrite (const wchar_t c, uInt pos) { + if ( pos > length ) + pos = length; + if ( length >= (pos + 1) ) - { string[pos] = c; + else + { + wchar_t s[2]; + s[0] = c; + s[1] = L'\0'; + _insert (length, pos + 1 - length, s); } return *this; @@ -2456,34 +2497,48 @@ const FString& FString::overwrite (const wchar_t c, uInt pos) //---------------------------------------------------------------------- const FString& FString::remove (uInt pos, uInt len) { - assert ((pos < length) && ((pos + len) <= length)); + if ( pos > length ) + return *this; + + if ( pos + len > length ) + len = length - pos; + _remove (pos, len); return *this; } //---------------------------------------------------------------------- -bool FString::includes (const FString& s) +bool FString::includes (const FString& s) const { - if ( ! string ) + if ( ! s ) + return false; + + if ( ! (string && s.string) ) return false; return ( std::wcsstr(string, s.string) != 0 ); } //---------------------------------------------------------------------- -bool FString::includes (const wchar_t s[]) +bool FString::includes (const wchar_t s[]) const { - if ( ! string ) + if ( ! s ) + return false; + + if ( ! ( string && s[0]) ) return false; return ( std::wcsstr(string, s) != 0 ); } //---------------------------------------------------------------------- -bool FString::includes (const char s[]) +bool FString::includes (const char s[]) const { - if ( ! string ) + if ( ! s ) + return false; + + if ( ! (string && s[0]) ) return false; bool ret; @@ -2498,9 +2553,9 @@ bool FString::includes (const char s[]) } //---------------------------------------------------------------------- -bool FString::includes (const wchar_t c) +bool FString::includes (const wchar_t c) const { - if ( ! string ) + if ( ! (string && c) ) return false; wchar_t s[2]; @@ -2510,9 +2565,9 @@ bool FString::includes (const wchar_t c) } //---------------------------------------------------------------------- -bool FString::includes (const char c) +bool FString::includes (const char c) const { - if ( ! string ) + if ( ! (string && c) ) return false; wchar_t s[2]; diff --git a/src/test/fstring-test.cpp b/src/test/fstring-test.cpp index 533e619b..ae18d613 100644 --- a/src/test/fstring-test.cpp +++ b/src/test/fstring-test.cpp @@ -69,8 +69,8 @@ class FStringTest : public CPPUNIT_NS::TestFixture void notEqualTest(); void lessEqualTest(); void lessTest(); - void GreaterEqualTest(); - void GreaterTest(); + void greaterEqualTest(); + void greaterTest(); void streamInsertionTest(); void streamExtractionTest(); void subscriptOperatorTest(); @@ -83,6 +83,9 @@ class FStringTest : public CPPUNIT_NS::TestFixture void subStringTest(); void insertTest(); void replaceTest(); + void overwriteTest(); + void removeTest(); + void includesTest(); void controlCodesTest(); private: @@ -102,8 +105,8 @@ class FStringTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST (notEqualTest); CPPUNIT_TEST (lessEqualTest); CPPUNIT_TEST (lessTest); - CPPUNIT_TEST (GreaterEqualTest); - CPPUNIT_TEST (GreaterTest); + CPPUNIT_TEST (greaterEqualTest); + CPPUNIT_TEST (greaterTest); CPPUNIT_TEST (streamInsertionTest); CPPUNIT_TEST (streamExtractionTest); CPPUNIT_TEST (subscriptOperatorTest); @@ -116,6 +119,9 @@ class FStringTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST (subStringTest); CPPUNIT_TEST (insertTest); CPPUNIT_TEST (replaceTest); + CPPUNIT_TEST (overwriteTest); + CPPUNIT_TEST (removeTest); + CPPUNIT_TEST (includesTest); CPPUNIT_TEST (controlCodesTest); // End of test suite definition @@ -345,6 +351,9 @@ void FStringTest::assignmentTest() CPPUNIT_ASSERT ( s1 ); CPPUNIT_ASSERT ( s1 == "A character string" ); + s1.setString(L"A wide character string"); + // Set the identical content again. + // Requires no string replacement (new string = string) s1.setString(L"A wide character string"); CPPUNIT_ASSERT ( s1 ); CPPUNIT_ASSERT ( s1 == L"A wide character string" ); @@ -648,7 +657,7 @@ void FStringTest::lessTest() } //---------------------------------------------------------------------- -void FStringTest::GreaterEqualTest() +void FStringTest::greaterEqualTest() { const FString one_char('x'); const char ch = 'x'; @@ -693,7 +702,7 @@ void FStringTest::GreaterEqualTest() } //---------------------------------------------------------------------- -void FStringTest::GreaterTest() +void FStringTest::greaterTest() { const FString one_char('x'); const char ch = 'w'; @@ -1440,24 +1449,119 @@ void FStringTest::replaceTest() CPPUNIT_ASSERT ( s.replace(from3, empty) == "ABC" ); CPPUNIT_ASSERT ( s.replace(from5, to5) == "ABC" ); CPPUNIT_ASSERT ( s.replace(empty, to1) == "ABC" ); + CPPUNIT_ASSERT ( s.replace(from6, empty) == "ABC" ); empty = ""; CPPUNIT_ASSERT ( s.replace(from1, empty) == "ABC" ); CPPUNIT_ASSERT ( s.replace(from3, empty) == "ABC" ); CPPUNIT_ASSERT ( s.replace(from5, to5) == "ABC" ); CPPUNIT_ASSERT ( s.replace(empty, to1) == "ABC" ); + CPPUNIT_ASSERT ( s.replace(from6, empty) == "ABC" ); s.clear(); CPPUNIT_ASSERT ( s.replace(from1, to1).isNull() ); CPPUNIT_ASSERT ( s.replace(from1, to1).isEmpty() ); CPPUNIT_ASSERT ( s.replace(from6, to1).isNull() ); CPPUNIT_ASSERT ( s.replace(from6, to1).isEmpty() ); + CPPUNIT_ASSERT ( s.replace(from5, to5).isNull() ); CPPUNIT_ASSERT ( s.replace(from5, to5).isEmpty() ); CPPUNIT_ASSERT ( s.replace(from7, to7).isNull() ); CPPUNIT_ASSERT ( s.replace(from7, to7).isEmpty() ); } +//---------------------------------------------------------------------- +void FStringTest::overwriteTest() +{ + // FString + FString str = "abcdefghijklm"; + CPPUNIT_ASSERT ( str.overwrite("+++++++", 3) == "abc+++++++klm" ); + CPPUNIT_ASSERT ( str.overwrite(".............") == "............." ); + CPPUNIT_ASSERT ( str.overwrite(",,,,,,,,,,,,,,,") == ",,,,,,,,,,,,,,," ); + str = "abc"; + CPPUNIT_ASSERT ( str.overwrite("+++++", 99) == "abc+++++" ); + str = "abc"; + CPPUNIT_ASSERT ( str.overwrite("+++", -5) == "+++" ); + + // Wide string + str = "abcdefghijklm"; + CPPUNIT_ASSERT ( str.overwrite(L"+++++++", 3) == "abc+++++++klm" ); + CPPUNIT_ASSERT ( str.overwrite(L".............") == "............." ); + CPPUNIT_ASSERT ( str.overwrite(L",,,,,,,,,,,,,,,") == ",,,,,,,,,,,,,,," ); + str = "abc"; + CPPUNIT_ASSERT ( str.overwrite(L"+++++", 99) == "abc+++++" ); + str = "abc"; + CPPUNIT_ASSERT ( str.overwrite(L"+++", -5) == "+++" ); + + // Wide char + str = "abcdefghijklm"; + CPPUNIT_ASSERT ( str.overwrite(L'+', 3) == "abc+efghijklm" ); + CPPUNIT_ASSERT ( str.overwrite(L'.') == ".bc+efghijklm" ); + CPPUNIT_ASSERT ( str.overwrite(L',', 12) == ".bc+efghijkl," ); + CPPUNIT_ASSERT ( str.overwrite(L'.', 13) == ".bc+efghijkl,." ); + str = "abc"; + CPPUNIT_ASSERT ( str.overwrite(L'+', 99) == "abc+" ); + str = "abc"; + CPPUNIT_ASSERT ( str.overwrite(L'+', -5) == "+bc" ); +} + +//---------------------------------------------------------------------- +void FStringTest::removeTest() +{ + FString str = "ABCDE"; + CPPUNIT_ASSERT ( str.remove(2, 2) == "ABE" ); + CPPUNIT_ASSERT ( str.remove(2, 1) == "AB" ); + CPPUNIT_ASSERT ( str.remove(2, 1) == "AB" ); + CPPUNIT_ASSERT ( str.remove(2, 5) == "AB" ); + str = "ABCDE"; + CPPUNIT_ASSERT ( str.remove(2, 99) == "AB" ); + CPPUNIT_ASSERT ( str.remove(99, 1) == "AB" ); +} + +//---------------------------------------------------------------------- +void FStringTest::includesTest() +{ + const FString str = "Look behind you, a three-headed monkey!"; + const FString empty1; + const wchar_t empty2[] = L""; + const char empty3[] = ""; + const FString search1 = "you"; + const FString search2 = "me"; + const wchar_t search3[] = L"you"; + const wchar_t search4[] = L"me"; + const char search5[] = "you"; + const char search6[] = "me"; + const wchar_t search7 = L'y'; + const wchar_t search8 = L'&'; + const char search9 = 'y'; + const char search10 = '&'; + + CPPUNIT_ASSERT ( ! str.includes(empty1) ); + CPPUNIT_ASSERT ( str.includes(search1) ); + CPPUNIT_ASSERT ( ! str.includes(search2) ); + CPPUNIT_ASSERT ( ! empty1.includes(search1) ); + + CPPUNIT_ASSERT ( ! str.includes(empty2) ); + CPPUNIT_ASSERT ( str.includes(search3) ); + CPPUNIT_ASSERT ( ! str.includes(search4) ); + CPPUNIT_ASSERT ( ! empty1.includes(search3) ); + + CPPUNIT_ASSERT ( ! str.includes(empty3) ); + CPPUNIT_ASSERT ( str.includes(search5) ); + CPPUNIT_ASSERT ( ! str.includes(search6) ); + CPPUNIT_ASSERT ( ! empty1.includes(search5) ); + + CPPUNIT_ASSERT ( ! str.includes(wchar_t(L'\0')) ); + CPPUNIT_ASSERT ( str.includes(search7) ); + CPPUNIT_ASSERT ( ! str.includes(search8) ); + CPPUNIT_ASSERT ( ! empty1.includes(search7) ); + + CPPUNIT_ASSERT ( ! str.includes(char('\0')) ); + CPPUNIT_ASSERT ( str.includes(search9) ); + CPPUNIT_ASSERT ( ! str.includes(search10) ); + CPPUNIT_ASSERT ( ! empty1.includes(search9) ); +} + //---------------------------------------------------------------------- void FStringTest::controlCodesTest() { @@ -1539,8 +1643,8 @@ void FStringTest::controlCodesTest() CPPUNIT_ASSERT ( cc.replaceControlCodes() == FString(32, L' ') ); - cc = "t\b\bTesT\bt"; - CPPUNIT_ASSERT ( cc.replaceControlCodes() == "t␈␈TesT␈t" ); + cc = "t\b\bTes\177Tt"; + CPPUNIT_ASSERT ( cc.replaceControlCodes() == "t␈␈Tes␡Tt" ); } // Put the test suite in the registry