diff --git a/gsl/string_span b/gsl/string_span index fa3d2ff..415744b 100644 --- a/gsl/string_span +++ b/gsl/string_span @@ -56,6 +56,10 @@ #endif // _MSC_VER <= 1800 #endif // _MSC_VER +#ifndef __CYGWIN__ +#define GSL_PLATFORM_HAS_STRNLEN +#endif + // In order to test the library, we need it to throw exceptions that we can catch #ifdef GSL_THROW_ON_CONTRACT_VIOLATION @@ -95,6 +99,27 @@ using zstring = basic_zstring; template using wzstring = basic_zstring; +namespace details +{ + inline std::size_t string_length(const char *str, std::size_t n) + { +#ifdef GSL_PLATFORM_HAS_STRNLEN + return strnlen(str, n); +#else + if (str == nullptr || n == 0) + return 0; + + std::size_t len = 0; + span str_span{str, n}; + + while (len < n && str_span[len]) + len++; + + return len; +#endif + } +} + // // ensure_sentinel() // @@ -127,14 +152,14 @@ inline span ensure_z(T* const& sz, std::ptrdiff_t max = PTRDI // overloads to share an implementation inline span ensure_z(char* const& sz, std::ptrdiff_t max) { - auto len = strnlen(sz, narrow_cast(max)); + auto len = details::string_length(sz, narrow_cast(max)); Ensures(sz[len] == 0); return {sz, static_cast(len)}; } inline span ensure_z(const char* const& sz, std::ptrdiff_t max) { - auto len = strnlen(sz, narrow_cast(max)); + auto len = details::string_length(sz, narrow_cast(max)); Ensures(sz[len] == 0); return {sz, static_cast(len)}; } @@ -196,7 +221,7 @@ namespace details { std::ptrdiff_t operator()(char* const ptr, std::ptrdiff_t length) noexcept { - return narrow_cast(strnlen(ptr, narrow_cast(length))); + return narrow_cast(details::string_length(ptr, narrow_cast(length))); } }; @@ -214,7 +239,7 @@ namespace details { std::ptrdiff_t operator()(const char* const ptr, std::ptrdiff_t length) noexcept { - return narrow_cast(strnlen(ptr, narrow_cast(length))); + return narrow_cast(details::string_length(ptr, narrow_cast(length))); } };