Add to_static_string:

This function converts integers to their decimal
representation as a static string.

In addition, static_string::resize no longer initializes
characters if the new size is larger.
This commit is contained in:
Vinnie Falco
2017-05-07 18:40:22 -07:00
parent 8a49eed947
commit 4edd797611
6 changed files with 144 additions and 6 deletions

View File

@ -1,3 +1,9 @@
Version 40
* Add to_static_string
--------------------------------------------------------------------------------
Version 39
Beast versions are now identified by a single integer which

View File

@ -183,6 +183,7 @@
<member><link linkend="beast.ref.prepare_buffer">prepare_buffer</link></member>
<member><link linkend="beast.ref.prepare_buffers">prepare_buffers</link></member>
<member><link linkend="beast.ref.system_category">system_category</link></member>
<member><link linkend="beast.ref.to_static_string">to_static_string</link></member>
</simplelist>
<bridgehead renderas="sect3">Macros</bridgehead>
<simplelist type="vert" columns="1">

View File

@ -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<std::size_t>(
bytes * 2.41) + 1;
}
} // detail
} // beast

View File

@ -450,6 +450,18 @@ copy(CharT* dest, size_type count, size_type pos) const ->
return str.size();
}
template<std::size_t N, class CharT, class Traits>
void
static_string<N, CharT, Traits>::
resize(std::size_t n)
{
if(n > max_size())
throw detail::make_exception<std::length_error>(
"n > max_size()", __FILE__, __LINE__);
n_ = n;
term();
}
template<std::size_t N, class CharT, class Traits>
void
static_string<N, CharT, Traits>::
@ -518,6 +530,76 @@ assign_char(CharT ch, std::false_type) ->
"max_size() == 0", __FILE__, __LINE__);
}
namespace detail {
template<class Integer>
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<class Integer>
static_string<max_digits(sizeof(Integer))>
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<detail::max_digits(
sizeof(Integer))> s;
s.resize(p - buf);
auto d = &s[0];
while(p > buf)
*d++ = *--p;
return s;
}
} // detail
template<class Integer>
static_string<detail::max_digits(sizeof(Integer))>
to_static_string(Integer x)
{
static_assert(
std::is_integral<Integer>::value,
"Integral requirements not met");
return detail::to_static_string(
x, std::integral_constant<bool,
std::is_signed<Integer>::value>{});
}
} // beast
#endif

View File

@ -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<CharT, Traits>& os,
beast::basic_string_view<CharT, Traits>>(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<class Integer>
static_string<detail::max_digits(sizeof(Integer))>
to_static_string(Integer x);
} // beast
#include <beast/core/impl/static_string.ipp>

View File

@ -1433,7 +1433,29 @@ public:
pass();
}
void run() override
void
testToStaticString()
{
BEAST_EXPECT(to_static_string<long>(0) == "0");
BEAST_EXPECT(to_static_string<long>(1) == "1");
BEAST_EXPECT(to_static_string<long>(0xffff) == "65535");
BEAST_EXPECT(to_static_string<long>(0x10000) == "65536");
BEAST_EXPECT(to_static_string<long long>(0xffffffff) == "4294967295");
BEAST_EXPECT(to_static_string<long>(-1) == "-1");
BEAST_EXPECT(to_static_string<long>(-65535) == "-65535");
BEAST_EXPECT(to_static_string<long>(-65536) == "-65536");
BEAST_EXPECT(to_static_string<long long>(-4294967295ll) == "-4294967295");
BEAST_EXPECT(to_static_string<unsigned long>(0) == "0");
BEAST_EXPECT(to_static_string<unsigned long>(1) == "1");
BEAST_EXPECT(to_static_string<unsigned long>(0xffff) == "65535");
BEAST_EXPECT(to_static_string<unsigned long>(0x10000) == "65536");
BEAST_EXPECT(to_static_string<unsigned long>(0xffffffff) == "4294967295");
}
void
run() override
{
testConstruct();
testAssign();
@ -1445,6 +1467,7 @@ public:
testSwap();
testGeneral();
testToStaticString();
}
};