14ba319b5SDimitry Andric// -*- C++ -*- 24ba319b5SDimitry Andric//===------------------------------ charconv ------------------------------===// 34ba319b5SDimitry Andric// 44ba319b5SDimitry Andric// The LLVM Compiler Infrastructure 54ba319b5SDimitry Andric// 64ba319b5SDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open 74ba319b5SDimitry Andric// Source Licenses. See LICENSE.TXT for details. 84ba319b5SDimitry Andric// 94ba319b5SDimitry Andric//===----------------------------------------------------------------------===// 104ba319b5SDimitry Andric 114ba319b5SDimitry Andric#ifndef _LIBCPP_CHARCONV 124ba319b5SDimitry Andric#define _LIBCPP_CHARCONV 134ba319b5SDimitry Andric 144ba319b5SDimitry Andric/* 154ba319b5SDimitry Andric charconv synopsis 164ba319b5SDimitry Andric 174ba319b5SDimitry Andricnamespace std { 184ba319b5SDimitry Andric 194ba319b5SDimitry Andric // floating-point format for primitive numerical conversion 204ba319b5SDimitry Andric enum class chars_format { 214ba319b5SDimitry Andric scientific = unspecified, 224ba319b5SDimitry Andric fixed = unspecified, 234ba319b5SDimitry Andric hex = unspecified, 244ba319b5SDimitry Andric general = fixed | scientific 254ba319b5SDimitry Andric }; 264ba319b5SDimitry Andric 274ba319b5SDimitry Andric // 23.20.2, primitive numerical output conversion 284ba319b5SDimitry Andric struct to_chars_result { 294ba319b5SDimitry Andric char* ptr; 304ba319b5SDimitry Andric errc ec; 314ba319b5SDimitry Andric }; 324ba319b5SDimitry Andric 334ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, see below value, 344ba319b5SDimitry Andric int base = 10); 354ba319b5SDimitry Andric 364ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, float value); 374ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, double value); 384ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, long double value); 394ba319b5SDimitry Andric 404ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, float value, 414ba319b5SDimitry Andric chars_format fmt); 424ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, double value, 434ba319b5SDimitry Andric chars_format fmt); 444ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, long double value, 454ba319b5SDimitry Andric chars_format fmt); 464ba319b5SDimitry Andric 474ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, float value, 484ba319b5SDimitry Andric chars_format fmt, int precision); 494ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, double value, 504ba319b5SDimitry Andric chars_format fmt, int precision); 514ba319b5SDimitry Andric to_chars_result to_chars(char* first, char* last, long double value, 524ba319b5SDimitry Andric chars_format fmt, int precision); 534ba319b5SDimitry Andric 544ba319b5SDimitry Andric // 23.20.3, primitive numerical input conversion 554ba319b5SDimitry Andric struct from_chars_result { 564ba319b5SDimitry Andric const char* ptr; 574ba319b5SDimitry Andric errc ec; 584ba319b5SDimitry Andric }; 594ba319b5SDimitry Andric 604ba319b5SDimitry Andric from_chars_result from_chars(const char* first, const char* last, 614ba319b5SDimitry Andric see below& value, int base = 10); 624ba319b5SDimitry Andric 634ba319b5SDimitry Andric from_chars_result from_chars(const char* first, const char* last, 644ba319b5SDimitry Andric float& value, 654ba319b5SDimitry Andric chars_format fmt = chars_format::general); 664ba319b5SDimitry Andric from_chars_result from_chars(const char* first, const char* last, 674ba319b5SDimitry Andric double& value, 684ba319b5SDimitry Andric chars_format fmt = chars_format::general); 694ba319b5SDimitry Andric from_chars_result from_chars(const char* first, const char* last, 704ba319b5SDimitry Andric long double& value, 714ba319b5SDimitry Andric chars_format fmt = chars_format::general); 724ba319b5SDimitry Andric 734ba319b5SDimitry Andric} // namespace std 744ba319b5SDimitry Andric 754ba319b5SDimitry Andric*/ 764ba319b5SDimitry Andric 774ba319b5SDimitry Andric#include <__errc> 784ba319b5SDimitry Andric#include <type_traits> 794ba319b5SDimitry Andric#include <limits> 804ba319b5SDimitry Andric#include <stdint.h> 814ba319b5SDimitry Andric#include <string.h> 824ba319b5SDimitry Andric#include <math.h> 834ba319b5SDimitry Andric 844ba319b5SDimitry Andric#include <__debug> 854ba319b5SDimitry Andric 864ba319b5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 874ba319b5SDimitry Andric#pragma GCC system_header 884ba319b5SDimitry Andric#endif 894ba319b5SDimitry Andric 90*b5893f02SDimitry Andric_LIBCPP_PUSH_MACROS 91*b5893f02SDimitry Andric#include <__undef_macros> 92*b5893f02SDimitry Andric 934ba319b5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 944ba319b5SDimitry Andric 95*b5893f02SDimitry Andricnamespace __itoa { 96*b5893f02SDimitry Andric_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer); 97*b5893f02SDimitry Andric_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer); 98*b5893f02SDimitry Andric} 99*b5893f02SDimitry Andric 1004ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 11 1014ba319b5SDimitry Andric 1024ba319b5SDimitry Andricenum class _LIBCPP_ENUM_VIS chars_format 1034ba319b5SDimitry Andric{ 1044ba319b5SDimitry Andric scientific = 0x1, 1054ba319b5SDimitry Andric fixed = 0x2, 1064ba319b5SDimitry Andric hex = 0x4, 1074ba319b5SDimitry Andric general = fixed | scientific 1084ba319b5SDimitry Andric}; 1094ba319b5SDimitry Andric 1104ba319b5SDimitry Andricstruct _LIBCPP_TYPE_VIS to_chars_result 1114ba319b5SDimitry Andric{ 1124ba319b5SDimitry Andric char* ptr; 1134ba319b5SDimitry Andric errc ec; 1144ba319b5SDimitry Andric}; 1154ba319b5SDimitry Andric 1164ba319b5SDimitry Andricstruct _LIBCPP_TYPE_VIS from_chars_result 1174ba319b5SDimitry Andric{ 1184ba319b5SDimitry Andric const char* ptr; 1194ba319b5SDimitry Andric errc ec; 1204ba319b5SDimitry Andric}; 1214ba319b5SDimitry Andric 1224ba319b5SDimitry Andricvoid to_chars(char*, char*, bool, int = 10) = delete; 1234ba319b5SDimitry Andricvoid from_chars(const char*, const char*, bool, int = 10) = delete; 1244ba319b5SDimitry Andric 1254ba319b5SDimitry Andricnamespace __itoa 1264ba319b5SDimitry Andric{ 1274ba319b5SDimitry Andric 1284ba319b5SDimitry Andricstatic constexpr uint64_t __pow10_64[] = { 1294ba319b5SDimitry Andric UINT64_C(0), 1304ba319b5SDimitry Andric UINT64_C(10), 1314ba319b5SDimitry Andric UINT64_C(100), 1324ba319b5SDimitry Andric UINT64_C(1000), 1334ba319b5SDimitry Andric UINT64_C(10000), 1344ba319b5SDimitry Andric UINT64_C(100000), 1354ba319b5SDimitry Andric UINT64_C(1000000), 1364ba319b5SDimitry Andric UINT64_C(10000000), 1374ba319b5SDimitry Andric UINT64_C(100000000), 1384ba319b5SDimitry Andric UINT64_C(1000000000), 1394ba319b5SDimitry Andric UINT64_C(10000000000), 1404ba319b5SDimitry Andric UINT64_C(100000000000), 1414ba319b5SDimitry Andric UINT64_C(1000000000000), 1424ba319b5SDimitry Andric UINT64_C(10000000000000), 1434ba319b5SDimitry Andric UINT64_C(100000000000000), 1444ba319b5SDimitry Andric UINT64_C(1000000000000000), 1454ba319b5SDimitry Andric UINT64_C(10000000000000000), 1464ba319b5SDimitry Andric UINT64_C(100000000000000000), 1474ba319b5SDimitry Andric UINT64_C(1000000000000000000), 1484ba319b5SDimitry Andric UINT64_C(10000000000000000000), 1494ba319b5SDimitry Andric}; 1504ba319b5SDimitry Andric 1514ba319b5SDimitry Andricstatic constexpr uint32_t __pow10_32[] = { 1524ba319b5SDimitry Andric UINT32_C(0), UINT32_C(10), UINT32_C(100), 1534ba319b5SDimitry Andric UINT32_C(1000), UINT32_C(10000), UINT32_C(100000), 1544ba319b5SDimitry Andric UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000), 1554ba319b5SDimitry Andric UINT32_C(1000000000), 1564ba319b5SDimitry Andric}; 1574ba319b5SDimitry Andric 1584ba319b5SDimitry Andrictemplate <typename _Tp, typename = void> 1594ba319b5SDimitry Andricstruct _LIBCPP_HIDDEN __traits_base 1604ba319b5SDimitry Andric{ 1614ba319b5SDimitry Andric using type = uint64_t; 1624ba319b5SDimitry Andric 1634ba319b5SDimitry Andric#if !defined(_LIBCPP_COMPILER_MSVC) 1644ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY int __width(_Tp __v) 1654ba319b5SDimitry Andric { 1664ba319b5SDimitry Andric auto __t = (64 - __builtin_clzll(__v | 1)) * 1233 >> 12; 1674ba319b5SDimitry Andric return __t - (__v < __pow10_64[__t]) + 1; 1684ba319b5SDimitry Andric } 1694ba319b5SDimitry Andric#endif 1704ba319b5SDimitry Andric 1714ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p) 1724ba319b5SDimitry Andric { 1734ba319b5SDimitry Andric return __u64toa(__v, __p); 1744ba319b5SDimitry Andric } 1754ba319b5SDimitry Andric 1764ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY auto& __pow() { return __pow10_64; } 1774ba319b5SDimitry Andric}; 1784ba319b5SDimitry Andric 1794ba319b5SDimitry Andrictemplate <typename _Tp> 1804ba319b5SDimitry Andricstruct _LIBCPP_HIDDEN 1814ba319b5SDimitry Andric __traits_base<_Tp, decltype(void(uint32_t{declval<_Tp>()}))> 1824ba319b5SDimitry Andric{ 1834ba319b5SDimitry Andric using type = uint32_t; 1844ba319b5SDimitry Andric 1854ba319b5SDimitry Andric#if !defined(_LIBCPP_COMPILER_MSVC) 1864ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY int __width(_Tp __v) 1874ba319b5SDimitry Andric { 1884ba319b5SDimitry Andric auto __t = (32 - __builtin_clz(__v | 1)) * 1233 >> 12; 1894ba319b5SDimitry Andric return __t - (__v < __pow10_32[__t]) + 1; 1904ba319b5SDimitry Andric } 1914ba319b5SDimitry Andric#endif 1924ba319b5SDimitry Andric 1934ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p) 1944ba319b5SDimitry Andric { 1954ba319b5SDimitry Andric return __u32toa(__v, __p); 1964ba319b5SDimitry Andric } 1974ba319b5SDimitry Andric 1984ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY auto& __pow() { return __pow10_32; } 1994ba319b5SDimitry Andric}; 2004ba319b5SDimitry Andric 2014ba319b5SDimitry Andrictemplate <typename _Tp> 2024ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY bool 2034ba319b5SDimitry Andric__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) 2044ba319b5SDimitry Andric{ 2054ba319b5SDimitry Andric auto __c = __a * __b; 2064ba319b5SDimitry Andric __r = __c; 2074ba319b5SDimitry Andric return __c > (numeric_limits<unsigned char>::max)(); 2084ba319b5SDimitry Andric} 2094ba319b5SDimitry Andric 2104ba319b5SDimitry Andrictemplate <typename _Tp> 2114ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY bool 2124ba319b5SDimitry Andric__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) 2134ba319b5SDimitry Andric{ 2144ba319b5SDimitry Andric auto __c = __a * __b; 2154ba319b5SDimitry Andric __r = __c; 2164ba319b5SDimitry Andric return __c > (numeric_limits<unsigned short>::max)(); 2174ba319b5SDimitry Andric} 2184ba319b5SDimitry Andric 2194ba319b5SDimitry Andrictemplate <typename _Tp> 2204ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY bool 2214ba319b5SDimitry Andric__mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) 2224ba319b5SDimitry Andric{ 2234ba319b5SDimitry Andric static_assert(is_unsigned<_Tp>::value, ""); 2244ba319b5SDimitry Andric#if !defined(_LIBCPP_COMPILER_MSVC) 2254ba319b5SDimitry Andric return __builtin_mul_overflow(__a, __b, &__r); 2264ba319b5SDimitry Andric#else 2274ba319b5SDimitry Andric bool __did = __b && ((numeric_limits<_Tp>::max)() / __b) < __a; 2284ba319b5SDimitry Andric __r = __a * __b; 2294ba319b5SDimitry Andric return __did; 2304ba319b5SDimitry Andric#endif 2314ba319b5SDimitry Andric} 2324ba319b5SDimitry Andric 2334ba319b5SDimitry Andrictemplate <typename _Tp, typename _Up> 2344ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY bool 2354ba319b5SDimitry Andric__mul_overflowed(_Tp __a, _Up __b, _Tp& __r) 2364ba319b5SDimitry Andric{ 2374ba319b5SDimitry Andric return __mul_overflowed(__a, static_cast<_Tp>(__b), __r); 2384ba319b5SDimitry Andric} 2394ba319b5SDimitry Andric 2404ba319b5SDimitry Andrictemplate <typename _Tp> 2414ba319b5SDimitry Andricstruct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> 2424ba319b5SDimitry Andric{ 2434ba319b5SDimitry Andric static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; 2444ba319b5SDimitry Andric using __traits_base<_Tp>::__pow; 2454ba319b5SDimitry Andric using typename __traits_base<_Tp>::type; 2464ba319b5SDimitry Andric 2474ba319b5SDimitry Andric // precondition: at least one non-zero character available 2484ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY char const* 2494ba319b5SDimitry Andric __read(char const* __p, char const* __ep, type& __a, type& __b) 2504ba319b5SDimitry Andric { 2514ba319b5SDimitry Andric type __cprod[digits]; 2524ba319b5SDimitry Andric int __j = digits - 1; 2534ba319b5SDimitry Andric int __i = digits; 2544ba319b5SDimitry Andric do 2554ba319b5SDimitry Andric { 2564ba319b5SDimitry Andric if (!('0' <= *__p && *__p <= '9')) 2574ba319b5SDimitry Andric break; 2584ba319b5SDimitry Andric __cprod[--__i] = *__p++ - '0'; 2594ba319b5SDimitry Andric } while (__p != __ep && __i != 0); 2604ba319b5SDimitry Andric 2614ba319b5SDimitry Andric __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, 2624ba319b5SDimitry Andric __cprod[__i]); 2634ba319b5SDimitry Andric if (__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) 2644ba319b5SDimitry Andric --__p; 2654ba319b5SDimitry Andric return __p; 2664ba319b5SDimitry Andric } 2674ba319b5SDimitry Andric 2684ba319b5SDimitry Andric template <typename _It1, typename _It2, class _Up> 2694ba319b5SDimitry Andric static _LIBCPP_INLINE_VISIBILITY _Up 2704ba319b5SDimitry Andric __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init) 2714ba319b5SDimitry Andric { 2724ba319b5SDimitry Andric for (; __first1 < __last1; ++__first1, ++__first2) 2734ba319b5SDimitry Andric __init = __init + *__first1 * *__first2; 2744ba319b5SDimitry Andric return __init; 2754ba319b5SDimitry Andric } 2764ba319b5SDimitry Andric}; 2774ba319b5SDimitry Andric 2784ba319b5SDimitry Andric} // namespace __itoa 2794ba319b5SDimitry Andric 2804ba319b5SDimitry Andrictemplate <typename _Tp> 2814ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY _Tp 2824ba319b5SDimitry Andric__complement(_Tp __x) 2834ba319b5SDimitry Andric{ 2844ba319b5SDimitry Andric static_assert(is_unsigned<_Tp>::value, "cast to unsigned first"); 2854ba319b5SDimitry Andric return _Tp(~__x + 1); 2864ba319b5SDimitry Andric} 2874ba319b5SDimitry Andric 2884ba319b5SDimitry Andrictemplate <typename _Tp> 2894ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY auto 2904ba319b5SDimitry Andric__to_unsigned(_Tp __x) 2914ba319b5SDimitry Andric{ 2924ba319b5SDimitry Andric return static_cast<make_unsigned_t<_Tp>>(__x); 2934ba319b5SDimitry Andric} 2944ba319b5SDimitry Andric 2954ba319b5SDimitry Andrictemplate <typename _Tp> 2964ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY to_chars_result 2974ba319b5SDimitry Andric__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) 2984ba319b5SDimitry Andric{ 2994ba319b5SDimitry Andric auto __x = __to_unsigned(__value); 3004ba319b5SDimitry Andric if (__value < 0 && __first != __last) 3014ba319b5SDimitry Andric { 3024ba319b5SDimitry Andric *__first++ = '-'; 3034ba319b5SDimitry Andric __x = __complement(__x); 3044ba319b5SDimitry Andric } 3054ba319b5SDimitry Andric 3064ba319b5SDimitry Andric return __to_chars_itoa(__first, __last, __x, false_type()); 3074ba319b5SDimitry Andric} 3084ba319b5SDimitry Andric 3094ba319b5SDimitry Andrictemplate <typename _Tp> 3104ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY to_chars_result 3114ba319b5SDimitry Andric__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) 3124ba319b5SDimitry Andric{ 3134ba319b5SDimitry Andric using __tx = __itoa::__traits<_Tp>; 3144ba319b5SDimitry Andric auto __diff = __last - __first; 3154ba319b5SDimitry Andric 3164ba319b5SDimitry Andric#if !defined(_LIBCPP_COMPILER_MSVC) 3174ba319b5SDimitry Andric if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) 3184ba319b5SDimitry Andric return {__tx::__convert(__value, __first), {}}; 3194ba319b5SDimitry Andric else 3204ba319b5SDimitry Andric return {__last, errc::value_too_large}; 3214ba319b5SDimitry Andric#else 3224ba319b5SDimitry Andric if (__tx::digits <= __diff) 3234ba319b5SDimitry Andric return {__tx::__convert(__value, __first), {}}; 3244ba319b5SDimitry Andric else 3254ba319b5SDimitry Andric { 3264ba319b5SDimitry Andric char __buf[__tx::digits]; 3274ba319b5SDimitry Andric auto __p = __tx::__convert(__value, __buf); 3284ba319b5SDimitry Andric auto __len = __p - __buf; 3294ba319b5SDimitry Andric if (__len <= __diff) 3304ba319b5SDimitry Andric { 3314ba319b5SDimitry Andric memcpy(__first, __buf, __len); 3324ba319b5SDimitry Andric return {__first + __len, {}}; 3334ba319b5SDimitry Andric } 3344ba319b5SDimitry Andric else 3354ba319b5SDimitry Andric return {__last, errc::value_too_large}; 3364ba319b5SDimitry Andric } 3374ba319b5SDimitry Andric#endif 3384ba319b5SDimitry Andric} 3394ba319b5SDimitry Andric 3404ba319b5SDimitry Andrictemplate <typename _Tp> 3414ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY to_chars_result 3424ba319b5SDimitry Andric__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, 3434ba319b5SDimitry Andric true_type) 3444ba319b5SDimitry Andric{ 3454ba319b5SDimitry Andric auto __x = __to_unsigned(__value); 3464ba319b5SDimitry Andric if (__value < 0 && __first != __last) 3474ba319b5SDimitry Andric { 3484ba319b5SDimitry Andric *__first++ = '-'; 3494ba319b5SDimitry Andric __x = __complement(__x); 3504ba319b5SDimitry Andric } 3514ba319b5SDimitry Andric 3524ba319b5SDimitry Andric return __to_chars_integral(__first, __last, __x, __base, false_type()); 3534ba319b5SDimitry Andric} 3544ba319b5SDimitry Andric 3554ba319b5SDimitry Andrictemplate <typename _Tp> 3564ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY to_chars_result 3574ba319b5SDimitry Andric__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, 3584ba319b5SDimitry Andric false_type) 3594ba319b5SDimitry Andric{ 3604ba319b5SDimitry Andric if (__base == 10) 3614ba319b5SDimitry Andric return __to_chars_itoa(__first, __last, __value, false_type()); 3624ba319b5SDimitry Andric 3634ba319b5SDimitry Andric auto __p = __last; 3644ba319b5SDimitry Andric while (__p != __first) 3654ba319b5SDimitry Andric { 3664ba319b5SDimitry Andric auto __c = __value % __base; 3674ba319b5SDimitry Andric __value /= __base; 3684ba319b5SDimitry Andric *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; 3694ba319b5SDimitry Andric if (__value == 0) 3704ba319b5SDimitry Andric break; 3714ba319b5SDimitry Andric } 3724ba319b5SDimitry Andric 3734ba319b5SDimitry Andric auto __len = __last - __p; 3744ba319b5SDimitry Andric if (__value != 0 || !__len) 3754ba319b5SDimitry Andric return {__last, errc::value_too_large}; 3764ba319b5SDimitry Andric else 3774ba319b5SDimitry Andric { 3784ba319b5SDimitry Andric memmove(__first, __p, __len); 3794ba319b5SDimitry Andric return {__first + __len, {}}; 3804ba319b5SDimitry Andric } 3814ba319b5SDimitry Andric} 3824ba319b5SDimitry Andric 3834ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_integral<_Tp>::value, int> = 0> 3844ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY to_chars_result 3854ba319b5SDimitry Andricto_chars(char* __first, char* __last, _Tp __value) 3864ba319b5SDimitry Andric{ 3874ba319b5SDimitry Andric return __to_chars_itoa(__first, __last, __value, is_signed<_Tp>()); 3884ba319b5SDimitry Andric} 3894ba319b5SDimitry Andric 3904ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_integral<_Tp>::value, int> = 0> 3914ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY to_chars_result 3924ba319b5SDimitry Andricto_chars(char* __first, char* __last, _Tp __value, int __base) 3934ba319b5SDimitry Andric{ 3944ba319b5SDimitry Andric _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); 3954ba319b5SDimitry Andric return __to_chars_integral(__first, __last, __value, __base, 3964ba319b5SDimitry Andric is_signed<_Tp>()); 3974ba319b5SDimitry Andric} 3984ba319b5SDimitry Andric 3994ba319b5SDimitry Andrictemplate <typename _It, typename _Tp, typename _Fn, typename... _Ts> 4004ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 4014ba319b5SDimitry Andric__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) 4024ba319b5SDimitry Andric{ 4034ba319b5SDimitry Andric using __tl = numeric_limits<_Tp>; 4044ba319b5SDimitry Andric decltype(__to_unsigned(__value)) __x; 4054ba319b5SDimitry Andric 4064ba319b5SDimitry Andric bool __neg = (__first != __last && *__first == '-'); 4074ba319b5SDimitry Andric auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); 4084ba319b5SDimitry Andric switch (__r.ec) 4094ba319b5SDimitry Andric { 4104ba319b5SDimitry Andric case errc::invalid_argument: 4114ba319b5SDimitry Andric return {__first, __r.ec}; 4124ba319b5SDimitry Andric case errc::result_out_of_range: 4134ba319b5SDimitry Andric return __r; 4144ba319b5SDimitry Andric default: 4154ba319b5SDimitry Andric break; 4164ba319b5SDimitry Andric } 4174ba319b5SDimitry Andric 4184ba319b5SDimitry Andric if (__neg) 4194ba319b5SDimitry Andric { 4204ba319b5SDimitry Andric if (__x <= __complement(__to_unsigned(__tl::min()))) 4214ba319b5SDimitry Andric { 4224ba319b5SDimitry Andric __x = __complement(__x); 4234ba319b5SDimitry Andric memcpy(&__value, &__x, sizeof(__x)); 4244ba319b5SDimitry Andric return __r; 4254ba319b5SDimitry Andric } 4264ba319b5SDimitry Andric } 4274ba319b5SDimitry Andric else 4284ba319b5SDimitry Andric { 4294ba319b5SDimitry Andric if (__x <= (__tl::max)()) 4304ba319b5SDimitry Andric { 4314ba319b5SDimitry Andric __value = __x; 4324ba319b5SDimitry Andric return __r; 4334ba319b5SDimitry Andric } 4344ba319b5SDimitry Andric } 4354ba319b5SDimitry Andric 4364ba319b5SDimitry Andric return {__r.ptr, errc::result_out_of_range}; 4374ba319b5SDimitry Andric} 4384ba319b5SDimitry Andric 4394ba319b5SDimitry Andrictemplate <typename _Tp> 4404ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY bool 4414ba319b5SDimitry Andric__in_pattern(_Tp __c) 4424ba319b5SDimitry Andric{ 4434ba319b5SDimitry Andric return '0' <= __c && __c <= '9'; 4444ba319b5SDimitry Andric} 4454ba319b5SDimitry Andric 4464ba319b5SDimitry Andricstruct _LIBCPP_HIDDEN __in_pattern_result 4474ba319b5SDimitry Andric{ 4484ba319b5SDimitry Andric bool __ok; 4494ba319b5SDimitry Andric int __val; 4504ba319b5SDimitry Andric 4514ba319b5SDimitry Andric explicit _LIBCPP_INLINE_VISIBILITY operator bool() const { return __ok; } 4524ba319b5SDimitry Andric}; 4534ba319b5SDimitry Andric 4544ba319b5SDimitry Andrictemplate <typename _Tp> 4554ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY __in_pattern_result 4564ba319b5SDimitry Andric__in_pattern(_Tp __c, int __base) 4574ba319b5SDimitry Andric{ 4584ba319b5SDimitry Andric if (__base <= 10) 4594ba319b5SDimitry Andric return {'0' <= __c && __c < '0' + __base, __c - '0'}; 4604ba319b5SDimitry Andric else if (__in_pattern(__c)) 4614ba319b5SDimitry Andric return {true, __c - '0'}; 4624ba319b5SDimitry Andric else if ('a' <= __c && __c < 'a' + __base - 10) 4634ba319b5SDimitry Andric return {true, __c - 'a' + 10}; 4644ba319b5SDimitry Andric else 4654ba319b5SDimitry Andric return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10}; 4664ba319b5SDimitry Andric} 4674ba319b5SDimitry Andric 4684ba319b5SDimitry Andrictemplate <typename _It, typename _Tp, typename _Fn, typename... _Ts> 4694ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 4704ba319b5SDimitry Andric__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, 4714ba319b5SDimitry Andric _Ts... __args) 4724ba319b5SDimitry Andric{ 4734ba319b5SDimitry Andric auto __find_non_zero = [](_It __first, _It __last) { 4744ba319b5SDimitry Andric for (; __first != __last; ++__first) 4754ba319b5SDimitry Andric if (*__first != '0') 4764ba319b5SDimitry Andric break; 4774ba319b5SDimitry Andric return __first; 4784ba319b5SDimitry Andric }; 4794ba319b5SDimitry Andric 4804ba319b5SDimitry Andric auto __p = __find_non_zero(__first, __last); 4814ba319b5SDimitry Andric if (__p == __last || !__in_pattern(*__p, __args...)) 4824ba319b5SDimitry Andric { 4834ba319b5SDimitry Andric if (__p == __first) 4844ba319b5SDimitry Andric return {__first, errc::invalid_argument}; 4854ba319b5SDimitry Andric else 4864ba319b5SDimitry Andric { 4874ba319b5SDimitry Andric __value = 0; 4884ba319b5SDimitry Andric return {__p, {}}; 4894ba319b5SDimitry Andric } 4904ba319b5SDimitry Andric } 4914ba319b5SDimitry Andric 4924ba319b5SDimitry Andric auto __r = __f(__p, __last, __value, __args...); 4934ba319b5SDimitry Andric if (__r.ec == errc::result_out_of_range) 4944ba319b5SDimitry Andric { 4954ba319b5SDimitry Andric for (; __r.ptr != __last; ++__r.ptr) 4964ba319b5SDimitry Andric { 4974ba319b5SDimitry Andric if (!__in_pattern(*__r.ptr, __args...)) 4984ba319b5SDimitry Andric break; 4994ba319b5SDimitry Andric } 5004ba319b5SDimitry Andric } 5014ba319b5SDimitry Andric 5024ba319b5SDimitry Andric return __r; 5034ba319b5SDimitry Andric} 5044ba319b5SDimitry Andric 5054ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_unsigned<_Tp>::value, int> = 0> 5064ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 5074ba319b5SDimitry Andric__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) 5084ba319b5SDimitry Andric{ 5094ba319b5SDimitry Andric using __tx = __itoa::__traits<_Tp>; 5104ba319b5SDimitry Andric using __output_type = typename __tx::type; 5114ba319b5SDimitry Andric 5124ba319b5SDimitry Andric return __subject_seq_combinator( 5134ba319b5SDimitry Andric __first, __last, __value, 5144ba319b5SDimitry Andric [](const char* __first, const char* __last, 5154ba319b5SDimitry Andric _Tp& __value) -> from_chars_result { 5164ba319b5SDimitry Andric __output_type __a, __b; 5174ba319b5SDimitry Andric auto __p = __tx::__read(__first, __last, __a, __b); 5184ba319b5SDimitry Andric if (__p == __last || !__in_pattern(*__p)) 5194ba319b5SDimitry Andric { 5204ba319b5SDimitry Andric __output_type __m = (numeric_limits<_Tp>::max)(); 5214ba319b5SDimitry Andric if (__m >= __a && __m - __a >= __b) 5224ba319b5SDimitry Andric { 5234ba319b5SDimitry Andric __value = __a + __b; 5244ba319b5SDimitry Andric return {__p, {}}; 5254ba319b5SDimitry Andric } 5264ba319b5SDimitry Andric } 5274ba319b5SDimitry Andric return {__p, errc::result_out_of_range}; 5284ba319b5SDimitry Andric }); 5294ba319b5SDimitry Andric} 5304ba319b5SDimitry Andric 5314ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_signed<_Tp>::value, int> = 0> 5324ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 5334ba319b5SDimitry Andric__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) 5344ba319b5SDimitry Andric{ 5354ba319b5SDimitry Andric using __t = decltype(__to_unsigned(__value)); 5364ba319b5SDimitry Andric return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); 5374ba319b5SDimitry Andric} 5384ba319b5SDimitry Andric 5394ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_unsigned<_Tp>::value, int> = 0> 5404ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 5414ba319b5SDimitry Andric__from_chars_integral(const char* __first, const char* __last, _Tp& __value, 5424ba319b5SDimitry Andric int __base) 5434ba319b5SDimitry Andric{ 5444ba319b5SDimitry Andric if (__base == 10) 5454ba319b5SDimitry Andric return __from_chars_atoi(__first, __last, __value); 5464ba319b5SDimitry Andric 5474ba319b5SDimitry Andric return __subject_seq_combinator( 5484ba319b5SDimitry Andric __first, __last, __value, 5494ba319b5SDimitry Andric [](const char* __p, const char* __last, _Tp& __value, 5504ba319b5SDimitry Andric int __base) -> from_chars_result { 5514ba319b5SDimitry Andric using __tl = numeric_limits<_Tp>; 5524ba319b5SDimitry Andric auto __digits = __tl::digits / log2f(float(__base)); 5534ba319b5SDimitry Andric _Tp __a = __in_pattern(*__p++, __base).__val, __b = 0; 5544ba319b5SDimitry Andric 5554ba319b5SDimitry Andric for (int __i = 1; __p != __last; ++__i, ++__p) 5564ba319b5SDimitry Andric { 5574ba319b5SDimitry Andric if (auto __c = __in_pattern(*__p, __base)) 5584ba319b5SDimitry Andric { 5594ba319b5SDimitry Andric if (__i < __digits - 1) 5604ba319b5SDimitry Andric __a = __a * __base + __c.__val; 5614ba319b5SDimitry Andric else 5624ba319b5SDimitry Andric { 5634ba319b5SDimitry Andric if (!__itoa::__mul_overflowed(__a, __base, __a)) 5644ba319b5SDimitry Andric ++__p; 5654ba319b5SDimitry Andric __b = __c.__val; 5664ba319b5SDimitry Andric break; 5674ba319b5SDimitry Andric } 5684ba319b5SDimitry Andric } 5694ba319b5SDimitry Andric else 5704ba319b5SDimitry Andric break; 5714ba319b5SDimitry Andric } 5724ba319b5SDimitry Andric 5734ba319b5SDimitry Andric if (__p == __last || !__in_pattern(*__p, __base)) 5744ba319b5SDimitry Andric { 5754ba319b5SDimitry Andric if ((__tl::max)() - __a >= __b) 5764ba319b5SDimitry Andric { 5774ba319b5SDimitry Andric __value = __a + __b; 5784ba319b5SDimitry Andric return {__p, {}}; 5794ba319b5SDimitry Andric } 5804ba319b5SDimitry Andric } 5814ba319b5SDimitry Andric return {__p, errc::result_out_of_range}; 5824ba319b5SDimitry Andric }, 5834ba319b5SDimitry Andric __base); 5844ba319b5SDimitry Andric} 5854ba319b5SDimitry Andric 5864ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_signed<_Tp>::value, int> = 0> 5874ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 5884ba319b5SDimitry Andric__from_chars_integral(const char* __first, const char* __last, _Tp& __value, 5894ba319b5SDimitry Andric int __base) 5904ba319b5SDimitry Andric{ 5914ba319b5SDimitry Andric using __t = decltype(__to_unsigned(__value)); 5924ba319b5SDimitry Andric return __sign_combinator(__first, __last, __value, 5934ba319b5SDimitry Andric __from_chars_integral<__t>, __base); 5944ba319b5SDimitry Andric} 5954ba319b5SDimitry Andric 5964ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_integral<_Tp>::value, int> = 0> 5974ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 5984ba319b5SDimitry Andricfrom_chars(const char* __first, const char* __last, _Tp& __value) 5994ba319b5SDimitry Andric{ 6004ba319b5SDimitry Andric return __from_chars_atoi(__first, __last, __value); 6014ba319b5SDimitry Andric} 6024ba319b5SDimitry Andric 6034ba319b5SDimitry Andrictemplate <typename _Tp, enable_if_t<is_integral<_Tp>::value, int> = 0> 6044ba319b5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY from_chars_result 6054ba319b5SDimitry Andricfrom_chars(const char* __first, const char* __last, _Tp& __value, int __base) 6064ba319b5SDimitry Andric{ 6074ba319b5SDimitry Andric _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); 6084ba319b5SDimitry Andric return __from_chars_integral(__first, __last, __value, __base); 6094ba319b5SDimitry Andric} 6104ba319b5SDimitry Andric 6114ba319b5SDimitry Andric#endif // _LIBCPP_STD_VER > 11 6124ba319b5SDimitry Andric 6134ba319b5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 6144ba319b5SDimitry Andric 615*b5893f02SDimitry Andric_LIBCPP_POP_MACROS 616*b5893f02SDimitry Andric 6174ba319b5SDimitry Andric#endif // _LIBCPP_CHARCONV 618