diff options
-rw-r--r-- | codemaker/source/cppumaker/cppumaker.cxx | 13 | ||||
-rw-r--r-- | codemaker/source/cppumaker/dumputils.cxx | 5 | ||||
-rw-r--r-- | codemaker/source/cppumaker/dumputils.hxx | 2 | ||||
-rw-r--r-- | codemaker/source/javamaker/javamaker.cxx | 13 | ||||
-rw-r--r-- | include/o3tl/string_view.hxx | 44 | ||||
-rw-r--r-- | o3tl/qa/test-string_view.cxx | 107 | ||||
-rw-r--r-- | sal/osl/all/debugbase.cxx | 3 |
7 files changed, 171 insertions, 16 deletions
diff --git a/codemaker/source/cppumaker/cppumaker.cxx b/codemaker/source/cppumaker/cppumaker.cxx index 384e2b5aa079..b2556655b361 100644 --- a/codemaker/source/cppumaker/cppumaker.cxx +++ b/codemaker/source/cppumaker/cppumaker.cxx @@ -32,6 +32,7 @@ #include <sal/main.h> #include <sal/types.h> #include <unoidl/unoidl.hxx> +#include <o3tl/string_view.hxx> #include "cppuoptions.hxx" #include "cpputype.hxx" @@ -57,13 +58,13 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { if (options.isValid("-T")) { OUString names(b2u(options.getOption("-T"))); for (sal_Int32 i = 0; i != -1;) { - OUString name(names.getToken(0, ';', i)); - if (!name.isEmpty()) { + std::u16string_view name(o3tl::getToken(names, 0, ';', i)); + if (!name.empty()) { produce( - (name == "*" - ? "" - : name.endsWith(".*") - ? name.copy(0, name.getLength() - std::strlen(".*")) + OUString(name == u"*" + ? u"" + : o3tl::ends_with(name, u".*") + ? name.substr(0, name.size() - std::strlen(".*")) : name), typeMgr, generated, options); } diff --git a/codemaker/source/cppumaker/dumputils.cxx b/codemaker/source/cppumaker/dumputils.cxx index 8524b1962ce2..2a3e809e70f3 100644 --- a/codemaker/source/cppumaker/dumputils.cxx +++ b/codemaker/source/cppumaker/dumputils.cxx @@ -24,17 +24,18 @@ #include <rtl/ustring.hxx> #include <sal/types.h> +#include <o3tl/string_view.hxx> namespace codemaker::cppumaker { bool dumpNamespaceOpen( - FileStream & out, OUString const & entityName, bool fullModuleType) + FileStream & out, std::u16string_view entityName, bool fullModuleType) { bool bOutput = false; bool bFirst = true; for (sal_Int32 i = 0; i >= 0;) { - OUString id(entityName.getToken(0, '.', i)); + std::u16string_view id(o3tl::getToken(entityName, 0, '.', i)); if (fullModuleType || i >= 0) { if (!bFirst) { out << " "; diff --git a/codemaker/source/cppumaker/dumputils.hxx b/codemaker/source/cppumaker/dumputils.hxx index 2fcd708c43fb..24e5bae3bede 100644 --- a/codemaker/source/cppumaker/dumputils.hxx +++ b/codemaker/source/cppumaker/dumputils.hxx @@ -30,7 +30,7 @@ class FileStream; namespace codemaker::cppumaker { -bool dumpNamespaceOpen(FileStream& out, rtl::OUString const& entityName, bool fullModuleType); +bool dumpNamespaceOpen(FileStream& out, std::u16string_view entityName, bool fullModuleType); bool dumpNamespaceClose(FileStream& out, std::u16string_view entityName, bool fullModuleType); diff --git a/codemaker/source/javamaker/javamaker.cxx b/codemaker/source/javamaker/javamaker.cxx index 044292bf6b8f..ee376c8cc484 100644 --- a/codemaker/source/javamaker/javamaker.cxx +++ b/codemaker/source/javamaker/javamaker.cxx @@ -32,6 +32,7 @@ #include <sal/main.h> #include <sal/types.h> #include <unoidl/unoidl.hxx> +#include <o3tl/string_view.hxx> #include "javaoptions.hxx" #include "javatype.hxx" @@ -57,13 +58,13 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) { if (options.isValid("-T")) { OUString names(b2u(options.getOption("-T"))); for (sal_Int32 i = 0; i != -1;) { - OUString name(names.getToken(0, ';', i)); - if (!name.isEmpty()) { + std::u16string_view name(o3tl::getToken(names, 0, ';', i)); + if (!name.empty()) { produce( - (name == "*" - ? "" - : name.endsWith(".*") - ? name.copy(0, name.getLength() - std::strlen(".*")) + OUString(name == u"*" + ? u"" + : o3tl::ends_with(name, u".*") + ? name.substr(0, name.size() - std::strlen(".*")) : name), typeMgr, generated, options); } diff --git a/include/o3tl/string_view.hxx b/include/o3tl/string_view.hxx index b14258c14d39..d9fc84a0d18b 100644 --- a/include/o3tl/string_view.hxx +++ b/include/o3tl/string_view.hxx @@ -59,6 +59,50 @@ inline std::string_view getToken(std::string_view sv, char delimiter, std::size_ return t; } +// Similar to OUString::getToken +inline std::u16string_view getToken(std::u16string_view pStr, sal_Int32 nToken, sal_Unicode cTok, + sal_Int32& rnIndex) +{ + assert(rnIndex <= static_cast<sal_Int32>(pStr.size())); + + // Return an empty string and set rnIndex to -1 if either nToken or rnIndex is + // negative: + if (rnIndex >= 0 && nToken >= 0) + { + const sal_Unicode* pOrgCharStr = pStr.data(); + const sal_Unicode* pCharStr = pOrgCharStr + rnIndex; + sal_Int32 nLen = pStr.size() - rnIndex; + sal_Int32 nTokCount = 0; + const sal_Unicode* pCharStrStart = pCharStr; + while (nLen > 0) + { + if (*pCharStr == cTok) + { + nTokCount++; + + if (nTokCount > nToken) + break; + if (nTokCount == nToken) + pCharStrStart = pCharStr + 1; + } + + pCharStr++; + nLen--; + } + if (nTokCount >= nToken) + { + if (nLen > 0) + rnIndex = pCharStr - pOrgCharStr + 1; + else + rnIndex = -1; + return std::u16string_view(pCharStrStart, pCharStr - pCharStrStart); + } + } + + rnIndex = -1; + return std::u16string_view(); +} + // Implementations of C++20 std::basic_string_view::starts_with and // std::basic_string_view::ends_with, until we can use those directly on all platforms: template <typename charT, typename traits = std::char_traits<charT>> diff --git a/o3tl/qa/test-string_view.cxx b/o3tl/qa/test-string_view.cxx index 28ea5a2e99b0..80f9bd9e13fd 100644 --- a/o3tl/qa/test-string_view.cxx +++ b/o3tl/qa/test-string_view.cxx @@ -15,6 +15,7 @@ #include <cppunit/TestFixture.h> #include <cppunit/extensions/HelperMacros.h> +#include <o3tl/safeint.hxx> #include <o3tl/string_view.hxx> #include <rtl/string.hxx> #include <rtl/ustring.hxx> @@ -61,6 +62,7 @@ private: CPPUNIT_TEST(testEndsWith); CPPUNIT_TEST(testEndsWithRest); CPPUNIT_TEST(testEqualsIgnoreAsciiCase); + CPPUNIT_TEST(testGetToken); CPPUNIT_TEST_SUITE_END(); void testStartsWith() @@ -597,6 +599,111 @@ private: CPPUNIT_ASSERT_GREATER(0, o3tl::compareToIgnoreAsciiCase(u"zest"sv, u"test"sv)); CPPUNIT_ASSERT_LESS(0, o3tl::compareToIgnoreAsciiCase(u"test"sv, u"test2"sv)); } + + void testGetToken() + { + { + OUString suTokenStr; + sal_Int32 nIndex = 0; + do + { + o3tl::getToken(suTokenStr, 0, ';', nIndex); + } while (nIndex >= 0); + // should not GPF + } + { + OUString suTokenStr("a;b"); + + sal_Int32 nIndex = 0; + + std::u16string_view suToken = o3tl::getToken(suTokenStr, 0, ';', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'a'", std::u16string_view(u"a"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, ';', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'b'", std::u16string_view(u"b"), + suToken); + CPPUNIT_ASSERT_EQUAL_MESSAGE("index should be negative", static_cast<sal_Int32>(-1), + nIndex); + } + { + std::u16string_view suTokenStr(u"a;b.c"); + + sal_Int32 nIndex = 0; + + std::u16string_view suToken = o3tl::getToken(suTokenStr, 0, ';', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'a'", std::u16string_view(u"a"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, '.', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'b'", std::u16string_view(u"b"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, '.', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'c'", std::u16string_view(u"c"), + suToken); + CPPUNIT_ASSERT_EQUAL_MESSAGE("index should be negative", static_cast<sal_Int32>(-1), + nIndex); + } + { + std::u16string_view suTokenStr(u"a;;b"); + + sal_Int32 nIndex = 0; + + std::u16string_view suToken = o3tl::getToken(suTokenStr, 0, ';', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'a'", std::u16string_view(u"a"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, ';', nIndex); + CPPUNIT_ASSERT_MESSAGE("Token should be empty", suToken.empty()); + + suToken = o3tl::getToken(suTokenStr, 0, ';', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be a 'b'", std::u16string_view(u"b"), + suToken); + CPPUNIT_ASSERT_EQUAL_MESSAGE("index should be negative", static_cast<sal_Int32>(-1), + nIndex); + } + { + std::u16string_view suTokenStr(u"longer.then.ever."); + + sal_Int32 nIndex = 0; + + std::u16string_view suToken = o3tl::getToken(suTokenStr, 0, '.', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be 'longer'", std::u16string_view(u"longer"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, '.', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be 'then'", std::u16string_view(u"then"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, '.', nIndex); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Token should be 'ever'", std::u16string_view(u"ever"), + suToken); + + suToken = o3tl::getToken(suTokenStr, 0, '.', nIndex); + CPPUNIT_ASSERT_MESSAGE("Token should be empty", suToken.empty()); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("index should be negative", static_cast<sal_Int32>(-1), + nIndex); + } + { + std::u16string_view ab(u"ab"); + sal_Int32 n = 0; + CPPUNIT_ASSERT_EQUAL_MESSAGE("token should be 'ab'", ab, o3tl::getToken(ab, 0, '-', n)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("n should be -1", static_cast<sal_Int32>(-1), n); + CPPUNIT_ASSERT_MESSAGE("token should be empty", o3tl::getToken(ab, 0, '-', n).empty()); + } + { + std::u16string_view suTokenStr; + auto pTokenStr = suTokenStr.data(); + sal_uInt64 n64 = reinterpret_cast<sal_uInt64>(pTokenStr) / sizeof(sal_Unicode); + // Point either to 0x0, or to some random address -4GiB away from this string + sal_Int32 n = n64 > o3tl::make_unsigned(SAL_MAX_INT32) ? -SAL_MAX_INT32 + : -static_cast<sal_Int32>(n64); + o3tl::getToken(suTokenStr, 0, ';', n); + // should not GPF with negative index + } + } }; CPPUNIT_TEST_SUITE_REGISTRATION(Test); diff --git a/sal/osl/all/debugbase.cxx b/sal/osl/all/debugbase.cxx index 208fa3e92a92..59848a883c9d 100644 --- a/sal/osl/all/debugbase.cxx +++ b/sal/osl/all/debugbase.cxx @@ -23,6 +23,7 @@ #include <osl/process.h> #include <osl/diagnose.hxx> #include <sal/log.hxx> +#include <o3tl/string_view.hxx> #include <algorithm> #include <vector> @@ -42,7 +43,7 @@ struct StaticDebugBaseAddressFilter sal_Int32 nIndex = 0; do { vec.push_back( OUStringToOString( - str.getToken( 0, ';', nIndex ), + o3tl::getToken(str, 0, ';', nIndex ), RTL_TEXTENCODING_ASCII_US ) ); } while (nIndex >= 0); |