Skip to content

Commit 141c2b7

Browse files
committed
Recommit r362649, which was reverted in r262680 because of bugs in std::to_chars (which have now been fixed). Speedup to_string and to_wstring for integers using stack buffer and SSO
llvm-svn: 363003
1 parent efb14f9 commit 141c2b7

File tree

1 file changed

+37
-103
lines changed

1 file changed

+37
-103
lines changed

libcxx/src/string.cpp

Lines changed: 37 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "string"
10+
#include "charconv"
1011
#include "cstdlib"
1112
#include "cwchar"
1213
#include "cerrno"
1314
#include "limits"
1415
#include "stdexcept"
1516
#include <stdio.h>
17+
#include "__debug"
1618

1719
_LIBCPP_BEGIN_NAMESPACE_STD
1820

@@ -171,7 +173,7 @@ as_integer( const string& func, const wstring& s, size_t* idx, int base )
171173

172174
// as_float
173175

174-
template<typename V, typename S, typename F>
176+
template<typename V, typename S, typename F>
175177
inline
176178
V
177179
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)
375377
return s;
376378
}
377379

378-
template <class S, class V, bool = is_floating_point<V>::value>
380+
template <class S>
379381
struct initial_string;
380382

381-
template <class V, bool b>
382-
struct initial_string<string, V, b>
383+
template <>
384+
struct initial_string<string>
383385
{
384386
string
385387
operator()() const
@@ -390,23 +392,8 @@ struct initial_string<string, V, b>
390392
}
391393
};
392394

393-
template <class V>
394-
struct initial_string<wstring, V, false>
395-
{
396-
wstring
397-
operator()() const
398-
{
399-
const size_t n = (numeric_limits<unsigned long long>::digits / 3)
400-
+ ((numeric_limits<unsigned long long>::digits % 3) != 0)
401-
+ 1;
402-
wstring s(n, wchar_t());
403-
s.resize(s.capacity());
404-
return s;
405-
}
406-
};
407-
408-
template <class V>
409-
struct initial_string<wstring, V, true>
395+
template <>
396+
struct initial_string<wstring>
410397
{
411398
wstring
412399
operator()() const
@@ -430,95 +417,42 @@ get_swprintf()
430417
#endif
431418
}
432419

433-
} // unnamed namespace
434-
435-
string to_string(int val)
436-
{
437-
return as_string(snprintf, initial_string<string, int>()(), "%d", val);
438-
}
439-
440-
string to_string(unsigned val)
420+
template <typename S, typename V>
421+
S i_to_string(const V v)
441422
{
442-
return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
423+
// numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers.
424+
// For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented),
425+
// so we need +1 here.
426+
constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10
427+
char buf[bufsize];
428+
const auto res = to_chars(buf, buf + bufsize, v);
429+
_LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value");
430+
return S(buf, res.ptr);
443431
}
444432

445-
string to_string(long val)
446-
{
447-
return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
448-
}
449-
450-
string to_string(unsigned long val)
451-
{
452-
return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
453-
}
454-
455-
string to_string(long long val)
456-
{
457-
return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
458-
}
459-
460-
string to_string(unsigned long long val)
461-
{
462-
return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
463-
}
464-
465-
string to_string(float val)
466-
{
467-
return as_string(snprintf, initial_string<string, float>()(), "%f", val);
468-
}
469-
470-
string to_string(double val)
471-
{
472-
return as_string(snprintf, initial_string<string, double>()(), "%f", val);
473-
}
474-
475-
string to_string(long double val)
476-
{
477-
return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
478-
}
479-
480-
wstring to_wstring(int val)
481-
{
482-
return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
483-
}
484-
485-
wstring to_wstring(unsigned val)
486-
{
487-
return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
488-
}
489-
490-
wstring to_wstring(long val)
491-
{
492-
return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
493-
}
433+
} // unnamed namespace
494434

495-
wstring to_wstring(unsigned long val)
496-
{
497-
return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
498-
}
435+
string to_string (int val) { return i_to_string< string>(val); }
436+
string to_string (long val) { return i_to_string< string>(val); }
437+
string to_string (long long val) { return i_to_string< string>(val); }
438+
string to_string (unsigned val) { return i_to_string< string>(val); }
439+
string to_string (unsigned long val) { return i_to_string< string>(val); }
440+
string to_string (unsigned long long val) { return i_to_string< string>(val); }
499441

500-
wstring to_wstring(long long val)
501-
{
502-
return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
503-
}
442+
wstring to_wstring(int val) { return i_to_string<wstring>(val); }
443+
wstring to_wstring(long val) { return i_to_string<wstring>(val); }
444+
wstring to_wstring(long long val) { return i_to_string<wstring>(val); }
445+
wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); }
446+
wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); }
447+
wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); }
504448

505-
wstring to_wstring(unsigned long long val)
506-
{
507-
return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
508-
}
509449

510-
wstring to_wstring(float val)
511-
{
512-
return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
513-
}
450+
string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }
451+
string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); }
452+
string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); }
514453

515-
wstring to_wstring(double val)
516-
{
517-
return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
518-
}
454+
wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }
455+
wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); }
456+
wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); }
519457

520-
wstring to_wstring(long double val)
521-
{
522-
return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
523-
}
524458
_LIBCPP_END_NAMESPACE_STD

0 commit comments

Comments
 (0)