|  | //===------------------------- string.cpp ---------------------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is dual licensed under the MIT and the University of Illinois Open | 
|  | // Source Licenses. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "string" | 
|  | #include "cstdlib" | 
|  | #include "cwchar" | 
|  | #include "cerrno" | 
|  | #include "limits" | 
|  | #include "stdexcept" | 
|  | #include <stdio.h> | 
|  |  | 
|  | _LIBCPP_BEGIN_NAMESPACE_STD | 
|  |  | 
|  | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; | 
|  |  | 
|  | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; | 
|  | template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>; | 
|  |  | 
|  | template | 
|  | string | 
|  | operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); | 
|  |  | 
|  | namespace | 
|  | { | 
|  |  | 
|  | template<typename T> | 
|  | inline | 
|  | void throw_helper( const string& msg ) | 
|  | { | 
|  | #ifndef _LIBCPP_NO_EXCEPTIONS | 
|  | throw T( msg ); | 
|  | #else | 
|  | fprintf(stderr, "%s\n", msg.c_str()); | 
|  | _VSTD::abort(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | inline | 
|  | void throw_from_string_out_of_range( const string& func ) | 
|  | { | 
|  | throw_helper<out_of_range>(func + ": out of range"); | 
|  | } | 
|  |  | 
|  | inline | 
|  | void throw_from_string_invalid_arg( const string& func ) | 
|  | { | 
|  | throw_helper<invalid_argument>(func + ": no conversion"); | 
|  | } | 
|  |  | 
|  | // as_integer | 
|  |  | 
|  | template<typename V, typename S, typename F> | 
|  | inline | 
|  | V | 
|  | as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) | 
|  | { | 
|  | typename S::value_type* ptr = nullptr; | 
|  | const typename S::value_type* const p = str.c_str(); | 
|  | typename remove_reference<decltype(errno)>::type errno_save = errno; | 
|  | errno = 0; | 
|  | V r = f(p, &ptr, base); | 
|  | swap(errno, errno_save); | 
|  | if (errno_save == ERANGE) | 
|  | throw_from_string_out_of_range(func); | 
|  | if (ptr == p) | 
|  | throw_from_string_invalid_arg(func); | 
|  | if (idx) | 
|  | *idx = static_cast<size_t>(ptr - p); | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename V, typename S> | 
|  | inline | 
|  | V | 
|  | as_integer(const string& func, const S& s, size_t* idx, int base); | 
|  |  | 
|  | // string | 
|  | template<> | 
|  | inline | 
|  | int | 
|  | as_integer(const string& func, const string& s, size_t* idx, int base ) | 
|  | { | 
|  | // Use long as no Standard string to integer exists. | 
|  | long r = as_integer_helper<long>( func, s, idx, base, strtol ); | 
|  | if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) | 
|  | throw_from_string_out_of_range(func); | 
|  | return static_cast<int>(r); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | long | 
|  | as_integer(const string& func, const string& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<long>( func, s, idx, base, strtol ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | unsigned long | 
|  | as_integer( const string& func, const string& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | long long | 
|  | as_integer( const string& func, const string& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<long long>( func, s, idx, base, strtoll ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | unsigned long long | 
|  | as_integer( const string& func, const string& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); | 
|  | } | 
|  |  | 
|  | // wstring | 
|  | template<> | 
|  | inline | 
|  | int | 
|  | as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 
|  | { | 
|  | // Use long as no Stantard string to integer exists. | 
|  | long r = as_integer_helper<long>( func, s, idx, base, wcstol ); | 
|  | if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) | 
|  | throw_from_string_out_of_range(func); | 
|  | return static_cast<int>(r); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | long | 
|  | as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<long>( func, s, idx, base, wcstol ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | unsigned long | 
|  | as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | long long | 
|  | as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<long long>( func, s, idx, base, wcstoll ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | unsigned long long | 
|  | as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 
|  | { | 
|  | return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); | 
|  | } | 
|  |  | 
|  | // as_float | 
|  |  | 
|  | template<typename V, typename S, typename F> | 
|  | inline | 
|  | V | 
|  | as_float_helper(const string& func, const S& str, size_t* idx, F f ) | 
|  | { | 
|  | typename S::value_type* ptr = nullptr; | 
|  | const typename S::value_type* const p = str.c_str(); | 
|  | typename remove_reference<decltype(errno)>::type errno_save = errno; | 
|  | errno = 0; | 
|  | V r = f(p, &ptr); | 
|  | swap(errno, errno_save); | 
|  | if (errno_save == ERANGE) | 
|  | throw_from_string_out_of_range(func); | 
|  | if (ptr == p) | 
|  | throw_from_string_invalid_arg(func); | 
|  | if (idx) | 
|  | *idx = static_cast<size_t>(ptr - p); | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename V, typename S> | 
|  | inline | 
|  | V as_float( const string& func, const S& s, size_t* idx = nullptr ); | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | float | 
|  | as_float( const string& func, const string& s, size_t* idx ) | 
|  | { | 
|  | return as_float_helper<float>( func, s, idx, strtof ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | double | 
|  | as_float(const string& func, const string& s, size_t* idx ) | 
|  | { | 
|  | return as_float_helper<double>( func, s, idx, strtod ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | long double | 
|  | as_float( const string& func, const string& s, size_t* idx ) | 
|  | { | 
|  | return as_float_helper<long double>( func, s, idx, strtold ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | float | 
|  | as_float( const string& func, const wstring& s, size_t* idx ) | 
|  | { | 
|  | return as_float_helper<float>( func, s, idx, wcstof ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | double | 
|  | as_float( const string& func, const wstring& s, size_t* idx ) | 
|  | { | 
|  | return as_float_helper<double>( func, s, idx, wcstod ); | 
|  | } | 
|  |  | 
|  | template<> | 
|  | inline | 
|  | long double | 
|  | as_float( const string& func, const wstring& s, size_t* idx ) | 
|  | { | 
|  | return as_float_helper<long double>( func, s, idx, wcstold ); | 
|  | } | 
|  |  | 
|  | }  // unnamed namespace | 
|  |  | 
|  | int | 
|  | stoi(const string& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<int>( "stoi", str, idx, base ); | 
|  | } | 
|  |  | 
|  | int | 
|  | stoi(const wstring& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<int>( "stoi", str, idx, base ); | 
|  | } | 
|  |  | 
|  | long | 
|  | stol(const string& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<long>( "stol", str, idx, base ); | 
|  | } | 
|  |  | 
|  | long | 
|  | stol(const wstring& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<long>( "stol", str, idx, base ); | 
|  | } | 
|  |  | 
|  | unsigned long | 
|  | stoul(const string& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<unsigned long>( "stoul", str, idx, base ); | 
|  | } | 
|  |  | 
|  | unsigned long | 
|  | stoul(const wstring& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<unsigned long>( "stoul", str, idx, base ); | 
|  | } | 
|  |  | 
|  | long long | 
|  | stoll(const string& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<long long>( "stoll", str, idx, base ); | 
|  | } | 
|  |  | 
|  | long long | 
|  | stoll(const wstring& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<long long>( "stoll", str, idx, base ); | 
|  | } | 
|  |  | 
|  | unsigned long long | 
|  | stoull(const string& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<unsigned long long>( "stoull", str, idx, base ); | 
|  | } | 
|  |  | 
|  | unsigned long long | 
|  | stoull(const wstring& str, size_t* idx, int base) | 
|  | { | 
|  | return as_integer<unsigned long long>( "stoull", str, idx, base ); | 
|  | } | 
|  |  | 
|  | float | 
|  | stof(const string& str, size_t* idx) | 
|  | { | 
|  | return as_float<float>( "stof", str, idx ); | 
|  | } | 
|  |  | 
|  | float | 
|  | stof(const wstring& str, size_t* idx) | 
|  | { | 
|  | return as_float<float>( "stof", str, idx ); | 
|  | } | 
|  |  | 
|  | double | 
|  | stod(const string& str, size_t* idx) | 
|  | { | 
|  | return as_float<double>( "stod", str, idx ); | 
|  | } | 
|  |  | 
|  | double | 
|  | stod(const wstring& str, size_t* idx) | 
|  | { | 
|  | return as_float<double>( "stod", str, idx ); | 
|  | } | 
|  |  | 
|  | long double | 
|  | stold(const string& str, size_t* idx) | 
|  | { | 
|  | return as_float<long double>( "stold", str, idx ); | 
|  | } | 
|  |  | 
|  | long double | 
|  | stold(const wstring& str, size_t* idx) | 
|  | { | 
|  | return as_float<long double>( "stold", str, idx ); | 
|  | } | 
|  |  | 
|  | // to_string | 
|  |  | 
|  | namespace | 
|  | { | 
|  |  | 
|  | // as_string | 
|  |  | 
|  | template<typename S, typename P, typename V > | 
|  | inline | 
|  | S | 
|  | as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) | 
|  | { | 
|  | typedef typename S::size_type size_type; | 
|  | size_type available = s.size(); | 
|  | while (true) | 
|  | { | 
|  | int status = sprintf_like(&s[0], available + 1, fmt, a); | 
|  | if ( status >= 0 ) | 
|  | { | 
|  | size_type used = static_cast<size_type>(status); | 
|  | if ( used <= available ) | 
|  | { | 
|  | s.resize( used ); | 
|  | break; | 
|  | } | 
|  | available = used; // Assume this is advice of how much space we need. | 
|  | } | 
|  | else | 
|  | available = available * 2 + 1; | 
|  | s.resize(available); | 
|  | } | 
|  | return s; | 
|  | } | 
|  |  | 
|  | template <class S, class V, bool = is_floating_point<V>::value> | 
|  | struct initial_string; | 
|  |  | 
|  | template <class V, bool b> | 
|  | struct initial_string<string, V, b> | 
|  | { | 
|  | string | 
|  | operator()() const | 
|  | { | 
|  | string s; | 
|  | s.resize(s.capacity()); | 
|  | return s; | 
|  | } | 
|  | }; | 
|  |  | 
|  | 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> | 
|  | { | 
|  | wstring | 
|  | operator()() const | 
|  | { | 
|  | wstring s(20, wchar_t()); | 
|  | s.resize(s.capacity()); | 
|  | return s; | 
|  | } | 
|  | }; | 
|  |  | 
|  | typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); | 
|  |  | 
|  | inline | 
|  | wide_printf | 
|  | get_swprintf() | 
|  | { | 
|  | #ifndef _LIBCPP_MSVCRT | 
|  | return swprintf; | 
|  | #else | 
|  | return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | }  // unnamed namespace | 
|  |  | 
|  | string to_string(int val) | 
|  | { | 
|  | return as_string(snprintf, initial_string<string, int>()(), "%d", val); | 
|  | } | 
|  |  | 
|  | string to_string(unsigned val) | 
|  | { | 
|  | return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val); | 
|  | } | 
|  |  | 
|  | 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); | 
|  | } | 
|  |  | 
|  | wstring to_wstring(unsigned long val) | 
|  | { | 
|  | return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val); | 
|  | } | 
|  |  | 
|  | wstring to_wstring(long long val) | 
|  | { | 
|  | return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", 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); | 
|  | } | 
|  |  | 
|  | wstring to_wstring(double val) | 
|  | { | 
|  | return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val); | 
|  | } | 
|  |  | 
|  | wstring to_wstring(long double val) | 
|  | { | 
|  | return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val); | 
|  | } | 
|  | _LIBCPP_END_NAMESPACE_STD |