From a93ae710d04329b9a7134d97103971c18653735b Mon Sep 17 00:00:00 2001 From: q66 Date: Thu, 11 Jan 2018 23:27:45 +0100 Subject: [PATCH] universal internal strlen for all char types --- ostd/string.hh | 11 +++++++++-- src/string.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/ostd/string.hh b/ostd/string.hh index 5533eb2..4037b8b 100644 --- a/ostd/string.hh +++ b/ostd/string.hh @@ -73,6 +73,13 @@ static_assert( "wchar_t must correspond to either char, char16_t or char32_t" ); +namespace detail { + std::size_t tstrlen(char const *p) noexcept; + std::size_t tstrlen(char16_t const *p) noexcept; + std::size_t tstrlen(char32_t const *p) noexcept; + std::size_t tstrlen(wchar_t const *p) noexcept; +} + /** @addtogroup Strings * @{ */ @@ -135,7 +142,7 @@ public: std::size_t N = std::extent_v>; p_end = beg + N - (beg[N - 1] == '\0'); } else { - p_end = beg + (beg ? std::strlen(beg) : 0); + p_end = beg + (beg ? detail::tstrlen(beg) : 0); } } @@ -181,7 +188,7 @@ public: * The data pointed to by the argument must be zero terminated. */ basic_char_range &operator=(value_type *s) noexcept { - p_beg = s; p_end = s + (s ? std::strlen(s) : 0); return *this; + p_beg = s; p_end = s + (s ? detail::tstrlen(s) : 0); return *this; } /** @brief Checks if the slice is empty. */ diff --git a/src/string.cc b/src/string.cc index 0f6554e..721605b 100644 --- a/src/string.cc +++ b/src/string.cc @@ -5,9 +5,57 @@ #include #include +#include +#include +#include #include "ostd/string.hh" #include "ostd/format.hh" +namespace ostd { +namespace detail { + +template +inline std::size_t tstrlen_impl(C const *p) noexcept { + using SL = std::numeric_limits; + using UL = std::numeric_limits>; + constexpr std::size_t Lbits = SL::max() / UL::max(); + constexpr std::size_t Hbits = Lbits << (UL::digits - 1); + + C const *bp = p; + if constexpr(sizeof(C) >= sizeof(std::size_t)) { + goto sloop; + } + for (; std::uintptr_t(p) % sizeof(std::size_t); ++p) { + if (!*p) { + return (p - bp); + } + } + { + auto *wp = reinterpret_cast(p); + for (; !(((*wp - Lbits) & ~*wp) & Hbits); ++wp) {} + p = reinterpret_cast(wp); + } +sloop: + for (; *p; ++p) {} + return (p - bp); +} + +std::size_t tstrlen(char const *p) noexcept { + return tstrlen_impl(p); +} +std::size_t tstrlen(char16_t const *p) noexcept { + return tstrlen_impl(p); +} +std::size_t tstrlen(char32_t const *p) noexcept { + return tstrlen_impl(p); +} +std::size_t tstrlen(wchar_t const *p) noexcept { + return tstrlen_impl(p); +} + +} /* namespace detail */ +} /* namespace ostd */ + namespace ostd { namespace utf {