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

View File

@ -836,24 +836,152 @@ assign_char(CharT, std::false_type) ->
return *this; return *this;
} }
template<class Integer, class> // string
static_string<std::numeric_limits<int>::digits10 + 1>
inline inline
basic_static_string<detail::max_digits(sizeof(Integer)), char> to_static_string(int value)
to_static_string(Integer x)
{ {
using CharT = char; return detail::to_static_string_int_impl<
using Traits = std::char_traits<CharT>; std::char_traits<char>, std::numeric_limits<int>::digits10 + 1>(value);
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); static_string<std::numeric_limits<long>::digits10 + 1>
auto it = detail::raw_to_string< inline
CharT, Integer, Traits>(last, sizeof(buf), x); to_static_string(long value)
basic_static_string<detail::max_digits(sizeof(Integer)), char> s; {
s.resize(static_cast<std::size_t>(last - it)); return detail::to_static_string_int_impl<
auto p = s.data(); std::char_traits<char>, std::numeric_limits<long>::digits10 + 1>(value);
while(it < last) }
Traits::assign(*p++, *it++);
return s; 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 } // 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()); 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 // Numeric conversions
// //
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** Returns a static string representing an integer as a decimal. // string
@param x The signed or unsigned integer to convert. static_string<std::numeric_limits<int>::digits10 + 1>
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
>
inline inline
basic_static_string<detail::max_digits(sizeof(Integer)), char> to_static_string(int value);
to_static_string(Integer x);
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()); return boost::hash_range(str.begin(), str.end());
} }
#endif #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 } // static_string
} // boost } // boost
#ifndef GENERATING_DOCUMENTATION
// std::hash partial specialization for basic_static_string // std::hash partial specialization for basic_static_string
#endif
namespace std namespace std
{ {
template <std::size_t N, typename CharT, typename Traits> template <std::size_t N, typename CharT, typename Traits>