to_static_string and to_static_wstring overloads

This commit is contained in:
Krystian Stasiowski
2019-12-20 02:34:04 -05:00
parent c83e21e8f2
commit 4e4dcce1f1
3 changed files with 352 additions and 104 deletions

View File

@ -15,14 +15,22 @@
#include <iterator>
#include <type_traits>
#include <limits>
#include <cwchar>
namespace boost {
namespace static_string {
namespace detail {
template<std::size_t, typename, typename>
class basic_static_string;
namespace detail {
template<std::size_t N>
using static_string = basic_static_string<N, char, std::char_traits<char>>;
template<std::size_t N>
using static_wstring = basic_static_string<N, wchar_t, std::char_traits<wchar_t>>;
// At minimum an integral type shall not qualify as an iterator (Agustin Berge)
template<class T>
using is_input_iterator =
@ -288,73 +296,128 @@ lexicographical_compare(
s1.data(), s1.size(), s2.data(), s2.size());
}
// Maximum number of characters in the decimal
// representation of a binary number. This includes
// the potential minus sign.
//
BOOST_STATIC_STRING_CPP11_CONSTEXPR
template<typename Traits, typename Integer>
inline
std::size_t
max_digits(std::size_t bytes)
char*
integer_to_string(
char* str_end, Integer value, std::true_type)
{
return static_cast<std::size_t>(
bytes * 2.41) + 1 + 1;
if (value == 0)
{
Traits::assign(*--str_end, '0');
return str_end;
}
if (value < 0)
{
value = -value;
for(; value > 0; value /= 10)
Traits::assign(*--str_end, "0123456789"[value % 10]);
Traits::assign(*--str_end, '-');
return str_end;
}
for (; value > 0; value /= 10)
Traits::assign(*--str_end, "0123456789"[value % 10]);
return str_end;
}
template<typename CharT, class Integer, typename Traits>
template<typename Traits, typename Integer>
inline
CharT*
raw_to_string(
CharT* buf, Integer x, std::true_type)
char*
integer_to_string(
char* str_end, Integer value, std::false_type)
{
if(x == 0)
if (value == 0)
{
Traits::assign(*--buf, '0');
return buf;
Traits::assign(*--str_end, '0');
return str_end;
}
if(x < 0)
{
x = -x;
for(;x > 0; x /= 10)
Traits::assign(*--buf ,
"0123456789"[x % 10]);
Traits::assign(*--buf, '-');
return buf;
}
for(;x > 0; x /= 10)
Traits::assign(*--buf ,
"0123456789"[x % 10]);
return buf;
for (; value > 0; value /= 10)
Traits::assign(*--str_end, "0123456789"[value % 10]);
return str_end;
}
template<typename CharT, class Integer, typename Traits>
template<typename Traits, typename Integer>
inline
CharT*
raw_to_string(
CharT* buf, Integer x, std::false_type)
wchar_t*
integer_to_wstring(
wchar_t* str_end, Integer value, std::true_type)
{
if(x == 0)
{
*--buf = '0';
return buf;
}
for(;x > 0; x /= 10)
Traits::assign(*--buf ,
"0123456789"[x % 10]);
return buf;
if (value == 0)
{
Traits::assign(*--str_end, L'0');
return str_end;
}
if (value < 0)
{
value = -value;
for (; value > 0; value /= 10)
Traits::assign(*--str_end, L"0123456789"[value % 10]);
Traits::assign(*--str_end, L'-');
return str_end;
}
for (; value > 0; value /= 10)
Traits::assign(*--str_end, L"0123456789"[value % 10]);
return str_end;
}
template<
typename CharT,
class Integer,
typename Traits = std::char_traits<CharT>>
template<typename Traits, typename Integer>
inline
CharT*
raw_to_string(CharT* last, std::size_t size, Integer i)
wchar_t*
integer_to_wstring(
wchar_t* str_end, Integer value, std::false_type)
{
BOOST_STATIC_STRING_ASSERT(size >= max_digits(sizeof(Integer)));
return raw_to_string<CharT, Integer, Traits>(
last, i, std::is_signed<Integer>{});
if (value == 0)
{
Traits::assign(*--str_end, L'0');
return str_end;
}
for (; value > 0; value /= 10)
Traits::assign(*--str_end, L"0123456789"[value % 10]);
return str_end;
}
template<typename Traits, std::size_t N, typename Integer>
inline
static_string<N>
to_static_string_int_impl(Integer value)
{
char buffer[N];
const auto digits_end = std::end(buffer);
const auto digits_begin = integer_to_string<Traits, Integer>(
digits_end, value, std::is_signed<Integer>{});
return static_string<N>(digits_begin, std::distance(digits_begin, digits_end));
}
template<typename Traits, std::size_t N, typename Integer>
inline
static_wstring<N>
to_static_wstring_int_impl(Integer value)
{
wchar_t buffer[N];
const auto digits_end = std::end(buffer);
const auto digits_begin = integer_to_wstring<Traits, Integer>(
digits_end, value, std::is_signed<Integer>{});
return static_wstring<N>(digits_begin, std::distance(digits_begin, digits_end));
}
template<std::size_t N, typename Floating>
inline
static_string<N>
to_static_string_float_impl(Floating value)
{
char buffer[N];
std::sprintf(buffer, "%f", value);
return static_string<N>(buffer);
}
template<std::size_t N, typename Floating>
inline
static_wstring<N>
to_static_wstring_float_impl(Floating value)
{
wchar_t buffer[N];
std::swprintf(buffer, L"%f", value);
return static_wstring<N>(buffer);
}
template<

View File

@ -836,24 +836,152 @@ assign_char(CharT, std::false_type) ->
return *this;
}
template<class Integer, class>
// string
static_string<std::numeric_limits<int>::digits10 + 1>
inline
basic_static_string<detail::max_digits(sizeof(Integer)), char>
to_static_string(Integer x)
to_static_string(int value)
{
using CharT = char;
using Traits = std::char_traits<CharT>;
BOOST_STATIC_STRING_STATIC_ASSERT(std::is_integral<Integer>::value, "Integer must be an integral type");
char buf[detail::max_digits(sizeof(Integer))];
auto last = buf + sizeof(buf);
auto it = detail::raw_to_string<
CharT, Integer, Traits>(last, sizeof(buf), x);
basic_static_string<detail::max_digits(sizeof(Integer)), char> s;
s.resize(static_cast<std::size_t>(last - it));
auto p = s.data();
while(it < last)
Traits::assign(*p++, *it++);
return s;
return detail::to_static_string_int_impl<
std::char_traits<char>, std::numeric_limits<int>::digits10 + 1>(value);
}
static_string<std::numeric_limits<long>::digits10 + 1>
inline
to_static_string(long value)
{
return detail::to_static_string_int_impl<
std::char_traits<char>, std::numeric_limits<long>::digits10 + 1>(value);
}
static_string<std::numeric_limits<long long>::digits10 + 1>
inline
to_static_string(long long value)
{
return detail::to_static_string_int_impl<
std::char_traits<char>, std::numeric_limits<long long>::digits10 + 1>(value);
}
static_string<std::numeric_limits<unsigned int>::digits10 + 1>
inline
to_static_string(unsigned int value)
{
return detail::to_static_string_int_impl<
std::char_traits<char>, std::numeric_limits<unsigned int>::digits10 + 1>(value);
}
static_string<std::numeric_limits<unsigned long>::digits10 + 1>
inline
to_static_string(unsigned long value)
{
return detail::to_static_string_int_impl<
std::char_traits<char>, std::numeric_limits<unsigned long>::digits10 + 1>(value);
}
static_string<std::numeric_limits<unsigned long long>::digits10 + 1>
inline
to_static_string(unsigned long long value)
{
return detail::to_static_string_int_impl<
std::char_traits<char>, std::numeric_limits<unsigned long long>::digits10 + 1>(value);
}
static_string<std::numeric_limits<float>::max_digits10 + 1>
inline
to_static_string(float value)
{
return detail::to_static_string_float_impl<
std::numeric_limits<float>::max_digits10 + 1>(value);
}
static_string<std::numeric_limits<double>::max_digits10 + 1>
inline
to_static_string(double value)
{
return detail::to_static_string_float_impl<
std::numeric_limits<double>::max_digits10 + 1>(value);
}
static_string<std::numeric_limits<long double>::max_digits10 + 1>
inline
to_static_string(long double value)
{
return detail::to_static_string_float_impl<
std::numeric_limits<long double>::max_digits10 + 1>(value);
}
// wstring
static_wstring<std::numeric_limits<int>::digits10 + 1>
inline
to_static_wstring(int value)
{
return detail::to_static_wstring_int_impl<
std::char_traits<wchar_t>, std::numeric_limits<int>::digits10 + 1>(value);
}
static_wstring<std::numeric_limits<long>::digits10 + 1>
inline
to_static_wstring(long value)
{
return detail::to_static_wstring_int_impl<
std::char_traits<wchar_t>, std::numeric_limits<long>::digits10 + 1>(value);
}
static_wstring<std::numeric_limits<long long>::digits10 + 1>
inline
to_static_wstring(long long value)
{
return detail::to_static_wstring_int_impl<
std::char_traits<wchar_t>, std::numeric_limits<long long>::digits10 + 1>(value);
}
static_wstring<std::numeric_limits<unsigned int>::digits10 + 1>
inline
to_static_wstring(unsigned int value)
{
return detail::to_static_wstring_int_impl<
std::char_traits<wchar_t>, std::numeric_limits<unsigned int>::digits10 + 1>(value);
}
static_wstring<std::numeric_limits<unsigned long>::digits10 + 1>
inline
to_static_wstring(unsigned long value)
{
return detail::to_static_wstring_int_impl<
std::char_traits<wchar_t>, std::numeric_limits<unsigned long>::digits10 + 1>(value);
}
static_wstring<std::numeric_limits<unsigned long long>::digits10 + 1>
inline
to_static_wstring(unsigned long long value)
{
return detail::to_static_wstring_int_impl<
std::char_traits<wchar_t>, std::numeric_limits<unsigned long long>::digits10 + 1>(value);
}
static_wstring<std::numeric_limits<float>::max_digits10 + 1>
inline
to_static_wstring(float value)
{
return detail::to_static_wstring_float_impl<
std::numeric_limits<float>::max_digits10 + 1>(value);
}
static_wstring<std::numeric_limits<double>::max_digits10 + 1>
inline
to_static_wstring(double value)
{
return detail::to_static_wstring_float_impl<
std::numeric_limits<double>::max_digits10 + 1>(value);
}
static_wstring<std::numeric_limits<long double>::max_digits10 + 1>
inline
to_static_wstring(long double value)
{
return detail::to_static_wstring_float_impl<
std::numeric_limits<long double>::max_digits10 + 1>(value);
}
} // static_string

View File

@ -2773,31 +2773,105 @@ operator<<(std::basic_ostream<CharT, Traits>& os,
return os << basic_string_view<CharT, Traits>(s.data(), s.size());
}
//------------------------------------------------------------------------------
//
// Aliases
//
//------------------------------------------------------------------------------
template<std::size_t N>
using static_string = basic_static_string<N, char>;
template<std::size_t N>
using static_wstring = basic_static_string<N, wchar_t>;
template<std::size_t N>
using static_u16string = basic_static_string<N, char16_t>;
template<std::size_t N>
using static_u32string = basic_static_string<N, char32_t>;
//------------------------------------------------------------------------------
//
// Numeric conversions
//
//------------------------------------------------------------------------------
/** Returns a static string representing an integer as a decimal.
// string
@param x The signed or unsigned integer to convert.
This must be an integral type.
@return A @ref basic_static_string with an implementation defined
maximum size at least as large enough to hold the longest
possible decimal representation of any integer of the given type.
*/
template<
class Integer
#ifndef GENERATING_DOCUMENTATION
, class = typename std::enable_if<
std::is_integral<Integer>::value>::type
#endif
>
static_string<std::numeric_limits<int>::digits10 + 1>
inline
basic_static_string<detail::max_digits(sizeof(Integer)), char>
to_static_string(Integer x);
to_static_string(int value);
static_string<std::numeric_limits<long>::digits10 + 1>
inline
to_static_string(long value);
static_string<std::numeric_limits<long long>::digits10 + 1>
inline
to_static_string(long long value);
static_string<std::numeric_limits<unsigned int>::digits10 + 1>
inline
to_static_string(unsigned int value);
static_string<std::numeric_limits<unsigned long>::digits10 + 1>
inline
to_static_string(unsigned long value);
static_string<std::numeric_limits<unsigned long long>::digits10 + 1>
inline
to_static_string(unsigned long long value);
static_string<std::numeric_limits<float>::max_digits10 + 1>
inline
to_static_string(float value);
static_string<std::numeric_limits<double>::max_digits10 + 1>
inline
to_static_string(double value);
static_string<std::numeric_limits<long double>::max_digits10 + 1>
inline
to_static_string(long double value);
// wstring
static_wstring<std::numeric_limits<int>::digits10 + 1>
inline
to_static_wstring(int value);
static_wstring<std::numeric_limits<long>::digits10 + 1>
inline
to_static_wstring(long value);
static_wstring<std::numeric_limits<long long>::digits10 + 1>
inline
to_static_wstring(long long value);
static_wstring<std::numeric_limits<unsigned int>::digits10 + 1>
inline
to_static_wstring(unsigned int value);
static_wstring<std::numeric_limits<unsigned long>::digits10 + 1>
inline
to_static_wstring(unsigned long value);
static_wstring<std::numeric_limits<unsigned long long>::digits10 + 1>
inline
to_static_wstring(unsigned long long value);
static_wstring<std::numeric_limits<float>::max_digits10 + 1>
inline
to_static_wstring(float value);
static_wstring<std::numeric_limits<double>::max_digits10 + 1>
inline
to_static_wstring(double value);
static_wstring<std::numeric_limits<long double>::max_digits10 + 1>
inline
to_static_wstring(long double value);
//------------------------------------------------------------------------------
//
@ -2829,29 +2903,12 @@ hash_value(
return boost::hash_range(str.begin(), str.end());
}
#endif
//------------------------------------------------------------------------------
//
// Aliases
//
//------------------------------------------------------------------------------
template<std::size_t N>
using static_string = basic_static_string<N, char>;
template<std::size_t N>
using static_wstring = basic_static_string<N, wchar_t>;
template<std::size_t N>
using static_u16string = basic_static_string<N, char16_t>;
template<std::size_t N>
using static_u32string = basic_static_string<N, char32_t>;
} // static_string
} // boost
#ifndef GENERATING_DOCUMENTATION
// std::hash partial specialization for basic_static_string
#endif
namespace std
{
template <std::size_t N, typename CharT, typename Traits>