diff --git a/CHANGELOG.md b/CHANGELOG.md index 9217227d..1757fe2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 40 + +* Add to_static_string + +-------------------------------------------------------------------------------- + Version 39 Beast versions are now identified by a single integer which diff --git a/doc/quickref.xml b/doc/quickref.xml index fc11461e..c006e14e 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -183,6 +183,7 @@ prepare_buffer prepare_buffers system_category + to_static_string Macros diff --git a/include/beast/core/detail/static_string.hpp b/include/beast/core/detail/static_string.hpp index dbd92df1..a3e8b516 100644 --- a/include/beast/core/detail/static_string.hpp +++ b/include/beast/core/detail/static_string.hpp @@ -58,6 +58,16 @@ lexicographical_compare( s1.data(), s1.size(), s2.data(), s2.size()); } +// Maximum number of characters in the decimal +// representation of a binary number +inline +std::size_t constexpr +max_digits(std::size_t bytes) +{ + return static_cast( + bytes * 2.41) + 1; +} + } // detail } // beast diff --git a/include/beast/core/impl/static_string.ipp b/include/beast/core/impl/static_string.ipp index 4eec94fd..786eb516 100644 --- a/include/beast/core/impl/static_string.ipp +++ b/include/beast/core/impl/static_string.ipp @@ -450,6 +450,18 @@ copy(CharT* dest, size_type count, size_type pos) const -> return str.size(); } +template +void +static_string:: +resize(std::size_t n) +{ + if(n > max_size()) + throw detail::make_exception( + "n > max_size()", __FILE__, __LINE__); + n_ = n; + term(); +} + template void static_string:: @@ -518,6 +530,76 @@ assign_char(CharT ch, std::false_type) -> "max_size() == 0", __FILE__, __LINE__); } +namespace detail { + +template +static_string<1+max_digits(sizeof(Integer))> +to_static_string(Integer x, std::true_type) +{ + if(x == 0) + return {'0'}; + static_string<1 + detail::max_digits( + sizeof(Integer))> s; + if(x < 0) + { + x = -x; + char buf[max_digits(sizeof(x))]; + char* p = buf; + for(;x > 0; x /= 10) + *p++ = "0123456789"[x % 10]; + s.resize(1 + p - buf); + s[0] = '-'; + auto d = &s[1]; + while(p > buf) + *d++ = *--p; + } + else + { + char buf[max_digits(sizeof(x))]; + char* p = buf; + for(;x > 0; x /= 10) + *p++ = "0123456789"[x % 10]; + s.resize(p - buf); + auto d = &s[0]; + while(p > buf) + *d++ = *--p; + } + return s; +} + +template +static_string +to_static_string(Integer x, std::false_type) +{ + if(x == 0) + return {'0'}; + char buf[max_digits(sizeof(x))]; + char* p = buf; + for(;x > 0; x /= 10) + *p++ = "0123456789"[x % 10]; + static_string s; + s.resize(p - buf); + auto d = &s[0]; + while(p > buf) + *d++ = *--p; + return s; +} + +} // detail + +template +static_string +to_static_string(Integer x) +{ + static_assert( + std::is_integral::value, + "Integral requirements not met"); + return detail::to_static_string( + x, std::integral_constant::value>{}); +} + } // beast #endif diff --git a/include/beast/core/static_string.hpp b/include/beast/core/static_string.hpp index 1bd359e5..0f340acf 100644 --- a/include/beast/core/static_string.hpp +++ b/include/beast/core/static_string.hpp @@ -31,6 +31,8 @@ namespace beast { imposes a natural small upper limit on the size of a value. @note The stored string is always null-terminated. + + @see @ref to_static_string */ template< std::size_t N, @@ -783,13 +785,10 @@ public: /** Changes the number of characters stored. If the resulting string is larger, the new - characters are initialized to zero. + characters are uninitialized. */ void - resize(std::size_t n) - { - resize(n, 0); - } + resize(std::size_t n); /** Changes the number of characters stored. @@ -1098,6 +1097,23 @@ operator<<(std::basic_ostream& os, beast::basic_string_view>(str); } +// +// Numeric conversions +// + +/** Returns a static string representing an integer as a decimal. + + @param x The signed or unsigned integer to convert. + This must be an integral type. + + @return A @ref static_string with an implementation defined + maximum size large enough to hold the longest possible decimal + representation of any integer of the given type. +*/ +template +static_string +to_static_string(Integer x); + } // beast #include diff --git a/test/core/static_string.cpp b/test/core/static_string.cpp index ade4d50e..227b2e72 100644 --- a/test/core/static_string.cpp +++ b/test/core/static_string.cpp @@ -1433,7 +1433,29 @@ public: pass(); } - void run() override + void + testToStaticString() + { + BEAST_EXPECT(to_static_string(0) == "0"); + BEAST_EXPECT(to_static_string(1) == "1"); + BEAST_EXPECT(to_static_string(0xffff) == "65535"); + BEAST_EXPECT(to_static_string(0x10000) == "65536"); + BEAST_EXPECT(to_static_string(0xffffffff) == "4294967295"); + + BEAST_EXPECT(to_static_string(-1) == "-1"); + BEAST_EXPECT(to_static_string(-65535) == "-65535"); + BEAST_EXPECT(to_static_string(-65536) == "-65536"); + BEAST_EXPECT(to_static_string(-4294967295ll) == "-4294967295"); + + BEAST_EXPECT(to_static_string(0) == "0"); + BEAST_EXPECT(to_static_string(1) == "1"); + BEAST_EXPECT(to_static_string(0xffff) == "65535"); + BEAST_EXPECT(to_static_string(0x10000) == "65536"); + BEAST_EXPECT(to_static_string(0xffffffff) == "4294967295"); + } + + void + run() override { testConstruct(); testAssign(); @@ -1445,6 +1467,7 @@ public: testSwap(); testGeneral(); + testToStaticString(); } };