universal internal strlen for all char types

master
Daniel Kolesa 2018-01-11 23:27:45 +01:00
parent 375c014f7a
commit a93ae710d0
2 changed files with 57 additions and 2 deletions

View File

@ -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<std::remove_reference_t<U>>;
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. */

View File

@ -5,9 +5,57 @@
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <type_traits>
#include "ostd/string.hh"
#include "ostd/format.hh"
namespace ostd {
namespace detail {
template<typename C>
inline std::size_t tstrlen_impl(C const *p) noexcept {
using SL = std::numeric_limits<std::size_t>;
using UL = std::numeric_limits<std::make_unsigned_t<C>>;
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<std::size_t const *>(p);
for (; !(((*wp - Lbits) & ~*wp) & Hbits); ++wp) {}
p = reinterpret_cast<C const *>(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 {