//===------------------------- 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" #ifdef _LIBCPP_MSVCRT #include "support/win32/support.h" #endif // _LIBCPP_MSVCRT #include _LIBCPP_BEGIN_NAMESPACE_STD template class __basic_string_common; template class basic_string; template class basic_string; template string operator+, allocator >(char const*, string const&); namespace { template inline void throw_helper( const string& msg ) { #ifndef _LIBCPP_NO_EXCEPTIONS throw T( msg ); #else printf("%s\n", msg.c_str()); abort(); #endif } inline void throw_from_string_out_of_range( const string& func ) { throw_helper(func + ": out of range"); } inline void throw_from_string_invalid_arg( const string& func ) { throw_helper(func + ": no conversion"); } // as_integer template 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::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(ptr - p); return r; } template 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( func, s, idx, base, strtol ); if (r < numeric_limits::min() || numeric_limits::max() < r) throw_from_string_out_of_range(func); return static_cast(r); } template<> inline long as_integer(const string& func, const string& s, size_t* idx, int base ) { return as_integer_helper( 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( 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( 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( 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( func, s, idx, base, wcstol ); if (r < numeric_limits::min() || numeric_limits::max() < r) throw_from_string_out_of_range(func); return static_cast(r); } template<> inline long as_integer( const string& func, const wstring& s, size_t* idx, int base ) { return as_integer_helper( 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( 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( 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( func, s, idx, base, wcstoull ); } // as_float template 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::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(ptr - p); return r; } template 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( func, s, idx, strtof ); } template<> inline double as_float(const string& func, const string& s, size_t* idx ) { return as_float_helper( func, s, idx, strtod ); } template<> inline long double as_float( const string& func, const string& s, size_t* idx ) { return as_float_helper( func, s, idx, strtold ); } template<> inline float as_float( const string& func, const wstring& s, size_t* idx ) { return as_float_helper( func, s, idx, wcstof ); } template<> inline double as_float( const string& func, const wstring& s, size_t* idx ) { return as_float_helper( func, s, idx, wcstod ); } template<> inline long double as_float( const string& func, const wstring& s, size_t* idx ) { return as_float_helper( func, s, idx, wcstold ); } } // unnamed namespace int stoi(const string& str, size_t* idx, int base) { return as_integer( "stoi", str, idx, base ); } int stoi(const wstring& str, size_t* idx, int base) { return as_integer( "stoi", str, idx, base ); } long stol(const string& str, size_t* idx, int base) { return as_integer( "stol", str, idx, base ); } long stol(const wstring& str, size_t* idx, int base) { return as_integer( "stol", str, idx, base ); } unsigned long stoul(const string& str, size_t* idx, int base) { return as_integer( "stoul", str, idx, base ); } unsigned long stoul(const wstring& str, size_t* idx, int base) { return as_integer( "stoul", str, idx, base ); } long long stoll(const string& str, size_t* idx, int base) { return as_integer( "stoll", str, idx, base ); } long long stoll(const wstring& str, size_t* idx, int base) { return as_integer( "stoll", str, idx, base ); } unsigned long long stoull(const string& str, size_t* idx, int base) { return as_integer( "stoull", str, idx, base ); } unsigned long long stoull(const wstring& str, size_t* idx, int base) { return as_integer( "stoull", str, idx, base ); } float stof(const string& str, size_t* idx) { return as_float( "stof", str, idx ); } float stof(const wstring& str, size_t* idx) { return as_float( "stof", str, idx ); } double stod(const string& str, size_t* idx) { return as_float( "stod", str, idx ); } double stod(const wstring& str, size_t* idx) { return as_float( "stod", str, idx ); } long double stold(const string& str, size_t* idx) { return as_float( "stold", str, idx ); } long double stold(const wstring& str, size_t* idx) { return as_float( "stold", str, idx ); } // to_string namespace { // as_string template 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(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 ::value> struct initial_string; template struct initial_string { string operator()() const { string s; s.resize(s.capacity()); return s; } }; template struct initial_string { wstring operator()() const { const size_t n = (numeric_limits::digits / 3) + ((numeric_limits::digits % 3) != 0) + 1; wstring s(n, wchar_t()); s.resize(s.capacity()); return s; } }; template struct initial_string { 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(swprintf); #endif } } // unnamed namespace string to_string(int val) { return as_string(snprintf, initial_string()(), "%d", val); } string to_string(unsigned val) { return as_string(snprintf, initial_string()(), "%u", val); } string to_string(long val) { return as_string(snprintf, initial_string()(), "%ld", val); } string to_string(unsigned long val) { return as_string(snprintf, initial_string()(), "%lu", val); } string to_string(long long val) { return as_string(snprintf, initial_string()(), "%lld", val); } string to_string(unsigned long long val) { return as_string(snprintf, initial_string()(), "%llu", val); } string to_string(float val) { return as_string(snprintf, initial_string()(), "%f", val); } string to_string(double val) { return as_string(snprintf, initial_string()(), "%f", val); } string to_string(long double val) { return as_string(snprintf, initial_string()(), "%Lf", val); } wstring to_wstring(int val) { return as_string(get_swprintf(), initial_string()(), L"%d", val); } wstring to_wstring(unsigned val) { return as_string(get_swprintf(), initial_string()(), L"%u", val); } wstring to_wstring(long val) { return as_string(get_swprintf(), initial_string()(), L"%ld", val); } wstring to_wstring(unsigned long val) { return as_string(get_swprintf(), initial_string()(), L"%lu", val); } wstring to_wstring(long long val) { return as_string(get_swprintf(), initial_string()(), L"%lld", val); } wstring to_wstring(unsigned long long val) { return as_string(get_swprintf(), initial_string()(), L"%llu", val); } wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string()(), L"%f", val); } wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string()(), L"%f", val); } wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string()(), L"%Lf", val); } _LIBCPP_END_NAMESPACE_STD