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