diff options
author | Marshall Clow <mclow.lists@gmail.com> | 2019-06-05 21:04:26 +0000 |
---|---|---|
committer | Marshall Clow <mclow.lists@gmail.com> | 2019-06-05 21:04:26 +0000 |
commit | 7ce7110e6d964778141c0866488e154b1ce73d69 (patch) | |
tree | 370af54ba2e6c3f60853a89b06498d5eba123fca /libcxx/src | |
parent | 3975b15dbabd9ee595bcbada2088dd1395f52e0f (diff) | |
download | bcm5719-llvm-7ce7110e6d964778141c0866488e154b1ce73d69.tar.gz bcm5719-llvm-7ce7110e6d964778141c0866488e154b1ce73d69.zip |
Speedup to_string and to_wstring for integers using stack buffer and SSO. Reviewed as https://reviews.llvm.org/D59178 Thanks to ivafanas for all his work on this patch.
llvm-svn: 362649
Diffstat (limited to 'libcxx/src')
-rw-r--r-- | libcxx/src/string.cpp | 140 |
1 files changed, 37 insertions, 103 deletions
diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp index 6c89a5d7e06..4802d63c811 100644 --- a/libcxx/src/string.cpp +++ b/libcxx/src/string.cpp @@ -7,12 +7,14 @@ //===----------------------------------------------------------------------===// #include "string" +#include "charconv" #include "cstdlib" #include "cwchar" #include "cerrno" #include "limits" #include "stdexcept" #include <stdio.h> +#include "__debug" _LIBCPP_BEGIN_NAMESPACE_STD @@ -171,7 +173,7 @@ as_integer( const string& func, const wstring& s, size_t* idx, int base ) // as_float -template<typename V, typename S, typename F> +template<typename V, typename S, typename F> inline V as_float_helper(const string& func, const S& str, size_t* idx, F f ) @@ -375,11 +377,11 @@ as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) return s; } -template <class S, class V, bool = is_floating_point<V>::value> +template <class S> struct initial_string; -template <class V, bool b> -struct initial_string<string, V, b> +template <> +struct initial_string<string> { string operator()() const @@ -390,23 +392,8 @@ struct initial_string<string, V, b> } }; -template <class V> -struct initial_string<wstring, V, false> -{ - wstring - operator()() const - { - const size_t n = (numeric_limits<unsigned long long>::digits / 3) - + ((numeric_limits<unsigned long long>::digits % 3) != 0) - + 1; - wstring s(n, wchar_t()); - s.resize(s.capacity()); - return s; - } -}; - -template <class V> -struct initial_string<wstring, V, true> +template <> +struct initial_string<wstring> { wstring operator()() const @@ -430,95 +417,42 @@ get_swprintf() #endif } -} // unnamed namespace - -string to_string(int val) -{ - return as_string(snprintf, initial_string<string, int>()(), "%d", val); -} - -string to_string(unsigned val) +template <typename S, typename V> +S i_to_string(const V v) { - return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val); +// 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<V>::digits10 + 2; // +1 for minus, +1 for digits10 + 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); } -string to_string(long val) -{ - return as_string(snprintf, initial_string<string, long>()(), "%ld", val); -} - -string to_string(unsigned long val) -{ - return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val); -} - -string to_string(long long val) -{ - return as_string(snprintf, initial_string<string, long long>()(), "%lld", val); -} - -string to_string(unsigned long long val) -{ - return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val); -} - -string to_string(float val) -{ - return as_string(snprintf, initial_string<string, float>()(), "%f", val); -} - -string to_string(double val) -{ - return as_string(snprintf, initial_string<string, double>()(), "%f", val); -} - -string to_string(long double val) -{ - return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val); -} - -wstring to_wstring(int val) -{ - return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val); -} - -wstring to_wstring(unsigned val) -{ - return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val); -} - -wstring to_wstring(long val) -{ - return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val); -} +} // unnamed namespace -wstring to_wstring(unsigned long val) -{ - return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val); -} +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(long long val) -{ - return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val); -} +wstring to_wstring(int val) { return i_to_string<wstring>(val); } +wstring to_wstring(long val) { return i_to_string<wstring>(val); } +wstring to_wstring(long long val) { return i_to_string<wstring>(val); } +wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } +wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } +wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } -wstring to_wstring(unsigned long long val) -{ - return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val); -} -wstring to_wstring(float val) -{ - return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val); -} +string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } +string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } +string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } -wstring to_wstring(double val) -{ - return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val); -} +wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } +wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } +wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } -wstring to_wstring(long double val) -{ - return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val); -} _LIBCPP_END_NAMESPACE_STD |