diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp --- a/libcxx/src/string.cpp +++ b/libcxx/src/string.cpp @@ -422,34 +422,48 @@ #endif } -template -S i_to_string(const V v) +template +struct num_limits { + static constexpr int max_chars10 = numeric_limits::digits10 + 1 + (is_signed::value ? 1 : 0); +}; + +template +string i_to_string(const V v) +{ + string buf; + buf.resize(buf.capacity()); + _LIBCPP_ASSERT(buf.size() >= num_limits::max_chars10, "Capacity is too small"); + const auto res = to_chars(buf.data(), buf.data() + buf.size(), v); + _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); + buf.resize(res.ptr - buf.data()); + return buf; +} + +template +wstring i_to_wstring(const V v) { -// numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. -// For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), -// so we need +1 here. - constexpr size_t bufsize = numeric_limits::digits10 + 2; // +1 for minus, +1 for digits10 + constexpr size_t bufsize = num_limits::max_chars10; char buf[bufsize]; const auto res = to_chars(buf, buf + bufsize, v); _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); - return S(buf, res.ptr); + return wstring(buf, res.ptr); } } // unnamed namespace -string to_string (int val) { return i_to_string< string>(val); } -string to_string (long val) { return i_to_string< string>(val); } -string to_string (long long val) { return i_to_string< string>(val); } -string to_string (unsigned val) { return i_to_string< string>(val); } -string to_string (unsigned long val) { return i_to_string< string>(val); } -string to_string (unsigned long long val) { return i_to_string< string>(val); } - -wstring to_wstring(int val) { return i_to_string(val); } -wstring to_wstring(long val) { return i_to_string(val); } -wstring to_wstring(long long val) { return i_to_string(val); } -wstring to_wstring(unsigned val) { return i_to_string(val); } -wstring to_wstring(unsigned long val) { return i_to_string(val); } -wstring to_wstring(unsigned long long val) { return i_to_string(val); } +string to_string (int val) { return i_to_string(val); } +string to_string (long val) { return i_to_string(val); } +string to_string (long long val) { return i_to_string(val); } +string to_string (unsigned val) { return i_to_string(val); } +string to_string (unsigned long val) { return i_to_string(val); } +string to_string (unsigned long long val) { return i_to_string(val); } + +wstring to_wstring(int val) { return i_to_wstring(val); } +wstring to_wstring(long val) { return i_to_wstring(val); } +wstring to_wstring(long long val) { return i_to_wstring(val); } +wstring to_wstring(unsigned val) { return i_to_wstring(val); } +wstring to_wstring(unsigned long val) { return i_to_wstring(val); } +wstring to_wstring(unsigned long long val) { return i_to_wstring(val); } string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }