diff options
Diffstat (limited to 'sal/rtl/strtmpl.hxx')
-rw-r--r-- | sal/rtl/strtmpl.hxx | 219 |
1 files changed, 118 insertions, 101 deletions
diff --git a/sal/rtl/strtmpl.hxx b/sal/rtl/strtmpl.hxx index 256c0cc99dd0..c5cdc23fbc84 100644 --- a/sal/rtl/strtmpl.hxx +++ b/sal/rtl/strtmpl.hxx @@ -98,143 +98,173 @@ template <typename C1, typename C2> void warnIfOneIsCharAndNotAscii(C1 c1, C2 c2 } } -/* ----------------------------------------------------------------------- */ - -template <typename C1, typename C2> sal_Int32 compare(const C1* pStr1, const C2* pStr2) +struct CompareNormal { - assert(pStr1); - assert(pStr2); - if constexpr (sizeof(C1) == sizeof(char) && sizeof(C2) == sizeof(char)) + template <typename C1, typename C2> static sal_Int32 compare(C1 c1, C2 c2) { - // take advantage of builtin optimisations - return strcmp( pStr1, pStr2); + warnIfOneIsCharAndNotAscii(c1, c2); + return static_cast<sal_Int32>(IMPL_RTL_USTRCODE(c1)) + - static_cast<sal_Int32>(IMPL_RTL_USTRCODE(c2)); } - else if constexpr (sizeof(C1) == sizeof(wchar_t) && sizeof(C2) == sizeof(wchar_t)) +}; + +struct CompareIgnoreAsciiCase +{ + template <typename C1, typename C2> static sal_Int32 compare(C1 c1, C2 c2) { - // take advantage of builtin optimisations - return wcscmp(reinterpret_cast<wchar_t const *>(pStr1), reinterpret_cast<wchar_t const *>(pStr2)); + warnIfOneIsCharAndNotAscii(c1, c2); + return rtl::compareIgnoreAsciiCase(IMPL_RTL_USTRCODE(c1), IMPL_RTL_USTRCODE(c2)); } - else // including C1 != C2 - { - sal_Int32 nRet; - for (;;) - { - warnIfOneIsCharAndNotAscii(*pStr1, *pStr2); - - nRet = static_cast<sal_Int32>(IMPL_RTL_USTRCODE(*pStr1)) - - static_cast<sal_Int32>(IMPL_RTL_USTRCODE(*pStr2)); - if (!(nRet == 0 && *pStr2 )) - break; - pStr1++; - pStr2++; - } +}; - return nRet; +/* ----------------------------------------------------------------------- */ + +template <typename C1, typename C2, class Compare> +sal_Int32 compare(const C1* pStr1, const C2* pStr2, Compare) +{ + assert(pStr1); + assert(pStr2); + for (;;) + { + const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2); + if (!(nRet == 0 && *pStr2)) + return nRet; + ++pStr1; + ++pStr2; } } -/* ----------------------------------------------------------------------- */ - -template <typename IMPL_RTL_STRCODE> -sal_Int32 compare_WithLength ( const IMPL_RTL_STRCODE* pStr1, - sal_Int32 nStr1Len, - const IMPL_RTL_STRCODE* pStr2, - sal_Int32 nStr2Len ) +// take advantage of builtin optimisations +template <typename C, std::enable_if_t<sizeof(C) == sizeof(wchar_t), int> = 0> +sal_Int32 compare(const C* pStr1, const C* pStr2, CompareNormal) { - assert(nStr1Len >= 0); - assert(nStr2Len >= 0); - // take advantage of builtin optimisations - std::basic_string_view<IMPL_RTL_STRCODE> aView1(pStr1, nStr1Len); - std::basic_string_view<IMPL_RTL_STRCODE> aView2(pStr2, nStr2Len); - return aView1.compare(aView2); + assert(pStr1); + assert(pStr2); + return wcscmp(reinterpret_cast<wchar_t const*>(pStr1), reinterpret_cast<wchar_t const*>(pStr2)); +} +inline sal_Int32 compare(const char* pStr1, const char* pStr2, CompareNormal) +{ + assert(pStr1); + assert(pStr2); + return strcmp(pStr1, pStr2); } /* ----------------------------------------------------------------------- */ -template <typename IMPL_RTL_STRCODE> -sal_Int32 shortenedCompare_WithLength ( const IMPL_RTL_STRCODE* pStr1, - sal_Int32 nStr1Len, - const IMPL_RTL_STRCODE* pStr2, - sal_Int32 nStr2Len, - sal_Int32 nShortenedLength ) +template <typename C1, typename C2, class Compare> +sal_Int32 compare_WithLength(const C1* pStr1, sal_Int32 nStr1Len, const C2* pStr2, Compare) { - return compare_WithLength(pStr1, std::min(nStr1Len, nShortenedLength), - pStr2, std::min(nStr2Len, nShortenedLength)); + assert(pStr1 || nStr1Len == 0); + assert(nStr1Len >= 0); + assert(pStr2); + for (;;) + { + if (*pStr2 == '\0') + return nStr1Len; + if (nStr1Len == 0) + return -1; + if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2)) + return nRet; + pStr1++; + pStr2++; + nStr1Len--; + } } /* ----------------------------------------------------------------------- */ -template <typename C1, typename C2> -sal_Int32 reverseCompare_WithLength(const C1* pStr1, sal_Int32 nStr1Len, - const C2* pStr2, sal_Int32 nStr2Len) +template <typename C1, typename C2, class Compare> +sal_Int32 compare_WithLengths(const C1* pStr1, sal_Int32 nStr1Len, + const C2* pStr2, sal_Int32 nStr2Len, Compare) { + assert(pStr1 || nStr1Len == 0); assert(nStr1Len >= 0); + assert(pStr2 || nStr2Len == 0); assert(nStr2Len >= 0); - const C1* pStr1Run = pStr1+nStr1Len; - const C2* pStr2Run = pStr2+nStr2Len; - sal_Int32 nRet; - while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) ) + // TODO: use std::lexicographical_compare_three_way when C++20 is available + const C1* pStr1End = pStr1 + nStr1Len; + const C2* pStr2End = pStr2 + nStr2Len; + while ((pStr1 < pStr1End) && (pStr2 < pStr2End)) { - warnIfOneIsCharAndNotAscii(*pStr1, *pStr2); - - pStr1Run--; - pStr2Run--; - nRet = static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr1Run ))- - static_cast<sal_Int32>(IMPL_RTL_USTRCODE( *pStr2Run )); - if ( nRet ) + if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2)) return nRet; + pStr1++; + pStr2++; } return nStr1Len - nStr2Len; } +template <typename C> +sal_Int32 compare_WithLengths(const C* pStr1, sal_Int32 nStr1Len, + const C* pStr2, sal_Int32 nStr2Len, CompareNormal) +{ + assert(pStr1 || nStr1Len == 0); + assert(nStr1Len >= 0); + assert(pStr2 || nStr2Len == 0); + assert(nStr2Len >= 0); + // take advantage of builtin optimisations + std::basic_string_view<C> aView1(pStr1, nStr1Len); + std::basic_string_view<C> aView2(pStr2, nStr2Len); + return aView1.compare(aView2); +} + /* ----------------------------------------------------------------------- */ -template <typename C1, typename C2> -sal_Int32 compareIgnoreAsciiCase(const C1* pStr1, const C2* pStr2) +template <typename C1, typename C2, class Compare> +sal_Int32 shortenedCompare_WithLength(const C1* pStr1, sal_Int32 nStr1Len, const C2* pStr2, + sal_Int32 nShortenedLength, Compare) { assert(pStr1); + assert(nStr1Len >= 0); assert(pStr2); - sal_uInt32 c1; - do + assert(nShortenedLength >= 0); + const C1* pStr1End = pStr1 + nStr1Len; + for (;;) { - warnIfOneIsCharAndNotAscii(*pStr1, *pStr2); - - c1 = IMPL_RTL_USTRCODE(*pStr1); - sal_Int32 nRet = rtl::compareIgnoreAsciiCase( - c1, IMPL_RTL_USTRCODE(*pStr2)); - if ( nRet != 0 ) + if (nShortenedLength == 0) + return 0; + if (*pStr2 == '\0') + return pStr1End - pStr1; + if (pStr1 == pStr1End) + return -1; // first is a substring of the second string => less (negative value) + if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2)) return nRet; - + nShortenedLength--; pStr1++; pStr2++; } - while (c1); +} - return 0; +/* ----------------------------------------------------------------------- */ + +template <typename C1, typename C2, class Compare> +sal_Int32 shortenedCompare_WithLengths(const C1* pStr1, sal_Int32 nStr1Len, + const C2* pStr2, sal_Int32 nStr2Len, + sal_Int32 nShortenedLength, Compare cf) +{ + return compare_WithLengths(pStr1, std::min(nStr1Len, nShortenedLength), + pStr2, std::min(nStr2Len, nShortenedLength), cf); } /* ----------------------------------------------------------------------- */ -template <typename C1, typename C2> -sal_Int32 compareIgnoreAsciiCase_WithLength(const C1* pStr1, sal_Int32 nStr1Len, - const C2* pStr2, sal_Int32 nStr2Len) +template <typename C1, typename C2, class Compare> +sal_Int32 reverseCompare_WithLengths(const C1* pStr1, sal_Int32 nStr1Len, + const C2* pStr2, sal_Int32 nStr2Len, Compare) { + assert(pStr1 || nStr1Len == 0); assert(nStr1Len >= 0); + assert(pStr2 || nStr2Len == 0); assert(nStr2Len >= 0); - const C1* pStr1End = pStr1 + nStr1Len; - const C2* pStr2End = pStr2 + nStr2Len; - while ( (pStr1 < pStr1End) && (pStr2 < pStr2End) ) + const C1* pStr1Run = pStr1+nStr1Len; + const C2* pStr2Run = pStr2+nStr2Len; + while ((pStr1 < pStr1Run) && (pStr2 < pStr2Run)) { - warnIfOneIsCharAndNotAscii(*pStr1, *pStr2); - - sal_Int32 nRet = rtl::compareIgnoreAsciiCase( - IMPL_RTL_USTRCODE(*pStr1), IMPL_RTL_USTRCODE(*pStr2)); - if ( nRet != 0 ) + pStr1Run--; + pStr2Run--; + if (const sal_Int32 nRet = Compare::compare(*pStr1Run, *pStr2Run)) return nRet; - - pStr1++; - pStr2++; } return nStr1Len - nStr2Len; @@ -243,19 +273,6 @@ sal_Int32 compareIgnoreAsciiCase_WithLength(const C1* pStr1, sal_Int32 nStr1Len, /* ----------------------------------------------------------------------- */ template <typename IMPL_RTL_STRCODE> -sal_Int32 shortenedCompareIgnoreAsciiCase_WithLength ( const IMPL_RTL_STRCODE* pStr1, - sal_Int32 nStr1Len, - const IMPL_RTL_STRCODE* pStr2, - sal_Int32 nStr2Len, - sal_Int32 nShortenedLength ) -{ - return compareIgnoreAsciiCase_WithLength(pStr1, std::min(nStr1Len, nShortenedLength), - pStr2, std::min(nStr2Len, nShortenedLength)); -} - -/* ----------------------------------------------------------------------- */ - -template <typename IMPL_RTL_STRCODE> sal_Int32 hashCode_WithLength(const IMPL_RTL_STRCODE*, sal_Int32); template <typename IMPL_RTL_STRCODE> sal_Int32 hashCode( const IMPL_RTL_STRCODE* pStr ) |