// Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include #include #include #include #include #include #include _EXTERN_C_UNLESS_PURE constexpr int _Base_max = 36; // largest valid base // static data static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; // valid digits // 64-bits! static const char ndigs[_Base_max + 1] = {0, 0, 65, 41, 33, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13}; _CRTIMP2_PURE unsigned long long __CLRCALL_PURE_OR_CDECL _Stoullx( const char* s, char** endptr, int base, int* perr) noexcept { // convert string to unsigned long long, with checking const char* sc; const char* sd; const char* s1; const char* s2; char dig; char sign; ptrdiff_t n; unsigned long long x; unsigned long long y; if (perr != nullptr) { *perr = 0; } sc = s; while (isspace(static_cast(*sc))) { ++sc; } sign = static_cast(*sc == '-' || *sc == '+' ? *sc++ : '+'); if (base < 0 || base == 1 || _Base_max < base) { // silly base if (endptr != nullptr) { *endptr = const_cast(s); } return 0; } if (0 < base) { // strip 0x or 0X if (base == 16 && *sc == '0' && (sc[1] == 'x' || sc[1] == 'X')) { sc += 2; } } else if (*sc != '0') { base = 10; } else if (sc[1] == 'x' || sc[1] == 'X') { base = 16; sc += 2; } else { base = 8; } for (s1 = sc; *sc == '0'; ++sc) { // skip leading zeros } x = 0; for (s2 = sc, y = 0, dig = 0; (sd = static_cast(memchr(&digits[0], tolower(*sc), base))) != nullptr; ++sc) { // accumulate digits y = x; dig = static_cast(sd - digits); // for overflow checking x = x * base + dig; } if (s1 == sc) { // check string validity if (endptr != nullptr) { *endptr = const_cast(s); } return 0; } n = sc - s2 - ndigs[base]; if (n >= 0 && (0 < n || x < x - dig || (x - dig) / base != y)) { // overflow errno = ERANGE; if (perr != nullptr) { *perr = 1; } x = ULLONG_MAX; sign = '+'; } if (sign == '-') { // get final value x = 0 - x; } if (endptr != nullptr) { *endptr = const_cast(sc); } return x; } // TRANSITION, ABI: preserved for binary compatibility _CRTIMP2_PURE unsigned long long __CLRCALL_PURE_OR_CDECL _Stoull(const char* s, char** endptr, int base) noexcept { // convert string, discard error code return _Stoullx(s, endptr, base, nullptr); } _END_EXTERN_C_UNLESS_PURE