xref: /freebsd-12.1/contrib/libc++/src/string.cpp (revision aed8d94e)
17a984708SDavid Chisnall //===------------------------- string.cpp ---------------------------------===//
27a984708SDavid Chisnall //
37a984708SDavid Chisnall //                     The LLVM Compiler Infrastructure
47a984708SDavid Chisnall //
57a984708SDavid Chisnall // This file is dual licensed under the MIT and the University of Illinois Open
67a984708SDavid Chisnall // Source Licenses. See LICENSE.TXT for details.
77a984708SDavid Chisnall //
87a984708SDavid Chisnall //===----------------------------------------------------------------------===//
97a984708SDavid Chisnall 
107a984708SDavid Chisnall #include "string"
117a984708SDavid Chisnall #include "cstdlib"
127a984708SDavid Chisnall #include "cwchar"
137a984708SDavid Chisnall #include "cerrno"
144bab9fd9SDavid Chisnall #include "limits"
154bab9fd9SDavid Chisnall #include "stdexcept"
164f7ab58eSDimitry Andric #ifdef _LIBCPP_MSVCRT
177a984708SDavid Chisnall #include "support/win32/support.h"
184f7ab58eSDimitry Andric #endif // _LIBCPP_MSVCRT
194f7ab58eSDimitry Andric #include <stdio.h>
207a984708SDavid Chisnall 
217a984708SDavid Chisnall _LIBCPP_BEGIN_NAMESPACE_STD
227a984708SDavid Chisnall 
23*aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
247a984708SDavid Chisnall 
25*aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
26*aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
277a984708SDavid Chisnall 
287a984708SDavid Chisnall template
297a984708SDavid Chisnall     string
307a984708SDavid Chisnall     operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
317a984708SDavid Chisnall 
324bab9fd9SDavid Chisnall namespace
334bab9fd9SDavid Chisnall {
344bab9fd9SDavid Chisnall 
354bab9fd9SDavid Chisnall template<typename T>
364bab9fd9SDavid Chisnall inline
374bab9fd9SDavid Chisnall void throw_helper( const string& msg )
384bab9fd9SDavid Chisnall {
394bab9fd9SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
404bab9fd9SDavid Chisnall     throw T( msg );
414bab9fd9SDavid Chisnall #else
42854fa44bSDimitry Andric     fprintf(stderr, "%s\n", msg.c_str());
43*aed8d94eSDimitry Andric     _VSTD::abort();
444bab9fd9SDavid Chisnall #endif
454bab9fd9SDavid Chisnall }
464bab9fd9SDavid Chisnall 
474bab9fd9SDavid Chisnall inline
484bab9fd9SDavid Chisnall void throw_from_string_out_of_range( const string& func )
494bab9fd9SDavid Chisnall {
504bab9fd9SDavid Chisnall     throw_helper<out_of_range>(func + ": out of range");
514bab9fd9SDavid Chisnall }
524bab9fd9SDavid Chisnall 
534bab9fd9SDavid Chisnall inline
544bab9fd9SDavid Chisnall void throw_from_string_invalid_arg( const string& func )
554bab9fd9SDavid Chisnall {
564bab9fd9SDavid Chisnall     throw_helper<invalid_argument>(func + ": no conversion");
574bab9fd9SDavid Chisnall }
584bab9fd9SDavid Chisnall 
594bab9fd9SDavid Chisnall // as_integer
604bab9fd9SDavid Chisnall 
614bab9fd9SDavid Chisnall template<typename V, typename S, typename F>
624bab9fd9SDavid Chisnall inline
634bab9fd9SDavid Chisnall V
644bab9fd9SDavid Chisnall as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
654bab9fd9SDavid Chisnall {
66d72607e9SDimitry Andric     typename S::value_type* ptr = nullptr;
674bab9fd9SDavid Chisnall     const typename S::value_type* const p = str.c_str();
684bab9fd9SDavid Chisnall     typename remove_reference<decltype(errno)>::type errno_save = errno;
694bab9fd9SDavid Chisnall     errno = 0;
704bab9fd9SDavid Chisnall     V r = f(p, &ptr, base);
714bab9fd9SDavid Chisnall     swap(errno, errno_save);
724bab9fd9SDavid Chisnall     if (errno_save == ERANGE)
734bab9fd9SDavid Chisnall         throw_from_string_out_of_range(func);
744bab9fd9SDavid Chisnall     if (ptr == p)
754bab9fd9SDavid Chisnall         throw_from_string_invalid_arg(func);
764bab9fd9SDavid Chisnall     if (idx)
774bab9fd9SDavid Chisnall         *idx = static_cast<size_t>(ptr - p);
784bab9fd9SDavid Chisnall     return r;
794bab9fd9SDavid Chisnall }
804bab9fd9SDavid Chisnall 
814bab9fd9SDavid Chisnall template<typename V, typename S>
824bab9fd9SDavid Chisnall inline
834bab9fd9SDavid Chisnall V
844bab9fd9SDavid Chisnall as_integer(const string& func, const S& s, size_t* idx, int base);
854bab9fd9SDavid Chisnall 
864bab9fd9SDavid Chisnall // string
874bab9fd9SDavid Chisnall template<>
884bab9fd9SDavid Chisnall inline
894bab9fd9SDavid Chisnall int
904bab9fd9SDavid Chisnall as_integer(const string& func, const string& s, size_t* idx, int base )
914bab9fd9SDavid Chisnall {
924f7ab58eSDimitry Andric     // Use long as no Standard string to integer exists.
934bab9fd9SDavid Chisnall     long r = as_integer_helper<long>( func, s, idx, base, strtol );
944bab9fd9SDavid Chisnall     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
954bab9fd9SDavid Chisnall         throw_from_string_out_of_range(func);
964bab9fd9SDavid Chisnall     return static_cast<int>(r);
974bab9fd9SDavid Chisnall }
984bab9fd9SDavid Chisnall 
994bab9fd9SDavid Chisnall template<>
1004bab9fd9SDavid Chisnall inline
1014bab9fd9SDavid Chisnall long
1024bab9fd9SDavid Chisnall as_integer(const string& func, const string& s, size_t* idx, int base )
1034bab9fd9SDavid Chisnall {
1044bab9fd9SDavid Chisnall     return as_integer_helper<long>( func, s, idx, base, strtol );
1054bab9fd9SDavid Chisnall }
1064bab9fd9SDavid Chisnall 
1074bab9fd9SDavid Chisnall template<>
1084bab9fd9SDavid Chisnall inline
1094bab9fd9SDavid Chisnall unsigned long
1104bab9fd9SDavid Chisnall as_integer( const string& func, const string& s, size_t* idx, int base )
1114bab9fd9SDavid Chisnall {
1124bab9fd9SDavid Chisnall     return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
1134bab9fd9SDavid Chisnall }
1144bab9fd9SDavid Chisnall 
1154bab9fd9SDavid Chisnall template<>
1164bab9fd9SDavid Chisnall inline
1174bab9fd9SDavid Chisnall long long
1184bab9fd9SDavid Chisnall as_integer( const string& func, const string& s, size_t* idx, int base )
1194bab9fd9SDavid Chisnall {
1204bab9fd9SDavid Chisnall     return as_integer_helper<long long>( func, s, idx, base, strtoll );
1214bab9fd9SDavid Chisnall }
1224bab9fd9SDavid Chisnall 
1234bab9fd9SDavid Chisnall template<>
1244bab9fd9SDavid Chisnall inline
1254bab9fd9SDavid Chisnall unsigned long long
1264bab9fd9SDavid Chisnall as_integer( const string& func, const string& s, size_t* idx, int base )
1274bab9fd9SDavid Chisnall {
1284bab9fd9SDavid Chisnall     return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
1294bab9fd9SDavid Chisnall }
1304bab9fd9SDavid Chisnall 
1314bab9fd9SDavid Chisnall // wstring
1324bab9fd9SDavid Chisnall template<>
1334bab9fd9SDavid Chisnall inline
1344bab9fd9SDavid Chisnall int
1354bab9fd9SDavid Chisnall as_integer( const string& func, const wstring& s, size_t* idx, int base )
1364bab9fd9SDavid Chisnall {
1374bab9fd9SDavid Chisnall     // Use long as no Stantard string to integer exists.
1384bab9fd9SDavid Chisnall     long r = as_integer_helper<long>( func, s, idx, base, wcstol );
1394bab9fd9SDavid Chisnall     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
1404bab9fd9SDavid Chisnall         throw_from_string_out_of_range(func);
1414bab9fd9SDavid Chisnall     return static_cast<int>(r);
1424bab9fd9SDavid Chisnall }
1434bab9fd9SDavid Chisnall 
1444bab9fd9SDavid Chisnall template<>
1454bab9fd9SDavid Chisnall inline
1464bab9fd9SDavid Chisnall long
1474bab9fd9SDavid Chisnall as_integer( const string& func, const wstring& s, size_t* idx, int base )
1484bab9fd9SDavid Chisnall {
1494bab9fd9SDavid Chisnall     return as_integer_helper<long>( func, s, idx, base, wcstol );
1504bab9fd9SDavid Chisnall }
1514bab9fd9SDavid Chisnall 
1524bab9fd9SDavid Chisnall template<>
1534bab9fd9SDavid Chisnall inline
1544bab9fd9SDavid Chisnall unsigned long
1554bab9fd9SDavid Chisnall as_integer( const string& func, const wstring& s, size_t* idx, int base )
1564bab9fd9SDavid Chisnall {
1574bab9fd9SDavid Chisnall     return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
1584bab9fd9SDavid Chisnall }
1594bab9fd9SDavid Chisnall 
1604bab9fd9SDavid Chisnall template<>
1614bab9fd9SDavid Chisnall inline
1624bab9fd9SDavid Chisnall long long
1634bab9fd9SDavid Chisnall as_integer( const string& func, const wstring& s, size_t* idx, int base )
1644bab9fd9SDavid Chisnall {
1654bab9fd9SDavid Chisnall     return as_integer_helper<long long>( func, s, idx, base, wcstoll );
1664bab9fd9SDavid Chisnall }
1674bab9fd9SDavid Chisnall 
1684bab9fd9SDavid Chisnall template<>
1694bab9fd9SDavid Chisnall inline
1704bab9fd9SDavid Chisnall unsigned long long
1714bab9fd9SDavid Chisnall as_integer( const string& func, const wstring& s, size_t* idx, int base )
1724bab9fd9SDavid Chisnall {
1734bab9fd9SDavid Chisnall     return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
1744bab9fd9SDavid Chisnall }
1754bab9fd9SDavid Chisnall 
1764bab9fd9SDavid Chisnall // as_float
1774bab9fd9SDavid Chisnall 
1784bab9fd9SDavid Chisnall template<typename V, typename S, typename F>
1794bab9fd9SDavid Chisnall inline
1804bab9fd9SDavid Chisnall V
1814bab9fd9SDavid Chisnall as_float_helper(const string& func, const S& str, size_t* idx, F f )
1824bab9fd9SDavid Chisnall {
183d72607e9SDimitry Andric     typename S::value_type* ptr = nullptr;
1844bab9fd9SDavid Chisnall     const typename S::value_type* const p = str.c_str();
1854bab9fd9SDavid Chisnall     typename remove_reference<decltype(errno)>::type errno_save = errno;
1864bab9fd9SDavid Chisnall     errno = 0;
1874bab9fd9SDavid Chisnall     V r = f(p, &ptr);
1884bab9fd9SDavid Chisnall     swap(errno, errno_save);
1894bab9fd9SDavid Chisnall     if (errno_save == ERANGE)
1904bab9fd9SDavid Chisnall         throw_from_string_out_of_range(func);
1914bab9fd9SDavid Chisnall     if (ptr == p)
1924bab9fd9SDavid Chisnall         throw_from_string_invalid_arg(func);
1934bab9fd9SDavid Chisnall     if (idx)
1944bab9fd9SDavid Chisnall         *idx = static_cast<size_t>(ptr - p);
1954bab9fd9SDavid Chisnall     return r;
1964bab9fd9SDavid Chisnall }
1974bab9fd9SDavid Chisnall 
1984bab9fd9SDavid Chisnall template<typename V, typename S>
1994bab9fd9SDavid Chisnall inline
2004bab9fd9SDavid Chisnall V as_float( const string& func, const S& s, size_t* idx = nullptr );
2014bab9fd9SDavid Chisnall 
2024bab9fd9SDavid Chisnall template<>
2034bab9fd9SDavid Chisnall inline
2044bab9fd9SDavid Chisnall float
2054bab9fd9SDavid Chisnall as_float( const string& func, const string& s, size_t* idx )
2064bab9fd9SDavid Chisnall {
2074bab9fd9SDavid Chisnall     return as_float_helper<float>( func, s, idx, strtof );
2084bab9fd9SDavid Chisnall }
2094bab9fd9SDavid Chisnall 
2104bab9fd9SDavid Chisnall template<>
2114bab9fd9SDavid Chisnall inline
2124bab9fd9SDavid Chisnall double
2134bab9fd9SDavid Chisnall as_float(const string& func, const string& s, size_t* idx )
2144bab9fd9SDavid Chisnall {
2154bab9fd9SDavid Chisnall     return as_float_helper<double>( func, s, idx, strtod );
2164bab9fd9SDavid Chisnall }
2174bab9fd9SDavid Chisnall 
2184bab9fd9SDavid Chisnall template<>
2194bab9fd9SDavid Chisnall inline
2204bab9fd9SDavid Chisnall long double
2214bab9fd9SDavid Chisnall as_float( const string& func, const string& s, size_t* idx )
2224bab9fd9SDavid Chisnall {
2234bab9fd9SDavid Chisnall     return as_float_helper<long double>( func, s, idx, strtold );
2244bab9fd9SDavid Chisnall }
2254bab9fd9SDavid Chisnall 
2264bab9fd9SDavid Chisnall template<>
2274bab9fd9SDavid Chisnall inline
2284bab9fd9SDavid Chisnall float
2294bab9fd9SDavid Chisnall as_float( const string& func, const wstring& s, size_t* idx )
2304bab9fd9SDavid Chisnall {
2314bab9fd9SDavid Chisnall     return as_float_helper<float>( func, s, idx, wcstof );
2324bab9fd9SDavid Chisnall }
2334bab9fd9SDavid Chisnall 
2344bab9fd9SDavid Chisnall template<>
2354bab9fd9SDavid Chisnall inline
2364bab9fd9SDavid Chisnall double
2374bab9fd9SDavid Chisnall as_float( const string& func, const wstring& s, size_t* idx )
2384bab9fd9SDavid Chisnall {
2394bab9fd9SDavid Chisnall     return as_float_helper<double>( func, s, idx, wcstod );
2404bab9fd9SDavid Chisnall }
2414bab9fd9SDavid Chisnall 
2424bab9fd9SDavid Chisnall template<>
2434bab9fd9SDavid Chisnall inline
2444bab9fd9SDavid Chisnall long double
2454bab9fd9SDavid Chisnall as_float( const string& func, const wstring& s, size_t* idx )
2464bab9fd9SDavid Chisnall {
2474bab9fd9SDavid Chisnall     return as_float_helper<long double>( func, s, idx, wcstold );
2484bab9fd9SDavid Chisnall }
2494bab9fd9SDavid Chisnall 
2504bab9fd9SDavid Chisnall }  // unnamed namespace
2514bab9fd9SDavid Chisnall 
2527a984708SDavid Chisnall int
2537a984708SDavid Chisnall stoi(const string& str, size_t* idx, int base)
2547a984708SDavid Chisnall {
2554bab9fd9SDavid Chisnall     return as_integer<int>( "stoi", str, idx, base );
2567a984708SDavid Chisnall }
2577a984708SDavid Chisnall 
2587a984708SDavid Chisnall int
2597a984708SDavid Chisnall stoi(const wstring& str, size_t* idx, int base)
2607a984708SDavid Chisnall {
2614bab9fd9SDavid Chisnall     return as_integer<int>( "stoi", str, idx, base );
2627a984708SDavid Chisnall }
2637a984708SDavid Chisnall 
2647a984708SDavid Chisnall long
2657a984708SDavid Chisnall stol(const string& str, size_t* idx, int base)
2667a984708SDavid Chisnall {
2674bab9fd9SDavid Chisnall     return as_integer<long>( "stol", str, idx, base );
2687a984708SDavid Chisnall }
2697a984708SDavid Chisnall 
2707a984708SDavid Chisnall long
2717a984708SDavid Chisnall stol(const wstring& str, size_t* idx, int base)
2727a984708SDavid Chisnall {
2734bab9fd9SDavid Chisnall     return as_integer<long>( "stol", str, idx, base );
2747a984708SDavid Chisnall }
2757a984708SDavid Chisnall 
2767a984708SDavid Chisnall unsigned long
2777a984708SDavid Chisnall stoul(const string& str, size_t* idx, int base)
2787a984708SDavid Chisnall {
2794bab9fd9SDavid Chisnall     return as_integer<unsigned long>( "stoul", str, idx, base );
2807a984708SDavid Chisnall }
2817a984708SDavid Chisnall 
2827a984708SDavid Chisnall unsigned long
2837a984708SDavid Chisnall stoul(const wstring& str, size_t* idx, int base)
2847a984708SDavid Chisnall {
2854bab9fd9SDavid Chisnall     return as_integer<unsigned long>( "stoul", str, idx, base );
2867a984708SDavid Chisnall }
2877a984708SDavid Chisnall 
2887a984708SDavid Chisnall long long
2897a984708SDavid Chisnall stoll(const string& str, size_t* idx, int base)
2907a984708SDavid Chisnall {
2914bab9fd9SDavid Chisnall     return as_integer<long long>( "stoll", str, idx, base );
2927a984708SDavid Chisnall }
2937a984708SDavid Chisnall 
2947a984708SDavid Chisnall long long
2957a984708SDavid Chisnall stoll(const wstring& str, size_t* idx, int base)
2967a984708SDavid Chisnall {
2974bab9fd9SDavid Chisnall     return as_integer<long long>( "stoll", str, idx, base );
2987a984708SDavid Chisnall }
2997a984708SDavid Chisnall 
3007a984708SDavid Chisnall unsigned long long
3017a984708SDavid Chisnall stoull(const string& str, size_t* idx, int base)
3027a984708SDavid Chisnall {
3034bab9fd9SDavid Chisnall     return as_integer<unsigned long long>( "stoull", str, idx, base );
3047a984708SDavid Chisnall }
3057a984708SDavid Chisnall 
3067a984708SDavid Chisnall unsigned long long
3077a984708SDavid Chisnall stoull(const wstring& str, size_t* idx, int base)
3087a984708SDavid Chisnall {
3094bab9fd9SDavid Chisnall     return as_integer<unsigned long long>( "stoull", str, idx, base );
3107a984708SDavid Chisnall }
3117a984708SDavid Chisnall 
3127a984708SDavid Chisnall float
3137a984708SDavid Chisnall stof(const string& str, size_t* idx)
3147a984708SDavid Chisnall {
3154bab9fd9SDavid Chisnall     return as_float<float>( "stof", str, idx );
3167a984708SDavid Chisnall }
3177a984708SDavid Chisnall 
3187a984708SDavid Chisnall float
3197a984708SDavid Chisnall stof(const wstring& str, size_t* idx)
3207a984708SDavid Chisnall {
3214bab9fd9SDavid Chisnall     return as_float<float>( "stof", str, idx );
3227a984708SDavid Chisnall }
3237a984708SDavid Chisnall 
3247a984708SDavid Chisnall double
3257a984708SDavid Chisnall stod(const string& str, size_t* idx)
3267a984708SDavid Chisnall {
3274bab9fd9SDavid Chisnall     return as_float<double>( "stod", str, idx );
3287a984708SDavid Chisnall }
3297a984708SDavid Chisnall 
3307a984708SDavid Chisnall double
3317a984708SDavid Chisnall stod(const wstring& str, size_t* idx)
3327a984708SDavid Chisnall {
3334bab9fd9SDavid Chisnall     return as_float<double>( "stod", str, idx );
3347a984708SDavid Chisnall }
3357a984708SDavid Chisnall 
3367a984708SDavid Chisnall long double
3377a984708SDavid Chisnall stold(const string& str, size_t* idx)
3387a984708SDavid Chisnall {
3394bab9fd9SDavid Chisnall     return as_float<long double>( "stold", str, idx );
3407a984708SDavid Chisnall }
3417a984708SDavid Chisnall 
3427a984708SDavid Chisnall long double
3437a984708SDavid Chisnall stold(const wstring& str, size_t* idx)
3447a984708SDavid Chisnall {
3454bab9fd9SDavid Chisnall     return as_float<long double>( "stold", str, idx );
3467a984708SDavid Chisnall }
3477a984708SDavid Chisnall 
3484bab9fd9SDavid Chisnall // to_string
3494bab9fd9SDavid Chisnall 
3504bab9fd9SDavid Chisnall namespace
3514bab9fd9SDavid Chisnall {
3524bab9fd9SDavid Chisnall 
3534bab9fd9SDavid Chisnall // as_string
3544bab9fd9SDavid Chisnall 
3554bab9fd9SDavid Chisnall template<typename S, typename P, typename V >
3564bab9fd9SDavid Chisnall inline
3574bab9fd9SDavid Chisnall S
3584bab9fd9SDavid Chisnall as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
3594bab9fd9SDavid Chisnall {
3604bab9fd9SDavid Chisnall     typedef typename S::size_type size_type;
3614bab9fd9SDavid Chisnall     size_type available = s.size();
3624bab9fd9SDavid Chisnall     while (true)
3634bab9fd9SDavid Chisnall     {
3644bab9fd9SDavid Chisnall         int status = sprintf_like(&s[0], available + 1, fmt, a);
3654bab9fd9SDavid Chisnall         if ( status >= 0 )
3664bab9fd9SDavid Chisnall         {
3674bab9fd9SDavid Chisnall             size_type used = static_cast<size_type>(status);
3684bab9fd9SDavid Chisnall             if ( used <= available )
3694bab9fd9SDavid Chisnall             {
3704bab9fd9SDavid Chisnall                 s.resize( used );
3714bab9fd9SDavid Chisnall                 break;
3724bab9fd9SDavid Chisnall             }
3734bab9fd9SDavid Chisnall             available = used; // Assume this is advice of how much space we need.
3744bab9fd9SDavid Chisnall         }
3754bab9fd9SDavid Chisnall         else
3764bab9fd9SDavid Chisnall             available = available * 2 + 1;
3774bab9fd9SDavid Chisnall         s.resize(available);
3784bab9fd9SDavid Chisnall     }
3794bab9fd9SDavid Chisnall     return s;
3804bab9fd9SDavid Chisnall }
3814bab9fd9SDavid Chisnall 
3824bab9fd9SDavid Chisnall template <class S, class V, bool = is_floating_point<V>::value>
3834bab9fd9SDavid Chisnall struct initial_string;
3844bab9fd9SDavid Chisnall 
3854bab9fd9SDavid Chisnall template <class V, bool b>
3864bab9fd9SDavid Chisnall struct initial_string<string, V, b>
3874bab9fd9SDavid Chisnall {
3884bab9fd9SDavid Chisnall     string
3894bab9fd9SDavid Chisnall     operator()() const
3907a984708SDavid Chisnall     {
3917a984708SDavid Chisnall         string s;
3927a984708SDavid Chisnall         s.resize(s.capacity());
3937a984708SDavid Chisnall         return s;
3947a984708SDavid Chisnall     }
3954bab9fd9SDavid Chisnall };
3967a984708SDavid Chisnall 
3974bab9fd9SDavid Chisnall template <class V>
3984bab9fd9SDavid Chisnall struct initial_string<wstring, V, false>
3997a984708SDavid Chisnall {
4004bab9fd9SDavid Chisnall     wstring
4014bab9fd9SDavid Chisnall     operator()() const
4027a984708SDavid Chisnall     {
4037a984708SDavid Chisnall         const size_t n = (numeric_limits<unsigned long long>::digits / 3)
4047a984708SDavid Chisnall           + ((numeric_limits<unsigned long long>::digits % 3) != 0)
4057a984708SDavid Chisnall           + 1;
4067a984708SDavid Chisnall         wstring s(n, wchar_t());
4077a984708SDavid Chisnall         s.resize(s.capacity());
4087a984708SDavid Chisnall         return s;
4097a984708SDavid Chisnall     }
4104bab9fd9SDavid Chisnall };
4114bab9fd9SDavid Chisnall 
4124bab9fd9SDavid Chisnall template <class V>
4134bab9fd9SDavid Chisnall struct initial_string<wstring, V, true>
4144bab9fd9SDavid Chisnall {
4154bab9fd9SDavid Chisnall     wstring
4164bab9fd9SDavid Chisnall     operator()() const
4174bab9fd9SDavid Chisnall     {
4184bab9fd9SDavid Chisnall         wstring s(20, wchar_t());
4194bab9fd9SDavid Chisnall         s.resize(s.capacity());
4204bab9fd9SDavid Chisnall         return s;
4214bab9fd9SDavid Chisnall     }
4224bab9fd9SDavid Chisnall };
4234bab9fd9SDavid Chisnall 
4244bab9fd9SDavid Chisnall typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
4254bab9fd9SDavid Chisnall 
4264bab9fd9SDavid Chisnall inline
4274bab9fd9SDavid Chisnall wide_printf
4284bab9fd9SDavid Chisnall get_swprintf()
4294bab9fd9SDavid Chisnall {
4304f7ab58eSDimitry Andric #ifndef _LIBCPP_MSVCRT
4314bab9fd9SDavid Chisnall     return swprintf;
4324bab9fd9SDavid Chisnall #else
4334bab9fd9SDavid Chisnall     return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
4344bab9fd9SDavid Chisnall #endif
4354bab9fd9SDavid Chisnall }
4364bab9fd9SDavid Chisnall 
4374bab9fd9SDavid Chisnall }  // unnamed namespace
4384bab9fd9SDavid Chisnall 
4394bab9fd9SDavid Chisnall string to_string(int val)
4404bab9fd9SDavid Chisnall {
4414bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, int>()(), "%d", val);
4424bab9fd9SDavid Chisnall }
4434bab9fd9SDavid Chisnall 
4444bab9fd9SDavid Chisnall string to_string(unsigned val)
4454bab9fd9SDavid Chisnall {
4464bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
4474bab9fd9SDavid Chisnall }
4484bab9fd9SDavid Chisnall 
4494bab9fd9SDavid Chisnall string to_string(long val)
4504bab9fd9SDavid Chisnall {
4514bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
4524bab9fd9SDavid Chisnall }
4534bab9fd9SDavid Chisnall 
4544bab9fd9SDavid Chisnall string to_string(unsigned long val)
4554bab9fd9SDavid Chisnall {
4564bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
4574bab9fd9SDavid Chisnall }
4584bab9fd9SDavid Chisnall 
4594bab9fd9SDavid Chisnall string to_string(long long val)
4604bab9fd9SDavid Chisnall {
4614bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
4624bab9fd9SDavid Chisnall }
4634bab9fd9SDavid Chisnall 
4644bab9fd9SDavid Chisnall string to_string(unsigned long long val)
4654bab9fd9SDavid Chisnall {
4664bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
4674bab9fd9SDavid Chisnall }
4684bab9fd9SDavid Chisnall 
4694bab9fd9SDavid Chisnall string to_string(float val)
4704bab9fd9SDavid Chisnall {
4714bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, float>()(), "%f", val);
4724bab9fd9SDavid Chisnall }
4734bab9fd9SDavid Chisnall 
4744bab9fd9SDavid Chisnall string to_string(double val)
4754bab9fd9SDavid Chisnall {
4764bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, double>()(), "%f", val);
4774bab9fd9SDavid Chisnall }
4784bab9fd9SDavid Chisnall 
4794bab9fd9SDavid Chisnall string to_string(long double val)
4804bab9fd9SDavid Chisnall {
4814bab9fd9SDavid Chisnall     return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
4824bab9fd9SDavid Chisnall }
4834bab9fd9SDavid Chisnall 
4844bab9fd9SDavid Chisnall wstring to_wstring(int val)
4854bab9fd9SDavid Chisnall {
4864bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
4874bab9fd9SDavid Chisnall }
4884bab9fd9SDavid Chisnall 
4894bab9fd9SDavid Chisnall wstring to_wstring(unsigned val)
4904bab9fd9SDavid Chisnall {
4914bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
4924bab9fd9SDavid Chisnall }
4934bab9fd9SDavid Chisnall 
4944bab9fd9SDavid Chisnall wstring to_wstring(long val)
4954bab9fd9SDavid Chisnall {
4964bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
4974bab9fd9SDavid Chisnall }
4984bab9fd9SDavid Chisnall 
4994bab9fd9SDavid Chisnall wstring to_wstring(unsigned long val)
5004bab9fd9SDavid Chisnall {
5014bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
5024bab9fd9SDavid Chisnall }
5034bab9fd9SDavid Chisnall 
5044bab9fd9SDavid Chisnall wstring to_wstring(long long val)
5054bab9fd9SDavid Chisnall {
5064bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
5074bab9fd9SDavid Chisnall }
5084bab9fd9SDavid Chisnall 
5094bab9fd9SDavid Chisnall wstring to_wstring(unsigned long long val)
5104bab9fd9SDavid Chisnall {
5114bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
5124bab9fd9SDavid Chisnall }
5137a984708SDavid Chisnall 
5147a984708SDavid Chisnall wstring to_wstring(float val)
5157a984708SDavid Chisnall {
5164bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
5177a984708SDavid Chisnall }
5187a984708SDavid Chisnall 
5197a984708SDavid Chisnall wstring to_wstring(double val)
5207a984708SDavid Chisnall {
5214bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
5227a984708SDavid Chisnall }
5237a984708SDavid Chisnall 
5247a984708SDavid Chisnall wstring to_wstring(long double val)
5257a984708SDavid Chisnall {
5264bab9fd9SDavid Chisnall     return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
5277a984708SDavid Chisnall }
5287a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD
529