Home | History | Annotate | Download | only in src
      1 //===------------------------- string.cpp ---------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "string"
     11 #include "cstdlib"
     12 #include "cwchar"
     13 #include "cerrno"
     14 #include "limits"
     15 #include "stdexcept"
     16 #ifdef _WIN32
     17 #include "support/win32/support.h"
     18 #endif // _WIN32
     19 
     20 _LIBCPP_BEGIN_NAMESPACE_STD
     21 
     22 template class __basic_string_common<true>;
     23 
     24 template class basic_string<char>;
     25 template class basic_string<wchar_t>;
     26 
     27 template
     28     string
     29     operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
     30 
     31 namespace
     32 {
     33 
     34 template<typename T>
     35 inline
     36 void throw_helper( const string& msg )
     37 {
     38 #ifndef _LIBCPP_NO_EXCEPTIONS
     39     throw T( msg );
     40 #else
     41     abort();
     42 #endif
     43 }
     44 
     45 inline
     46 void throw_from_string_out_of_range( const string& func )
     47 {
     48     throw_helper<out_of_range>(func + ": out of range");
     49 }
     50 
     51 inline
     52 void throw_from_string_invalid_arg( const string& func )
     53 {
     54     throw_helper<invalid_argument>(func + ": no conversion");
     55 }
     56 
     57 // as_integer
     58 
     59 template<typename V, typename S, typename F>
     60 inline
     61 V
     62 as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
     63 {
     64     typename S::value_type* ptr;
     65     const typename S::value_type* const p = str.c_str();
     66     typename remove_reference<decltype(errno)>::type errno_save = errno;
     67     errno = 0;
     68     V r = f(p, &ptr, base);
     69     swap(errno, errno_save);
     70     if (errno_save == ERANGE)
     71         throw_from_string_out_of_range(func);
     72     if (ptr == p)
     73         throw_from_string_invalid_arg(func);
     74     if (idx)
     75         *idx = static_cast<size_t>(ptr - p);
     76     return r;
     77 }
     78 
     79 template<typename V, typename S>
     80 inline
     81 V
     82 as_integer(const string& func, const S& s, size_t* idx, int base);
     83 
     84 // string
     85 template<>
     86 inline
     87 int
     88 as_integer(const string& func, const string& s, size_t* idx, int base )
     89 {
     90     // Use long as no Stantard string to integer exists.
     91     long r = as_integer_helper<long>( func, s, idx, base, strtol );
     92     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
     93         throw_from_string_out_of_range(func);
     94     return static_cast<int>(r);
     95 }
     96 
     97 template<>
     98 inline
     99 long
    100 as_integer(const string& func, const string& s, size_t* idx, int base )
    101 {
    102     return as_integer_helper<long>( func, s, idx, base, strtol );
    103 }
    104 
    105 template<>
    106 inline
    107 unsigned long
    108 as_integer( const string& func, const string& s, size_t* idx, int base )
    109 {
    110     return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
    111 }
    112 
    113 template<>
    114 inline
    115 long long
    116 as_integer( const string& func, const string& s, size_t* idx, int base )
    117 {
    118     return as_integer_helper<long long>( func, s, idx, base, strtoll );
    119 }
    120 
    121 template<>
    122 inline
    123 unsigned long long
    124 as_integer( const string& func, const string& s, size_t* idx, int base )
    125 {
    126     return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
    127 }
    128 
    129 // wstring
    130 template<>
    131 inline
    132 int
    133 as_integer( const string& func, const wstring& s, size_t* idx, int base )
    134 {
    135     // Use long as no Stantard string to integer exists.
    136     long r = as_integer_helper<long>( func, s, idx, base, wcstol );
    137     if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
    138         throw_from_string_out_of_range(func);
    139     return static_cast<int>(r);
    140 }
    141 
    142 template<>
    143 inline
    144 long
    145 as_integer( const string& func, const wstring& s, size_t* idx, int base )
    146 {
    147     return as_integer_helper<long>( func, s, idx, base, wcstol );
    148 }
    149 
    150 template<>
    151 inline
    152 unsigned long
    153 as_integer( const string& func, const wstring& s, size_t* idx, int base )
    154 {
    155     return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
    156 }
    157 
    158 template<>
    159 inline
    160 long long
    161 as_integer( const string& func, const wstring& s, size_t* idx, int base )
    162 {
    163     return as_integer_helper<long long>( func, s, idx, base, wcstoll );
    164 }
    165 
    166 template<>
    167 inline
    168 unsigned long long
    169 as_integer( const string& func, const wstring& s, size_t* idx, int base )
    170 {
    171     return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
    172 }
    173 
    174 // as_float
    175 
    176 template<typename V, typename S, typename F>
    177 inline
    178 V
    179 as_float_helper(const string& func, const S& str, size_t* idx, F f )
    180 {
    181     typename S::value_type* ptr;
    182     const typename S::value_type* const p = str.c_str();
    183     typename remove_reference<decltype(errno)>::type errno_save = errno;
    184     errno = 0;
    185     V r = f(p, &ptr);
    186     swap(errno, errno_save);
    187     if (errno_save == ERANGE)
    188         throw_from_string_out_of_range(func);
    189     if (ptr == p)
    190         throw_from_string_invalid_arg(func);
    191     if (idx)
    192         *idx = static_cast<size_t>(ptr - p);
    193     return r;
    194 }
    195 
    196 template<typename V, typename S>
    197 inline
    198 V as_float( const string& func, const S& s, size_t* idx = nullptr );
    199 
    200 template<>
    201 inline
    202 float
    203 as_float( const string& func, const string& s, size_t* idx )
    204 {
    205     return as_float_helper<float>( func, s, idx, strtof );
    206 }
    207 
    208 template<>
    209 inline
    210 double
    211 as_float(const string& func, const string& s, size_t* idx )
    212 {
    213     return as_float_helper<double>( func, s, idx, strtod );
    214 }
    215 
    216 template<>
    217 inline
    218 long double
    219 as_float( const string& func, const string& s, size_t* idx )
    220 {
    221     return as_float_helper<long double>( func, s, idx, strtold );
    222 }
    223 
    224 template<>
    225 inline
    226 float
    227 as_float( const string& func, const wstring& s, size_t* idx )
    228 {
    229     return as_float_helper<float>( func, s, idx, wcstof );
    230 }
    231 
    232 template<>
    233 inline
    234 double
    235 as_float( const string& func, const wstring& s, size_t* idx )
    236 {
    237     return as_float_helper<double>( func, s, idx, wcstod );
    238 }
    239 
    240 template<>
    241 inline
    242 long double
    243 as_float( const string& func, const wstring& s, size_t* idx )
    244 {
    245     return as_float_helper<long double>( func, s, idx, wcstold );
    246 }
    247 
    248 }  // unnamed namespace
    249 
    250 int
    251 stoi(const string& str, size_t* idx, int base)
    252 {
    253     return as_integer<int>( "stoi", str, idx, base );
    254 }
    255 
    256 int
    257 stoi(const wstring& str, size_t* idx, int base)
    258 {
    259     return as_integer<int>( "stoi", str, idx, base );
    260 }
    261 
    262 long
    263 stol(const string& str, size_t* idx, int base)
    264 {
    265     return as_integer<long>( "stol", str, idx, base );
    266 }
    267 
    268 long
    269 stol(const wstring& str, size_t* idx, int base)
    270 {
    271     return as_integer<long>( "stol", str, idx, base );
    272 }
    273 
    274 unsigned long
    275 stoul(const string& str, size_t* idx, int base)
    276 {
    277     return as_integer<unsigned long>( "stoul", str, idx, base );
    278 }
    279 
    280 unsigned long
    281 stoul(const wstring& str, size_t* idx, int base)
    282 {
    283     return as_integer<unsigned long>( "stoul", str, idx, base );
    284 }
    285 
    286 long long
    287 stoll(const string& str, size_t* idx, int base)
    288 {
    289     return as_integer<long long>( "stoll", str, idx, base );
    290 }
    291 
    292 long long
    293 stoll(const wstring& str, size_t* idx, int base)
    294 {
    295     return as_integer<long long>( "stoll", str, idx, base );
    296 }
    297 
    298 unsigned long long
    299 stoull(const string& str, size_t* idx, int base)
    300 {
    301     return as_integer<unsigned long long>( "stoull", str, idx, base );
    302 }
    303 
    304 unsigned long long
    305 stoull(const wstring& str, size_t* idx, int base)
    306 {
    307     return as_integer<unsigned long long>( "stoull", str, idx, base );
    308 }
    309 
    310 float
    311 stof(const string& str, size_t* idx)
    312 {
    313     return as_float<float>( "stof", str, idx );
    314 }
    315 
    316 float
    317 stof(const wstring& str, size_t* idx)
    318 {
    319     return as_float<float>( "stof", str, idx );
    320 }
    321 
    322 double
    323 stod(const string& str, size_t* idx)
    324 {
    325     return as_float<double>( "stod", str, idx );
    326 }
    327 
    328 double
    329 stod(const wstring& str, size_t* idx)
    330 {
    331     return as_float<double>( "stod", str, idx );
    332 }
    333 
    334 long double
    335 stold(const string& str, size_t* idx)
    336 {
    337     return as_float<long double>( "stold", str, idx );
    338 }
    339 
    340 long double
    341 stold(const wstring& str, size_t* idx)
    342 {
    343     return as_float<long double>( "stold", str, idx );
    344 }
    345 
    346 // to_string
    347 
    348 namespace
    349 {
    350 
    351 // as_string
    352 
    353 template<typename S, typename P, typename V >
    354 inline
    355 S
    356 as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
    357 {
    358     typedef typename S::size_type size_type;
    359     size_type available = s.size();
    360     while (true)
    361     {
    362         int status = sprintf_like(&s[0], available + 1, fmt, a);
    363         if ( status >= 0 )
    364         {
    365             size_type used = static_cast<size_type>(status);
    366             if ( used <= available )
    367             {
    368                 s.resize( used );
    369                 break;
    370             }
    371             available = used; // Assume this is advice of how much space we need.
    372         }
    373         else
    374             available = available * 2 + 1;
    375         s.resize(available);
    376     }
    377     return s;
    378 }
    379 
    380 template <class S, class V, bool = is_floating_point<V>::value>
    381 struct initial_string;
    382 
    383 template <class V, bool b>
    384 struct initial_string<string, V, b>
    385 {
    386     string
    387     operator()() const
    388     {
    389         string s;
    390         s.resize(s.capacity());
    391         return s;
    392     }
    393 };
    394 
    395 template <class V>
    396 struct initial_string<wstring, V, false>
    397 {
    398     wstring
    399     operator()() const
    400     {
    401         const size_t n = (numeric_limits<unsigned long long>::digits / 3)
    402           + ((numeric_limits<unsigned long long>::digits % 3) != 0)
    403           + 1;
    404         wstring s(n, wchar_t());
    405         s.resize(s.capacity());
    406         return s;
    407     }
    408 };
    409 
    410 template <class V>
    411 struct initial_string<wstring, V, true>
    412 {
    413     wstring
    414     operator()() const
    415     {
    416         wstring s(20, wchar_t());
    417         s.resize(s.capacity());
    418         return s;
    419     }
    420 };
    421 
    422 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
    423 
    424 inline
    425 wide_printf
    426 get_swprintf()
    427 {
    428 #ifndef _WIN32
    429     return swprintf;
    430 #else
    431     return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
    432 #endif
    433 }
    434 
    435 }  // unnamed namespace
    436 
    437 string to_string(int val)
    438 {
    439     return as_string(snprintf, initial_string<string, int>()(), "%d", val);
    440 }
    441 
    442 string to_string(unsigned val)
    443 {
    444     return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
    445 }
    446 
    447 string to_string(long val)
    448 {
    449     return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
    450 }
    451 
    452 string to_string(unsigned long val)
    453 {
    454     return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
    455 }
    456 
    457 string to_string(long long val)
    458 {
    459     return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
    460 }
    461 
    462 string to_string(unsigned long long val)
    463 {
    464     return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
    465 }
    466 
    467 string to_string(float val)
    468 {
    469     return as_string(snprintf, initial_string<string, float>()(), "%f", val);
    470 }
    471 
    472 string to_string(double val)
    473 {
    474     return as_string(snprintf, initial_string<string, double>()(), "%f", val);
    475 }
    476 
    477 string to_string(long double val)
    478 {
    479     return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
    480 }
    481 
    482 wstring to_wstring(int val)
    483 {
    484     return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
    485 }
    486 
    487 wstring to_wstring(unsigned val)
    488 {
    489     return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
    490 }
    491 
    492 wstring to_wstring(long val)
    493 {
    494     return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
    495 }
    496 
    497 wstring to_wstring(unsigned long val)
    498 {
    499     return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
    500 }
    501 
    502 wstring to_wstring(long long val)
    503 {
    504     return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
    505 }
    506 
    507 wstring to_wstring(unsigned long long val)
    508 {
    509     return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
    510 }
    511 
    512 wstring to_wstring(float val)
    513 {
    514     return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
    515 }
    516 
    517 wstring to_wstring(double val)
    518 {
    519     return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
    520 }
    521 
    522 wstring to_wstring(long double val)
    523 {
    524     return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
    525 }
    526 _LIBCPP_END_NAMESPACE_STD
    527