diff --git a/include/boost/static_string/detail/static_string.hpp b/include/boost/static_string/detail/static_string.hpp index d7fcf79..88386de 100644 --- a/include/boost/static_string/detail/static_string.hpp +++ b/include/boost/static_string/detail/static_string.hpp @@ -15,14 +15,22 @@ #include #include #include +#include namespace boost { namespace static_string { -namespace detail { template class basic_static_string; +namespace detail { + +template +using static_string = basic_static_string>; + +template +using static_wstring = basic_static_string>; + // At minimum an integral type shall not qualify as an iterator (Agustin Berge) template 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 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( - 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 +template 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 +template 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> +template 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( - last, i, std::is_signed{}); + 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 +inline +static_string +to_static_string_int_impl(Integer value) +{ + char buffer[N]; + const auto digits_end = std::end(buffer); + const auto digits_begin = integer_to_string( + digits_end, value, std::is_signed{}); + return static_string(digits_begin, std::distance(digits_begin, digits_end)); +} + +template +inline +static_wstring +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( + digits_end, value, std::is_signed{}); + return static_wstring(digits_begin, std::distance(digits_begin, digits_end)); +} + +template +inline +static_string +to_static_string_float_impl(Floating value) +{ + char buffer[N]; + std::sprintf(buffer, "%f", value); + return static_string(buffer); +} + +template +inline +static_wstring +to_static_wstring_float_impl(Floating value) +{ + wchar_t buffer[N]; + std::swprintf(buffer, L"%f", value); + return static_wstring(buffer); } template< diff --git a/include/boost/static_string/impl/static_string.hpp b/include/boost/static_string/impl/static_string.hpp index 6dd44ca..4e38b88 100644 --- a/include/boost/static_string/impl/static_string.hpp +++ b/include/boost/static_string/impl/static_string.hpp @@ -836,24 +836,152 @@ assign_char(CharT, std::false_type) -> return *this; } -template +// string + +static_string::digits10 + 1> inline -basic_static_string -to_static_string(Integer x) +to_static_string(int value) { - using CharT = char; - using Traits = std::char_traits; - BOOST_STATIC_STRING_STATIC_ASSERT(std::is_integral::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 s; - s.resize(static_cast(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, std::numeric_limits::digits10 + 1>(value); +} + +static_string::digits10 + 1> +inline +to_static_string(long value) +{ + return detail::to_static_string_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_string::digits10 + 1> +inline +to_static_string(long long value) +{ + return detail::to_static_string_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_string::digits10 + 1> +inline +to_static_string(unsigned int value) +{ + return detail::to_static_string_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_string::digits10 + 1> +inline +to_static_string(unsigned long value) +{ + return detail::to_static_string_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_string::digits10 + 1> +inline +to_static_string(unsigned long long value) +{ + return detail::to_static_string_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_string::max_digits10 + 1> +inline +to_static_string(float value) +{ + return detail::to_static_string_float_impl< + std::numeric_limits::max_digits10 + 1>(value); +} + +static_string::max_digits10 + 1> +inline +to_static_string(double value) +{ + return detail::to_static_string_float_impl< + std::numeric_limits::max_digits10 + 1>(value); +} + +static_string::max_digits10 + 1> +inline +to_static_string(long double value) +{ + return detail::to_static_string_float_impl< + std::numeric_limits::max_digits10 + 1>(value); +} + +// wstring + +static_wstring::digits10 + 1> +inline +to_static_wstring(int value) +{ + return detail::to_static_wstring_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_wstring::digits10 + 1> +inline +to_static_wstring(long value) +{ + return detail::to_static_wstring_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_wstring::digits10 + 1> +inline +to_static_wstring(long long value) +{ + return detail::to_static_wstring_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_wstring::digits10 + 1> +inline +to_static_wstring(unsigned int value) +{ + return detail::to_static_wstring_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_wstring::digits10 + 1> +inline +to_static_wstring(unsigned long value) +{ + return detail::to_static_wstring_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_wstring::digits10 + 1> +inline +to_static_wstring(unsigned long long value) +{ + return detail::to_static_wstring_int_impl< + std::char_traits, std::numeric_limits::digits10 + 1>(value); +} + +static_wstring::max_digits10 + 1> +inline +to_static_wstring(float value) +{ + return detail::to_static_wstring_float_impl< + std::numeric_limits::max_digits10 + 1>(value); +} + +static_wstring::max_digits10 + 1> +inline +to_static_wstring(double value) +{ + return detail::to_static_wstring_float_impl< + std::numeric_limits::max_digits10 + 1>(value); +} + +static_wstring::max_digits10 + 1> +inline +to_static_wstring(long double value) +{ + return detail::to_static_wstring_float_impl< + std::numeric_limits::max_digits10 + 1>(value); } } // static_string diff --git a/include/boost/static_string/static_string.hpp b/include/boost/static_string/static_string.hpp index 5e32113..fb5572b 100644 --- a/include/boost/static_string/static_string.hpp +++ b/include/boost/static_string/static_string.hpp @@ -2773,31 +2773,105 @@ operator<<(std::basic_ostream& os, return os << basic_string_view(s.data(), s.size()); } +//------------------------------------------------------------------------------ +// +// Aliases +// +//------------------------------------------------------------------------------ + +template +using static_string = basic_static_string; + +template +using static_wstring = basic_static_string; + +template +using static_u16string = basic_static_string; + +template +using static_u32string = basic_static_string; + //------------------------------------------------------------------------------ // // 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::value>::type -#endif -> +static_string::digits10 + 1> inline -basic_static_string -to_static_string(Integer x); +to_static_string(int value); + +static_string::digits10 + 1> +inline +to_static_string(long value); + +static_string::digits10 + 1> +inline +to_static_string(long long value); + +static_string::digits10 + 1> +inline +to_static_string(unsigned int value); + +static_string::digits10 + 1> +inline +to_static_string(unsigned long value); + +static_string::digits10 + 1> +inline +to_static_string(unsigned long long value); + +static_string::max_digits10 + 1> +inline +to_static_string(float value); + +static_string::max_digits10 + 1> +inline +to_static_string(double value); + +static_string::max_digits10 + 1> +inline +to_static_string(long double value); + +// wstring + +static_wstring::digits10 + 1> +inline +to_static_wstring(int value); + +static_wstring::digits10 + 1> +inline +to_static_wstring(long value); + +static_wstring::digits10 + 1> +inline +to_static_wstring(long long value); + +static_wstring::digits10 + 1> +inline +to_static_wstring(unsigned int value); + +static_wstring::digits10 + 1> +inline +to_static_wstring(unsigned long value); + +static_wstring::digits10 + 1> +inline +to_static_wstring(unsigned long long value); + +static_wstring::max_digits10 + 1> +inline +to_static_wstring(float value); + +static_wstring::max_digits10 + 1> +inline +to_static_wstring(double value); + +static_wstring::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 -using static_string = basic_static_string; - -template -using static_wstring = basic_static_string; - -template -using static_u16string = basic_static_string; - -template -using static_u32string = basic_static_string; - } // static_string } // boost +#ifndef GENERATING_DOCUMENTATION // std::hash partial specialization for basic_static_string +#endif namespace std { template