codekingpro/portable-devtools
114k
1// -*- C++ -*-2//===------------------------------ charconv ------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCUDACXX_CHARCONV11#define _LIBCUDACXX_CHARCONV12 13/*14 charconv synopsis15 16namespace std {17 18 // floating-point format for primitive numerical conversion19 enum class chars_format {20 scientific = unspecified,21 fixed = unspecified,22 hex = unspecified,23 general = fixed | scientific24 };25 26 // 23.20.2, primitive numerical output conversion27 struct to_chars_result {28 char* ptr;29 errc ec;30 };31 32 to_chars_result to_chars(char* first, char* last, see below value,33 int base = 10);34 35 to_chars_result to_chars(char* first, char* last, float value);36 to_chars_result to_chars(char* first, char* last, double value);37 to_chars_result to_chars(char* first, char* last, long double value);38 39 to_chars_result to_chars(char* first, char* last, float value,40 chars_format fmt);41 to_chars_result to_chars(char* first, char* last, double value,42 chars_format fmt);43 to_chars_result to_chars(char* first, char* last, long double value,44 chars_format fmt);45 46 to_chars_result to_chars(char* first, char* last, float value,47 chars_format fmt, int precision);48 to_chars_result to_chars(char* first, char* last, double value,49 chars_format fmt, int precision);50 to_chars_result to_chars(char* first, char* last, long double value,51 chars_format fmt, int precision);52 53 // 23.20.3, primitive numerical input conversion54 struct from_chars_result {55 const char* ptr;56 errc ec;57 };58 59 from_chars_result from_chars(const char* first, const char* last,60 see below& value, int base = 10);61 62 from_chars_result from_chars(const char* first, const char* last,63 float& value,64 chars_format fmt = chars_format::general);65 from_chars_result from_chars(const char* first, const char* last,66 double& value,67 chars_format fmt = chars_format::general);68 from_chars_result from_chars(const char* first, const char* last,69 long double& value,70 chars_format fmt = chars_format::general);71 72} // namespace std73 74*/75 76#include <__errc>77#include <type_traits>78#include <limits>79#include <stdint.h>80#include <string.h>81#include <math.h>82 83#include <__debug>84 85#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)86# pragma GCC system_header87#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)88# pragma clang system_header89#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)90# pragma system_header91#endif // no system header92 93_LIBCUDACXX_PUSH_MACROS94#include <__undef_macros>95 96_LIBCUDACXX_BEGIN_NAMESPACE_STD97 98namespace __itoa {99_LIBCUDACXX_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);100_LIBCUDACXX_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);101}102 103enum class _LIBCUDACXX_ENUM_VIS chars_format104{105 scientific = 0x1,106 fixed = 0x2,107 hex = 0x4,108 general = fixed | scientific109};110 111struct _LIBCUDACXX_TYPE_VIS to_chars_result112{113 char* ptr;114 errc ec;115};116 117struct _LIBCUDACXX_TYPE_VIS from_chars_result118{119 const char* ptr;120 errc ec;121};122 123void to_chars(char*, char*, bool, int = 10) = delete;124void from_chars(const char*, const char*, bool, int = 10) = delete;125 126namespace __itoa127{128 129static constexpr uint64_t __pow10_64[] = {130 UINT64_C(0),131 UINT64_C(10),132 UINT64_C(100),133 UINT64_C(1000),134 UINT64_C(10000),135 UINT64_C(100000),136 UINT64_C(1000000),137 UINT64_C(10000000),138 UINT64_C(100000000),139 UINT64_C(1000000000),140 UINT64_C(10000000000),141 UINT64_C(100000000000),142 UINT64_C(1000000000000),143 UINT64_C(10000000000000),144 UINT64_C(100000000000000),145 UINT64_C(1000000000000000),146 UINT64_C(10000000000000000),147 UINT64_C(100000000000000000),148 UINT64_C(1000000000000000000),149 UINT64_C(10000000000000000000),150};151 152static constexpr uint32_t __pow10_32[] = {153 UINT32_C(0), UINT32_C(10), UINT32_C(100),154 UINT32_C(1000), UINT32_C(10000), UINT32_C(100000),155 UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000),156 UINT32_C(1000000000),157};158 159template <typename _Tp, typename = void>160struct _LIBCUDACXX_HIDDEN __traits_base161{162 using type = uint64_t;163 164#if !defined(_LIBCUDACXX_COMPILER_MSVC)165 static _LIBCUDACXX_INLINE_VISIBILITY int __width(_Tp __v)166 {167 auto __t = (64 - __builtin_clzll(__v | 1)) * 1233 >> 12;168 return __t - (__v < __pow10_64[__t]) + 1;169 }170#endif171 172 static _LIBCUDACXX_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p)173 {174 return __u64toa(__v, __p);175 }176 177 static _LIBCUDACXX_INLINE_VISIBILITY decltype(__pow10_64)& __pow() { return __pow10_64; }178};179 180template <typename _Tp>181struct _LIBCUDACXX_HIDDEN182 __traits_base<_Tp, decltype(void(uint32_t{declval<_Tp>()}))>183{184 using type = uint32_t;185 186#if !defined(_LIBCUDACXX_COMPILER_MSVC)187 static _LIBCUDACXX_INLINE_VISIBILITY int __width(_Tp __v)188 {189 auto __t = (32 - __builtin_clz(__v | 1)) * 1233 >> 12;190 return __t - (__v < __pow10_32[__t]) + 1;191 }192#endif193 194 static _LIBCUDACXX_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p)195 {196 return __u32toa(__v, __p);197 }198 199 static _LIBCUDACXX_INLINE_VISIBILITY decltype(__pow10_32)& __pow() { return __pow10_32; }200};201 202template <typename _Tp>203inline _LIBCUDACXX_INLINE_VISIBILITY bool204__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r)205{206 auto __c = __a * __b;207 __r = __c;208 return __c > (numeric_limits<unsigned char>::max)();209}210 211template <typename _Tp>212inline _LIBCUDACXX_INLINE_VISIBILITY bool213__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r)214{215 auto __c = __a * __b;216 __r = __c;217 return __c > (numeric_limits<unsigned short>::max)();218}219 220template <typename _Tp>221inline _LIBCUDACXX_INLINE_VISIBILITY bool222__mul_overflowed(_Tp __a, _Tp __b, _Tp& __r)223{224 static_assert(is_unsigned<_Tp>::value, "");225#if !defined(_LIBCUDACXX_COMPILER_MSVC) && !defined(_LIBCUDACXX_COMPILER_NVHPC)226 return __builtin_mul_overflow(__a, __b, &__r);227#else228 bool __did = __b && ((numeric_limits<_Tp>::max)() / __b) < __a;229 __r = __a * __b;230 return __did;231#endif232}233 234template <typename _Tp, typename _Up>235inline _LIBCUDACXX_INLINE_VISIBILITY bool236__mul_overflowed(_Tp __a, _Up __b, _Tp& __r)237{238 return __mul_overflowed(__a, static_cast<_Tp>(__b), __r);239}240 241template <typename _Tp>242struct _LIBCUDACXX_HIDDEN __traits : __traits_base<_Tp>243{244 static constexpr int digits = numeric_limits<_Tp>::digits10 + 1;245 using __traits_base<_Tp>::__pow;246 using typename __traits_base<_Tp>::type;247 248 // precondition: at least one non-zero character available249 static _LIBCUDACXX_INLINE_VISIBILITY char const*250 __read(char const* __p, char const* __ep, type& __a, type& __b)251 {252 type __cprod[digits];253 int __j = digits - 1;254 int __i = digits;255 do256 {257 if (!('0' <= *__p && *__p <= '9'))258 break;259 __cprod[--__i] = *__p++ - '0';260 } while (__p != __ep && __i != 0);261 262 __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1,263 __cprod[__i]);264 if (__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b))265 --__p;266 return __p;267 }268 269 template <typename _It1, typename _It2, class _Up>270 static _LIBCUDACXX_INLINE_VISIBILITY _Up271 __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init)272 {273 for (; __first1 < __last1; ++__first1, ++__first2)274 __init = __init + *__first1 * *__first2;275 return __init;276 }277};278 279} // namespace __itoa280 281template <typename _Tp>282inline _LIBCUDACXX_INLINE_VISIBILITY _Tp283__complement(_Tp __x)284{285 static_assert(is_unsigned<_Tp>::value, "cast to unsigned first");286 return _Tp(~__x + 1);287}288 289template <typename _Tp>290inline _LIBCUDACXX_INLINE_VISIBILITY typename make_unsigned<_Tp>::type291__to_unsigned(_Tp __x)292{293 return static_cast<typename make_unsigned<_Tp>::type>(__x);294}295 296template <typename _Tp>297inline _LIBCUDACXX_INLINE_VISIBILITY to_chars_result298__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type)299{300 auto __x = __to_unsigned(__value);301 if (__value < 0 && __first != __last)302 {303 *__first++ = '-';304 __x = __complement(__x);305 }306 307 return __to_chars_itoa(__first, __last, __x, false_type());308}309 310template <typename _Tp>311inline _LIBCUDACXX_INLINE_VISIBILITY to_chars_result312__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type)313{314 using __tx = __itoa::__traits<_Tp>;315 auto __diff = __last - __first;316 317#if !defined(_LIBCUDACXX_COMPILER_MSVC)318 if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)319 return {__tx::__convert(__value, __first), errc(0)};320 else321 return {__last, errc::value_too_large};322#else323 if (__tx::digits <= __diff)324 return {__tx::__convert(__value, __first), {}};325 else326 {327 char __buf[__tx::digits];328 auto __p = __tx::__convert(__value, __buf);329 auto __len = __p - __buf;330 if (__len <= __diff)331 {332 memcpy(__first, __buf, __len);333 return {__first + __len, {}};334 }335 else336 return {__last, errc::value_too_large};337 }338#endif339}340 341template <typename _Tp>342inline _LIBCUDACXX_INLINE_VISIBILITY to_chars_result343__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,344 true_type)345{346 auto __x = __to_unsigned(__value);347 if (__value < 0 && __first != __last)348 {349 *__first++ = '-';350 __x = __complement(__x);351 }352 353 return __to_chars_integral(__first, __last, __x, __base, false_type());354}355 356template <typename _Tp>357inline _LIBCUDACXX_INLINE_VISIBILITY to_chars_result358__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,359 false_type)360{361 if (__base == 10)362 return __to_chars_itoa(__first, __last, __value, false_type());363 364 auto __p = __last;365 while (__p != __first)366 {367 auto __c = __value % __base;368 __value /= __base;369 *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];370 if (__value == 0)371 break;372 }373 374 auto __len = __last - __p;375 if (__value != 0 || !__len)376 return {__last, errc::value_too_large};377 else378 {379 memmove(__first, __p, __len);380 return {__first + __len, {}};381 }382}383 384template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>385inline _LIBCUDACXX_INLINE_VISIBILITY to_chars_result386to_chars(char* __first, char* __last, _Tp __value)387{388 return __to_chars_itoa(__first, __last, __value, is_signed<_Tp>());389}390 391template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>392inline _LIBCUDACXX_INLINE_VISIBILITY to_chars_result393to_chars(char* __first, char* __last, _Tp __value, int __base)394{395 _LIBCUDACXX_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]");396 return __to_chars_integral(__first, __last, __value, __base,397 is_signed<_Tp>());398}399 400template <typename _It, typename _Tp, typename _Fn, typename... _Ts>401inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result402__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args)403{404 using __tl = numeric_limits<_Tp>;405 decltype(__to_unsigned(__value)) __x;406 407 bool __neg = (__first != __last && *__first == '-');408 auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...);409 switch (__r.ec)410 {411 case errc::invalid_argument:412 return {__first, __r.ec};413 case errc::result_out_of_range:414 return __r;415 default:416 break;417 }418 419 if (__neg)420 {421 if (__x <= __complement(__to_unsigned(__tl::min())))422 {423 __x = __complement(__x);424 memcpy(&__value, &__x, sizeof(__x));425 return __r;426 }427 }428 else429 {430 if (__x <= (__tl::max)())431 {432 __value = __x;433 return __r;434 }435 }436 437 return {__r.ptr, errc::result_out_of_range};438}439 440template <typename _Tp>441inline _LIBCUDACXX_INLINE_VISIBILITY bool442__in_pattern(_Tp __c)443{444 return '0' <= __c && __c <= '9';445}446 447struct _LIBCUDACXX_HIDDEN __in_pattern_result448{449 bool __ok;450 int __val;451 452 explicit _LIBCUDACXX_INLINE_VISIBILITY operator bool() const { return __ok; }453};454 455template <typename _Tp>456inline _LIBCUDACXX_INLINE_VISIBILITY __in_pattern_result457__in_pattern(_Tp __c, int __base)458{459 if (__base <= 10)460 return {'0' <= __c && __c < '0' + __base, __c - '0'};461 else if (__in_pattern(__c))462 return {true, __c - '0'};463 else if ('a' <= __c && __c < 'a' + __base - 10)464 return {true, __c - 'a' + 10};465 else466 return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10};467}468 469template <typename _It, typename _Tp, typename _Fn, typename... _Ts>470inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result471__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f,472 _Ts... __args)473{474 auto __find_non_zero = [](_It __first, _It __last) {475 for (; __first != __last; ++__first)476 if (*__first != '0')477 break;478 return __first;479 };480 481 auto __p = __find_non_zero(__first, __last);482 if (__p == __last || !__in_pattern(*__p, __args...))483 {484 if (__p == __first)485 return {__first, errc::invalid_argument};486 else487 {488 __value = 0;489 return {__p, {}};490 }491 }492 493 auto __r = __f(__p, __last, __value, __args...);494 if (__r.ec == errc::result_out_of_range)495 {496 for (; __r.ptr != __last; ++__r.ptr)497 {498 if (!__in_pattern(*__r.ptr, __args...))499 break;500 }501 }502 503 return __r;504}505 506template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0>507inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result508__from_chars_atoi(const char* __first, const char* __last, _Tp& __value)509{510 using __tx = __itoa::__traits<_Tp>;511 using __output_type = typename __tx::type;512 513 return __subject_seq_combinator(514 __first, __last, __value,515 [](const char* __first, const char* __last,516 _Tp& __value) -> from_chars_result {517 __output_type __a, __b;518 auto __p = __tx::__read(__first, __last, __a, __b);519 if (__p == __last || !__in_pattern(*__p))520 {521 __output_type __m = (numeric_limits<_Tp>::max)();522 if (__m >= __a && __m - __a >= __b)523 {524 __value = __a + __b;525 return {__p, {}};526 }527 }528 return {__p, errc::result_out_of_range};529 });530}531 532template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0>533inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result534__from_chars_atoi(const char* __first, const char* __last, _Tp& __value)535{536 using __t = decltype(__to_unsigned(__value));537 return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>);538}539 540template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0>541inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result542__from_chars_integral(const char* __first, const char* __last, _Tp& __value,543 int __base)544{545 if (__base == 10)546 return __from_chars_atoi(__first, __last, __value);547 548 return __subject_seq_combinator(549 __first, __last, __value,550 [](const char* __p, const char* __last, _Tp& __value,551 int __base) -> from_chars_result {552 using __tl = numeric_limits<_Tp>;553 auto __digits = __tl::digits / log2f(float(__base));554 _Tp __a = __in_pattern(*__p++, __base).__val, __b = 0;555 556 for (int __i = 1; __p != __last; ++__i, ++__p)557 {558 if (auto __c = __in_pattern(*__p, __base))559 {560 if (__i < __digits - 1)561 __a = __a * __base + __c.__val;562 else563 {564 if (!__itoa::__mul_overflowed(__a, __base, __a))565 ++__p;566 __b = __c.__val;567 break;568 }569 }570 else571 break;572 }573 574 if (__p == __last || !__in_pattern(*__p, __base))575 {576 if ((__tl::max)() - __a >= __b)577 {578 __value = __a + __b;579 return {__p, {}};580 }581 }582 return {__p, errc::result_out_of_range};583 },584 __base);585}586 587template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0>588inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result589__from_chars_integral(const char* __first, const char* __last, _Tp& __value,590 int __base)591{592 using __t = decltype(__to_unsigned(__value));593 return __sign_combinator(__first, __last, __value,594 __from_chars_integral<__t>, __base);595}596 597template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>598inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result599from_chars(const char* __first, const char* __last, _Tp& __value)600{601 return __from_chars_atoi(__first, __last, __value);602}603 604template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>605inline _LIBCUDACXX_INLINE_VISIBILITY from_chars_result606from_chars(const char* __first, const char* __last, _Tp& __value, int __base)607{608 _LIBCUDACXX_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]");609 return __from_chars_integral(__first, __last, __value, __base);610}611 612_LIBCUDACXX_END_NAMESPACE_STD613 614_LIBCUDACXX_POP_MACROS615 616#endif // _LIBCUDACXX_CHARCONV617 