1d2748964SZhihao Yuan// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
3d2748964SZhihao Yuan//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7d2748964SZhihao Yuan//
8d2748964SZhihao Yuan//===----------------------------------------------------------------------===//
9d2748964SZhihao Yuan
10d2748964SZhihao Yuan#ifndef _LIBCPP_CHARCONV
11d2748964SZhihao Yuan#define _LIBCPP_CHARCONV
12d2748964SZhihao Yuan
13d2748964SZhihao Yuan/*
14d2748964SZhihao Yuan    charconv synopsis
15d2748964SZhihao Yuan
16d2748964SZhihao Yuannamespace std {
17d2748964SZhihao Yuan
18d2748964SZhihao Yuan  // floating-point format for primitive numerical conversion
19d2748964SZhihao Yuan  enum class chars_format {
20d2748964SZhihao Yuan    scientific = unspecified,
21d2748964SZhihao Yuan    fixed = unspecified,
22d2748964SZhihao Yuan    hex = unspecified,
23d2748964SZhihao Yuan    general = fixed | scientific
24d2748964SZhihao Yuan  };
25d2748964SZhihao Yuan
26d2748964SZhihao Yuan  // 23.20.2, primitive numerical output conversion
27d2748964SZhihao Yuan  struct to_chars_result {
28d2748964SZhihao Yuan    char* ptr;
29d2748964SZhihao Yuan    errc ec;
303624c4d8SMark de Wever    friend bool operator==(const to_chars_result&, const to_chars_result&) = default; // since C++20
31d2748964SZhihao Yuan  };
32d2748964SZhihao Yuan
33d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, see below value,
34d2748964SZhihao Yuan                           int base = 10);
35a59c1a21SKonstantin Varlamov  to_chars_result to_chars(char* first, char* last, bool value,
36a59c1a21SKonstantin Varlamov                           int base = 10) = delete;
37d2748964SZhihao Yuan
38d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, float value);
39d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, double value);
40d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, long double value);
41d2748964SZhihao Yuan
42d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, float value,
43d2748964SZhihao Yuan                           chars_format fmt);
44d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, double value,
45d2748964SZhihao Yuan                           chars_format fmt);
46d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, long double value,
47d2748964SZhihao Yuan                           chars_format fmt);
48d2748964SZhihao Yuan
49d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, float value,
50d2748964SZhihao Yuan                           chars_format fmt, int precision);
51d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, double value,
52d2748964SZhihao Yuan                           chars_format fmt, int precision);
53d2748964SZhihao Yuan  to_chars_result to_chars(char* first, char* last, long double value,
54d2748964SZhihao Yuan                           chars_format fmt, int precision);
55d2748964SZhihao Yuan
56d2748964SZhihao Yuan  // 23.20.3, primitive numerical input conversion
57d2748964SZhihao Yuan  struct from_chars_result {
58d2748964SZhihao Yuan    const char* ptr;
59d2748964SZhihao Yuan    errc ec;
603624c4d8SMark de Wever    friend bool operator==(const from_chars_result&, const from_chars_result&) = default; // since C++20
61d2748964SZhihao Yuan  };
62d2748964SZhihao Yuan
63d2748964SZhihao Yuan  from_chars_result from_chars(const char* first, const char* last,
64d2748964SZhihao Yuan                               see below& value, int base = 10);
65d2748964SZhihao Yuan
66d2748964SZhihao Yuan  from_chars_result from_chars(const char* first, const char* last,
67d2748964SZhihao Yuan                               float& value,
68d2748964SZhihao Yuan                               chars_format fmt = chars_format::general);
69d2748964SZhihao Yuan  from_chars_result from_chars(const char* first, const char* last,
70d2748964SZhihao Yuan                               double& value,
71d2748964SZhihao Yuan                               chars_format fmt = chars_format::general);
72d2748964SZhihao Yuan  from_chars_result from_chars(const char* first, const char* last,
73d2748964SZhihao Yuan                               long double& value,
74d2748964SZhihao Yuan                               chars_format fmt = chars_format::general);
75d2748964SZhihao Yuan
76d2748964SZhihao Yuan} // namespace std
77d2748964SZhihao Yuan
78d2748964SZhihao Yuan*/
79d2748964SZhihao Yuan
80385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
812eadbc86SLouis Dionne#include <__availability>
8296ed451fSMark de Wever#include <__bits>
83e983a659SMark de Wever#include <__charconv/chars_format.h>
84e983a659SMark de Wever#include <__charconv/from_chars_result.h>
85a15ae413SMark de Wever#include <__charconv/tables.h>
86a15ae413SMark de Wever#include <__charconv/to_chars_base_10.h>
87e983a659SMark de Wever#include <__charconv/to_chars_result.h>
88bfbd73f8SArthur O'Dwyer#include <__config>
892a8f9a5eSNikolas Klauser#include <__debug>
90d2748964SZhihao Yuan#include <__errc>
91*b7aa9c4aSNikolas Klauser#include <__type_traits/make_32_64_or_128_bit.h>
922a8f9a5eSNikolas Klauser#include <__utility/unreachable.h>
93b12ea065SArthur O'Dwyer#include <cmath> // for log2f
94b12ea065SArthur O'Dwyer#include <cstdint>
952a8f9a5eSNikolas Klauser#include <cstdlib>
96b12ea065SArthur O'Dwyer#include <cstring>
97d2748964SZhihao Yuan#include <limits>
98b12ea065SArthur O'Dwyer#include <type_traits>
99d2748964SZhihao Yuan
100de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
101de4a57cbSLouis Dionne#  include <iosfwd>
102de4a57cbSLouis Dionne#endif
103de4a57cbSLouis Dionne
104d2748964SZhihao Yuan#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
105d2748964SZhihao Yuan#  pragma GCC system_header
106d2748964SZhihao Yuan#endif
107d2748964SZhihao Yuan
10827e9fdb2SMarshall Clow_LIBCPP_PUSH_MACROS
10927e9fdb2SMarshall Clow#include <__undef_macros>
11027e9fdb2SMarshall Clow
111d2748964SZhihao Yuan_LIBCPP_BEGIN_NAMESPACE_STD
112d2748964SZhihao Yuan
113769c2459SMarshall Clow#ifndef _LIBCPP_CXX03_LANG
114d2748964SZhihao Yuan
115bfc253c0SMark de Weverto_chars_result to_chars(char*, char*, bool, int = 10) = delete;
116bfc253c0SMark de Weverfrom_chars_result from_chars(const char*, const char*, bool, int = 10) = delete;
117d2748964SZhihao Yuan
118d2748964SZhihao Yuannamespace __itoa
119d2748964SZhihao Yuan{
120d2748964SZhihao Yuan
121d2748964SZhihao Yuantemplate <typename _Tp, typename = void>
1223f786833SMark de Weverstruct _LIBCPP_HIDDEN __traits_base;
123d2748964SZhihao Yuan
124d2748964SZhihao Yuantemplate <typename _Tp>
1253f786833SMark de Weverstruct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uint32_t)>>
126d2748964SZhihao Yuan{
127d2748964SZhihao Yuan    using type = uint32_t;
128d2748964SZhihao Yuan
1293f786833SMark de Wever    /// The width estimation using a log10 algorithm.
1303f786833SMark de Wever    ///
1313f786833SMark de Wever    /// The algorithm is based on
1323f786833SMark de Wever    /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
1333f786833SMark de Wever    /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
1343f786833SMark de Wever    /// function requires its input to have at least one bit set the value of
1353f786833SMark de Wever    /// zero is set to one. This means the first element of the lookup table is
1363f786833SMark de Wever    /// zero.
1373925f98dSMark de Wever    static _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v)
138d2748964SZhihao Yuan    {
1393925f98dSMark de Wever        auto __t = (32 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12;
140dea7a8e6SMark de Wever        return __t - (__v < __table<>::__pow10_32[__t]) + 1;
141d2748964SZhihao Yuan    }
142d2748964SZhihao Yuan
1433561ee58SMark de Wever    static _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v)
144d2748964SZhihao Yuan    {
1453561ee58SMark de Wever        return __itoa::__base_10_u32(__p, __v);
146d2748964SZhihao Yuan    }
147d2748964SZhihao Yuan
148dea7a8e6SMark de Wever    static _LIBCPP_HIDE_FROM_ABI decltype(__table<>::__pow10_32)& __pow() { return __table<>::__pow10_32; }
149d2748964SZhihao Yuan};
150d2748964SZhihao Yuan
151d2748964SZhihao Yuantemplate <typename _Tp>
1523f786833SMark de Weverstruct _LIBCPP_HIDDEN
1533f786833SMark de Wever    __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uint64_t)>> {
1543f786833SMark de Wever  using type = uint64_t;
1553f786833SMark de Wever
1563f786833SMark de Wever  /// The width estimation using a log10 algorithm.
1573f786833SMark de Wever  ///
1583f786833SMark de Wever  /// The algorithm is based on
1593f786833SMark de Wever  /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
1603f786833SMark de Wever  /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
1613f786833SMark de Wever  /// function requires its input to have at least one bit set the value of
1623f786833SMark de Wever  /// zero is set to one. This means the first element of the lookup table is
1633f786833SMark de Wever  /// zero.
1643f786833SMark de Wever  static _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) {
1653f786833SMark de Wever    auto __t = (64 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12;
1663f786833SMark de Wever    return __t - (__v < __table<>::__pow10_64[__t]) + 1;
1673f786833SMark de Wever  }
1683f786833SMark de Wever
1693f786833SMark de Wever  static _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { return __itoa::__base_10_u64(__p, __v); }
1703f786833SMark de Wever
1713f786833SMark de Wever  static _LIBCPP_HIDE_FROM_ABI decltype(__table<>::__pow10_64)& __pow() { return __table<>::__pow10_64; }
1723f786833SMark de Wever};
1733f786833SMark de Wever
1743f786833SMark de Wever
1753f786833SMark de Wever#  ifndef _LIBCPP_HAS_NO_INT128
1763f786833SMark de Wevertemplate <typename _Tp>
1773f786833SMark de Weverstruct _LIBCPP_HIDDEN
1783f786833SMark de Wever    __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(__uint128_t)> > {
1793f786833SMark de Wever  using type = __uint128_t;
1803f786833SMark de Wever
1813f786833SMark de Wever  /// The width estimation using a log10 algorithm.
1823f786833SMark de Wever  ///
1833f786833SMark de Wever  /// The algorithm is based on
1843f786833SMark de Wever  /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
1853f786833SMark de Wever  /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
1863f786833SMark de Wever  /// function requires its input to have at least one bit set the value of
1873f786833SMark de Wever  /// zero is set to one. This means the first element of the lookup table is
1883f786833SMark de Wever  /// zero.
1893f786833SMark de Wever  static _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) {
1903f786833SMark de Wever    _LIBCPP_ASSERT(__v > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true.");
1913f786833SMark de Wever    // There's always a bit set in the upper 64-bits.
1923f786833SMark de Wever    auto __t = (128 - std::__libcpp_clz(static_cast<uint64_t>(__v >> 64))) * 1233 >> 12;
1933f786833SMark de Wever    _LIBCPP_ASSERT(__t >= __table<>::__pow10_128_offset, "Index out of bounds");
1943f786833SMark de Wever    // __t is adjusted since the lookup table misses the lower entries.
1953f786833SMark de Wever    return __t - (__v < __table<>::__pow10_128[__t - __table<>::__pow10_128_offset]) + 1;
1963f786833SMark de Wever  }
1973f786833SMark de Wever
1983f786833SMark de Wever  static _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { return __itoa::__base_10_u128(__p, __v); }
1993f786833SMark de Wever
2003f786833SMark de Wever  // TODO FMT This pow function should get an index.
2013f786833SMark de Wever  // By moving this to its own header it can be reused by the pow function in to_chars_base_10.
2023f786833SMark de Wever  static _LIBCPP_HIDE_FROM_ABI decltype(__table<>::__pow10_128)& __pow() { return __table<>::__pow10_128; }
2033f786833SMark de Wever};
2043f786833SMark de Wever#endif
2053f786833SMark de Wever
2063f786833SMark de Wevertemplate <typename _Tp>
2073925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI bool
208d2748964SZhihao Yuan__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r)
209d2748964SZhihao Yuan{
210d2748964SZhihao Yuan    auto __c = __a * __b;
211d2748964SZhihao Yuan    __r = __c;
21203ee4612SArthur O'Dwyer    return __c > numeric_limits<unsigned char>::max();
213d2748964SZhihao Yuan}
214d2748964SZhihao Yuan
215d2748964SZhihao Yuantemplate <typename _Tp>
2163925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI bool
217d2748964SZhihao Yuan__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r)
218d2748964SZhihao Yuan{
219d2748964SZhihao Yuan    auto __c = __a * __b;
220d2748964SZhihao Yuan    __r = __c;
22103ee4612SArthur O'Dwyer    return __c > numeric_limits<unsigned short>::max();
222d2748964SZhihao Yuan}
223d2748964SZhihao Yuan
224d2748964SZhihao Yuantemplate <typename _Tp>
2253925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI bool
226d2748964SZhihao Yuan__mul_overflowed(_Tp __a, _Tp __b, _Tp& __r)
227d2748964SZhihao Yuan{
228d2748964SZhihao Yuan    static_assert(is_unsigned<_Tp>::value, "");
229d2748964SZhihao Yuan#if !defined(_LIBCPP_COMPILER_MSVC)
230d2748964SZhihao Yuan    return __builtin_mul_overflow(__a, __b, &__r);
231d2748964SZhihao Yuan#else
23203ee4612SArthur O'Dwyer    bool __did = __b && (numeric_limits<_Tp>::max() / __b) < __a;
233d2748964SZhihao Yuan    __r = __a * __b;
234d2748964SZhihao Yuan    return __did;
235d2748964SZhihao Yuan#endif
236d2748964SZhihao Yuan}
237d2748964SZhihao Yuan
238d2748964SZhihao Yuantemplate <typename _Tp, typename _Up>
2393925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI bool
240d2748964SZhihao Yuan__mul_overflowed(_Tp __a, _Up __b, _Tp& __r)
241d2748964SZhihao Yuan{
242d2748964SZhihao Yuan    return __mul_overflowed(__a, static_cast<_Tp>(__b), __r);
243d2748964SZhihao Yuan}
244d2748964SZhihao Yuan
245d2748964SZhihao Yuantemplate <typename _Tp>
246d2748964SZhihao Yuanstruct _LIBCPP_HIDDEN __traits : __traits_base<_Tp>
247d2748964SZhihao Yuan{
2483925f98dSMark de Wever    static constexpr int digits = numeric_limits<_Tp>::digits10 + 1;
249d2748964SZhihao Yuan    using __traits_base<_Tp>::__pow;
250d2748964SZhihao Yuan    using typename __traits_base<_Tp>::type;
251d2748964SZhihao Yuan
252d2748964SZhihao Yuan    // precondition: at least one non-zero character available
2533925f98dSMark de Wever    static _LIBCPP_HIDE_FROM_ABI char const*
254d2748964SZhihao Yuan    __read(char const* __p, char const* __ep, type& __a, type& __b)
255d2748964SZhihao Yuan    {
256d2748964SZhihao Yuan        type __cprod[digits];
257d2748964SZhihao Yuan        int __j = digits - 1;
258d2748964SZhihao Yuan        int __i = digits;
259d2748964SZhihao Yuan        do
260d2748964SZhihao Yuan        {
261d2748964SZhihao Yuan            if (!('0' <= *__p && *__p <= '9'))
262d2748964SZhihao Yuan                break;
263d2748964SZhihao Yuan            __cprod[--__i] = *__p++ - '0';
264d2748964SZhihao Yuan        } while (__p != __ep && __i != 0);
265d2748964SZhihao Yuan
266d2748964SZhihao Yuan        __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1,
267d2748964SZhihao Yuan                              __cprod[__i]);
268d2748964SZhihao Yuan        if (__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b))
269d2748964SZhihao Yuan            --__p;
270d2748964SZhihao Yuan        return __p;
271d2748964SZhihao Yuan    }
272d2748964SZhihao Yuan
273d2748964SZhihao Yuan    template <typename _It1, typename _It2, class _Up>
2743925f98dSMark de Wever    static _LIBCPP_HIDE_FROM_ABI _Up
275d2748964SZhihao Yuan    __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init)
276d2748964SZhihao Yuan    {
277d2748964SZhihao Yuan        for (; __first1 < __last1; ++__first1, ++__first2)
278d2748964SZhihao Yuan            __init = __init + *__first1 * *__first2;
279d2748964SZhihao Yuan        return __init;
280d2748964SZhihao Yuan    }
281d2748964SZhihao Yuan};
282d2748964SZhihao Yuan
283d2748964SZhihao Yuan}  // namespace __itoa
284d2748964SZhihao Yuan
285d2748964SZhihao Yuantemplate <typename _Tp>
2863925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI _Tp
287d2748964SZhihao Yuan__complement(_Tp __x)
288d2748964SZhihao Yuan{
289d2748964SZhihao Yuan    static_assert(is_unsigned<_Tp>::value, "cast to unsigned first");
290d2748964SZhihao Yuan    return _Tp(~__x + 1);
291d2748964SZhihao Yuan}
292d2748964SZhihao Yuan
293d2748964SZhihao Yuantemplate <typename _Tp>
2943925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
295d2748964SZhihao Yuan__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type)
296d2748964SZhihao Yuan{
297c273f5efSMark de Wever    auto __x = __to_unsigned_like(__value);
298d2748964SZhihao Yuan    if (__value < 0 && __first != __last)
299d2748964SZhihao Yuan    {
300d2748964SZhihao Yuan        *__first++ = '-';
301d2748964SZhihao Yuan        __x = __complement(__x);
302d2748964SZhihao Yuan    }
303d2748964SZhihao Yuan
304d2748964SZhihao Yuan    return __to_chars_itoa(__first, __last, __x, false_type());
305d2748964SZhihao Yuan}
306d2748964SZhihao Yuan
307d2748964SZhihao Yuantemplate <typename _Tp>
3083925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
309d2748964SZhihao Yuan__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type)
310d2748964SZhihao Yuan{
311d2748964SZhihao Yuan    using __tx = __itoa::__traits<_Tp>;
312d2748964SZhihao Yuan    auto __diff = __last - __first;
313d2748964SZhihao Yuan
314d2748964SZhihao Yuan    if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)
3153561ee58SMark de Wever        return {__tx::__convert(__first, __value), errc(0)};
316d2748964SZhihao Yuan    else
317d2748964SZhihao Yuan        return {__last, errc::value_too_large};
318d2748964SZhihao Yuan}
319d2748964SZhihao Yuan
3203f786833SMark de Wever#  ifndef _LIBCPP_HAS_NO_INT128
3213f786833SMark de Wevertemplate <>
3223f786833SMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
3233f786833SMark de Wever__to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type)
3243f786833SMark de Wever{
3253f786833SMark de Wever    // When the value fits in 64-bits use the 64-bit code path. This reduces
3263f786833SMark de Wever    // the number of expensive calculations on 128-bit values.
3273f786833SMark de Wever    //
3283f786833SMark de Wever    // NOTE the 128-bit code path requires this optimization.
3293f786833SMark de Wever    if(__value <= numeric_limits<uint64_t>::max())
3303f786833SMark de Wever        return __to_chars_itoa(__first, __last, static_cast<uint64_t>(__value), false_type());
3313f786833SMark de Wever
3323f786833SMark de Wever    using __tx = __itoa::__traits<__uint128_t>;
3333f786833SMark de Wever    auto __diff = __last - __first;
3343f786833SMark de Wever
3353f786833SMark de Wever    if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)
3363f786833SMark de Wever        return {__tx::__convert(__first, __value), errc(0)};
3373f786833SMark de Wever    else
3383f786833SMark de Wever        return {__last, errc::value_too_large};
3393f786833SMark de Wever}
3403f786833SMark de Wever#endif
3413f786833SMark de Wever
342d2748964SZhihao Yuantemplate <typename _Tp>
3433925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
344d2748964SZhihao Yuan__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
345d2748964SZhihao Yuan                    true_type)
346d2748964SZhihao Yuan{
347c273f5efSMark de Wever    auto __x = __to_unsigned_like(__value);
348d2748964SZhihao Yuan    if (__value < 0 && __first != __last)
349d2748964SZhihao Yuan    {
350d2748964SZhihao Yuan        *__first++ = '-';
351d2748964SZhihao Yuan        __x = __complement(__x);
352d2748964SZhihao Yuan    }
353d2748964SZhihao Yuan
354d2748964SZhihao Yuan    return __to_chars_integral(__first, __last, __x, __base, false_type());
355d2748964SZhihao Yuan}
356d2748964SZhihao Yuan
3576c11aebdSMark de Wevernamespace __itoa {
3586c11aebdSMark de Wever
3596c11aebdSMark de Wevertemplate <unsigned _Base>
3606c11aebdSMark de Weverstruct _LIBCPP_HIDDEN __integral;
3616c11aebdSMark de Wever
3626c11aebdSMark de Wevertemplate <>
3636c11aebdSMark de Weverstruct _LIBCPP_HIDDEN __integral<2> {
3646c11aebdSMark de Wever  template <typename _Tp>
3656c11aebdSMark de Wever  _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
3666c11aebdSMark de Wever    // If value == 0 still need one digit. If the value != this has no
3676c11aebdSMark de Wever    // effect since the code scans for the most significant bit set. (Note
3686c11aebdSMark de Wever    // that __libcpp_clz doesn't work for 0.)
3696c11aebdSMark de Wever    return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1);
3706c11aebdSMark de Wever  }
3716c11aebdSMark de Wever
3726c11aebdSMark de Wever  template <typename _Tp>
3736c11aebdSMark de Wever  _LIBCPP_HIDE_FROM_ABI static to_chars_result __to_chars(char* __first, char* __last, _Tp __value) {
3746c11aebdSMark de Wever    ptrdiff_t __cap = __last - __first;
3756c11aebdSMark de Wever    int __n = __width(__value);
3766c11aebdSMark de Wever    if (__n > __cap)
3776c11aebdSMark de Wever      return {__last, errc::value_too_large};
3786c11aebdSMark de Wever
3796c11aebdSMark de Wever    __last = __first + __n;
3806c11aebdSMark de Wever    char* __p = __last;
3816c11aebdSMark de Wever    const unsigned __divisor = 16;
3826c11aebdSMark de Wever    while (__value > __divisor) {
3836c11aebdSMark de Wever      unsigned __c = __value % __divisor;
3846c11aebdSMark de Wever      __value /= __divisor;
3856c11aebdSMark de Wever      __p -= 4;
386dea7a8e6SMark de Wever      std::memcpy(__p, &__table<>::__base_2_lut[4 * __c], 4);
3876c11aebdSMark de Wever    }
3886c11aebdSMark de Wever    do {
3896c11aebdSMark de Wever      unsigned __c = __value % 2;
3906c11aebdSMark de Wever      __value /= 2;
3916c11aebdSMark de Wever      *--__p = "01"[__c];
3926c11aebdSMark de Wever    } while (__value != 0);
3936c11aebdSMark de Wever    return {__last, errc(0)};
3946c11aebdSMark de Wever  }
3956c11aebdSMark de Wever};
3966c11aebdSMark de Wever
3976c11aebdSMark de Wevertemplate <>
3986c11aebdSMark de Weverstruct _LIBCPP_HIDDEN __integral<8> {
3996c11aebdSMark de Wever  template <typename _Tp>
4006c11aebdSMark de Wever  _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
4016c11aebdSMark de Wever    // If value == 0 still need one digit. If the value != this has no
4026c11aebdSMark de Wever    // effect since the code scans for the most significat bit set. (Note
4036c11aebdSMark de Wever    // that __libcpp_clz doesn't work for 0.)
4046c11aebdSMark de Wever    return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3;
4056c11aebdSMark de Wever  }
4066c11aebdSMark de Wever
4076c11aebdSMark de Wever  template <typename _Tp>
4086c11aebdSMark de Wever  _LIBCPP_HIDE_FROM_ABI static to_chars_result __to_chars(char* __first, char* __last, _Tp __value) {
4096c11aebdSMark de Wever    ptrdiff_t __cap = __last - __first;
4106c11aebdSMark de Wever    int __n = __width(__value);
4116c11aebdSMark de Wever    if (__n > __cap)
4126c11aebdSMark de Wever      return {__last, errc::value_too_large};
4136c11aebdSMark de Wever
4146c11aebdSMark de Wever    __last = __first + __n;
4156c11aebdSMark de Wever    char* __p = __last;
4166c11aebdSMark de Wever    unsigned __divisor = 64;
4176c11aebdSMark de Wever    while (__value > __divisor) {
4186c11aebdSMark de Wever      unsigned __c = __value % __divisor;
4196c11aebdSMark de Wever      __value /= __divisor;
4206c11aebdSMark de Wever      __p -= 2;
421dea7a8e6SMark de Wever      std::memcpy(__p, &__table<>::__base_8_lut[2 * __c], 2);
4226c11aebdSMark de Wever    }
4236c11aebdSMark de Wever    do {
4246c11aebdSMark de Wever      unsigned __c = __value % 8;
4256c11aebdSMark de Wever      __value /= 8;
4266c11aebdSMark de Wever      *--__p = "01234567"[__c];
4276c11aebdSMark de Wever    } while (__value != 0);
4286c11aebdSMark de Wever    return {__last, errc(0)};
4296c11aebdSMark de Wever  }
4306c11aebdSMark de Wever
4316c11aebdSMark de Wever};
4326c11aebdSMark de Wever
4336c11aebdSMark de Wevertemplate <>
4346c11aebdSMark de Weverstruct _LIBCPP_HIDDEN __integral<16> {
4356c11aebdSMark de Wever  template <typename _Tp>
4366c11aebdSMark de Wever  _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
4376c11aebdSMark de Wever    // If value == 0 still need one digit. If the value != this has no
4386c11aebdSMark de Wever    // effect since the code scans for the most significat bit set. (Note
4396c11aebdSMark de Wever    // that __libcpp_clz doesn't work for 0.)
4406c11aebdSMark de Wever    return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4;
4416c11aebdSMark de Wever  }
4426c11aebdSMark de Wever
4436c11aebdSMark de Wever  template <typename _Tp>
4446c11aebdSMark de Wever  _LIBCPP_HIDE_FROM_ABI static to_chars_result __to_chars(char* __first, char* __last, _Tp __value) {
4456c11aebdSMark de Wever    ptrdiff_t __cap = __last - __first;
4466c11aebdSMark de Wever    int __n = __width(__value);
4476c11aebdSMark de Wever    if (__n > __cap)
4486c11aebdSMark de Wever      return {__last, errc::value_too_large};
4496c11aebdSMark de Wever
4506c11aebdSMark de Wever    __last = __first + __n;
4516c11aebdSMark de Wever    char* __p = __last;
4526c11aebdSMark de Wever    unsigned __divisor = 256;
4536c11aebdSMark de Wever    while (__value > __divisor) {
4546c11aebdSMark de Wever      unsigned __c = __value % __divisor;
4556c11aebdSMark de Wever      __value /= __divisor;
4566c11aebdSMark de Wever      __p -= 2;
457dea7a8e6SMark de Wever      std::memcpy(__p, &__table<>::__base_16_lut[2 * __c], 2);
4586c11aebdSMark de Wever    }
4596c11aebdSMark de Wever    if (__first != __last)
4606c11aebdSMark de Wever      do {
4616c11aebdSMark de Wever        unsigned __c = __value % 16;
4626c11aebdSMark de Wever        __value /= 16;
4636c11aebdSMark de Wever        *--__p = "0123456789abcdef"[__c];
4646c11aebdSMark de Wever      } while (__value != 0);
4656c11aebdSMark de Wever    return {__last, errc(0)};
4666c11aebdSMark de Wever  }
4676c11aebdSMark de Wever};
4686c11aebdSMark de Wever
4696c11aebdSMark de Wever} // namespace __itoa
4706c11aebdSMark de Wever
4716c11aebdSMark de Wevertemplate <unsigned _Base, typename _Tp,
4726c11aebdSMark de Wever          typename enable_if<(sizeof(_Tp) >= sizeof(unsigned)), int>::type = 0>
4736c11aebdSMark de Wever_LIBCPP_HIDE_FROM_ABI int
4746c11aebdSMark de Wever__to_chars_integral_width(_Tp __value) {
4756c11aebdSMark de Wever  return __itoa::__integral<_Base>::__width(__value);
4766c11aebdSMark de Wever}
4776c11aebdSMark de Wever
4786c11aebdSMark de Wevertemplate <unsigned _Base, typename _Tp,
4796c11aebdSMark de Wever          typename enable_if<(sizeof(_Tp) < sizeof(unsigned)), int>::type = 0>
4806c11aebdSMark de Wever_LIBCPP_HIDE_FROM_ABI int
4816c11aebdSMark de Wever__to_chars_integral_width(_Tp __value) {
4826c11aebdSMark de Wever  return std::__to_chars_integral_width<_Base>(static_cast<unsigned>(__value));
4836c11aebdSMark de Wever}
4846c11aebdSMark de Wever
4856c11aebdSMark de Wevertemplate <unsigned _Base, typename _Tp,
4866c11aebdSMark de Wever          typename enable_if<(sizeof(_Tp) >= sizeof(unsigned)), int>::type = 0>
4876c11aebdSMark de Wever_LIBCPP_HIDE_FROM_ABI to_chars_result
4886c11aebdSMark de Wever__to_chars_integral(char* __first, char* __last, _Tp __value) {
4896c11aebdSMark de Wever  return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);
4906c11aebdSMark de Wever}
4916c11aebdSMark de Wever
4926c11aebdSMark de Wevertemplate <unsigned _Base, typename _Tp,
4936c11aebdSMark de Wever          typename enable_if<(sizeof(_Tp) < sizeof(unsigned)), int>::type = 0>
4946c11aebdSMark de Wever_LIBCPP_HIDE_FROM_ABI to_chars_result
4956c11aebdSMark de Wever__to_chars_integral(char* __first, char* __last, _Tp __value) {
4966c11aebdSMark de Wever  return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));
4976c11aebdSMark de Wever}
4986c11aebdSMark de Wever
499d2748964SZhihao Yuantemplate <typename _Tp>
500b968c345SMark de Wever_LIBCPP_HIDE_FROM_ABI int
5013925f98dSMark de Wever__to_chars_integral_width(_Tp __value, unsigned __base) {
5029393060fSMark de Wever  _LIBCPP_ASSERT(__value >= 0, "The function requires a non-negative value.");
5039393060fSMark de Wever
5049393060fSMark de Wever  unsigned __base_2 = __base * __base;
5059393060fSMark de Wever  unsigned __base_3 = __base_2 * __base;
5069393060fSMark de Wever  unsigned __base_4 = __base_2 * __base_2;
5079393060fSMark de Wever
5089393060fSMark de Wever  int __r = 0;
5099393060fSMark de Wever  while (true) {
5109393060fSMark de Wever    if (__value < __base)
5119393060fSMark de Wever      return __r + 1;
5129393060fSMark de Wever    if (__value < __base_2)
5139393060fSMark de Wever      return __r + 2;
5149393060fSMark de Wever    if (__value < __base_3)
5159393060fSMark de Wever      return __r + 3;
5169393060fSMark de Wever    if (__value < __base_4)
5179393060fSMark de Wever      return __r + 4;
5189393060fSMark de Wever
5199393060fSMark de Wever    __value /= __base_4;
5209393060fSMark de Wever    __r += 4;
5219393060fSMark de Wever  }
5229393060fSMark de Wever
5232a8f9a5eSNikolas Klauser  __libcpp_unreachable();
5249393060fSMark de Wever}
5259393060fSMark de Wever
5269393060fSMark de Wevertemplate <typename _Tp>
5273925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
528d2748964SZhihao Yuan__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
529d2748964SZhihao Yuan                    false_type)
530d2748964SZhihao Yuan{
5316c11aebdSMark de Wever  if (__base == 10) [[likely]]
532d2748964SZhihao Yuan    return __to_chars_itoa(__first, __last, __value, false_type());
533d2748964SZhihao Yuan
5346c11aebdSMark de Wever  switch (__base) {
5356c11aebdSMark de Wever  case 2:
5366c11aebdSMark de Wever    return __to_chars_integral<2>(__first, __last, __value);
5376c11aebdSMark de Wever  case 8:
5386c11aebdSMark de Wever    return __to_chars_integral<8>(__first, __last, __value);
5396c11aebdSMark de Wever  case 16:
5406c11aebdSMark de Wever    return __to_chars_integral<16>(__first, __last, __value);
5416c11aebdSMark de Wever  }
5426c11aebdSMark de Wever
5439393060fSMark de Wever  ptrdiff_t __cap = __last - __first;
5449393060fSMark de Wever  int __n = __to_chars_integral_width(__value, __base);
5459393060fSMark de Wever  if (__n > __cap)
5469393060fSMark de Wever    return {__last, errc::value_too_large};
5479393060fSMark de Wever
5489393060fSMark de Wever  __last = __first + __n;
5499393060fSMark de Wever  char* __p = __last;
5509393060fSMark de Wever  do {
5519393060fSMark de Wever    unsigned __c = __value % __base;
552d2748964SZhihao Yuan    __value /= __base;
553d2748964SZhihao Yuan    *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];
5549393060fSMark de Wever  } while (__value != 0);
5559393060fSMark de Wever  return {__last, errc(0)};
556d2748964SZhihao Yuan}
557d2748964SZhihao Yuan
558769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
5593925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
560d2748964SZhihao Yuanto_chars(char* __first, char* __last, _Tp __value)
561d2748964SZhihao Yuan{
562cf927669SMark de Wever  using _Type = __make_32_64_or_128_bit_t<_Tp>;
563cf927669SMark de Wever  static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars");
564cf927669SMark de Wever  return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>());
565d2748964SZhihao Yuan}
566d2748964SZhihao Yuan
567769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
5683925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI to_chars_result
569d2748964SZhihao Yuanto_chars(char* __first, char* __last, _Tp __value, int __base)
570d2748964SZhihao Yuan{
571d2748964SZhihao Yuan  _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]");
572cf927669SMark de Wever
573cf927669SMark de Wever  using _Type = __make_32_64_or_128_bit_t<_Tp>;
574cf927669SMark de Wever  return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>());
575d2748964SZhihao Yuan}
576d2748964SZhihao Yuan
577d2748964SZhihao Yuantemplate <typename _It, typename _Tp, typename _Fn, typename... _Ts>
5783925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
579d2748964SZhihao Yuan__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args)
580d2748964SZhihao Yuan{
581d2748964SZhihao Yuan    using __tl = numeric_limits<_Tp>;
582c273f5efSMark de Wever    decltype(__to_unsigned_like(__value)) __x;
583d2748964SZhihao Yuan
584d2748964SZhihao Yuan    bool __neg = (__first != __last && *__first == '-');
585d2748964SZhihao Yuan    auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...);
586d2748964SZhihao Yuan    switch (__r.ec)
587d2748964SZhihao Yuan    {
588d2748964SZhihao Yuan    case errc::invalid_argument:
589d2748964SZhihao Yuan        return {__first, __r.ec};
590d2748964SZhihao Yuan    case errc::result_out_of_range:
591d2748964SZhihao Yuan        return __r;
592d2748964SZhihao Yuan    default:
593d2748964SZhihao Yuan        break;
594d2748964SZhihao Yuan    }
595d2748964SZhihao Yuan
596d2748964SZhihao Yuan    if (__neg)
597d2748964SZhihao Yuan    {
598c273f5efSMark de Wever        if (__x <= __complement(__to_unsigned_like(__tl::min())))
599d2748964SZhihao Yuan        {
600d2748964SZhihao Yuan            __x = __complement(__x);
6013925f98dSMark de Wever            std::memcpy(&__value, &__x, sizeof(__x));
602d2748964SZhihao Yuan            return __r;
603d2748964SZhihao Yuan        }
604d2748964SZhihao Yuan    }
605d2748964SZhihao Yuan    else
606d2748964SZhihao Yuan    {
607e39095a3SLouis Dionne        if (__x <= __to_unsigned_like(__tl::max()))
608d2748964SZhihao Yuan        {
609d2748964SZhihao Yuan            __value = __x;
610d2748964SZhihao Yuan            return __r;
611d2748964SZhihao Yuan        }
612d2748964SZhihao Yuan    }
613d2748964SZhihao Yuan
614d2748964SZhihao Yuan    return {__r.ptr, errc::result_out_of_range};
615d2748964SZhihao Yuan}
616d2748964SZhihao Yuan
617d2748964SZhihao Yuantemplate <typename _Tp>
6183925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI bool
619d2748964SZhihao Yuan__in_pattern(_Tp __c)
620d2748964SZhihao Yuan{
621d2748964SZhihao Yuan    return '0' <= __c && __c <= '9';
622d2748964SZhihao Yuan}
623d2748964SZhihao Yuan
624d2748964SZhihao Yuanstruct _LIBCPP_HIDDEN __in_pattern_result
625d2748964SZhihao Yuan{
626d2748964SZhihao Yuan    bool __ok;
627d2748964SZhihao Yuan    int __val;
628d2748964SZhihao Yuan
6293925f98dSMark de Wever    explicit _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; }
630d2748964SZhihao Yuan};
631d2748964SZhihao Yuan
632d2748964SZhihao Yuantemplate <typename _Tp>
6333925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI __in_pattern_result
634d2748964SZhihao Yuan__in_pattern(_Tp __c, int __base)
635d2748964SZhihao Yuan{
636d2748964SZhihao Yuan    if (__base <= 10)
637d2748964SZhihao Yuan        return {'0' <= __c && __c < '0' + __base, __c - '0'};
638d2748964SZhihao Yuan    else if (__in_pattern(__c))
639d2748964SZhihao Yuan        return {true, __c - '0'};
640d2748964SZhihao Yuan    else if ('a' <= __c && __c < 'a' + __base - 10)
641d2748964SZhihao Yuan        return {true, __c - 'a' + 10};
642d2748964SZhihao Yuan    else
643d2748964SZhihao Yuan        return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10};
644d2748964SZhihao Yuan}
645d2748964SZhihao Yuan
646d2748964SZhihao Yuantemplate <typename _It, typename _Tp, typename _Fn, typename... _Ts>
6473925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
648d2748964SZhihao Yuan__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f,
649d2748964SZhihao Yuan                         _Ts... __args)
650d2748964SZhihao Yuan{
651e39095a3SLouis Dionne    auto __find_non_zero = [](_It __firstit, _It __lastit) {
652e39095a3SLouis Dionne        for (; __firstit != __lastit; ++__firstit)
653e39095a3SLouis Dionne            if (*__firstit != '0')
654d2748964SZhihao Yuan                break;
655e39095a3SLouis Dionne        return __firstit;
656d2748964SZhihao Yuan    };
657d2748964SZhihao Yuan
658d2748964SZhihao Yuan    auto __p = __find_non_zero(__first, __last);
659d2748964SZhihao Yuan    if (__p == __last || !__in_pattern(*__p, __args...))
660d2748964SZhihao Yuan    {
661d2748964SZhihao Yuan        if (__p == __first)
662d2748964SZhihao Yuan            return {__first, errc::invalid_argument};
663d2748964SZhihao Yuan        else
664d2748964SZhihao Yuan        {
665d2748964SZhihao Yuan            __value = 0;
666d2748964SZhihao Yuan            return {__p, {}};
667d2748964SZhihao Yuan        }
668d2748964SZhihao Yuan    }
669d2748964SZhihao Yuan
670d2748964SZhihao Yuan    auto __r = __f(__p, __last, __value, __args...);
671d2748964SZhihao Yuan    if (__r.ec == errc::result_out_of_range)
672d2748964SZhihao Yuan    {
673d2748964SZhihao Yuan        for (; __r.ptr != __last; ++__r.ptr)
674d2748964SZhihao Yuan        {
675d2748964SZhihao Yuan            if (!__in_pattern(*__r.ptr, __args...))
676d2748964SZhihao Yuan                break;
677d2748964SZhihao Yuan        }
678d2748964SZhihao Yuan    }
679d2748964SZhihao Yuan
680d2748964SZhihao Yuan    return __r;
681d2748964SZhihao Yuan}
682d2748964SZhihao Yuan
683769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0>
6843925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
685d2748964SZhihao Yuan__from_chars_atoi(const char* __first, const char* __last, _Tp& __value)
686d2748964SZhihao Yuan{
687d2748964SZhihao Yuan    using __tx = __itoa::__traits<_Tp>;
688d2748964SZhihao Yuan    using __output_type = typename __tx::type;
689d2748964SZhihao Yuan
690d2748964SZhihao Yuan    return __subject_seq_combinator(
691d2748964SZhihao Yuan        __first, __last, __value,
692b48c5010SNikolas Klauser        [](const char* __f, const char* __l,
693e39095a3SLouis Dionne           _Tp& __val) -> from_chars_result {
694d2748964SZhihao Yuan            __output_type __a, __b;
695b48c5010SNikolas Klauser            auto __p = __tx::__read(__f, __l, __a, __b);
696b48c5010SNikolas Klauser            if (__p == __l || !__in_pattern(*__p))
697d2748964SZhihao Yuan            {
69803ee4612SArthur O'Dwyer                __output_type __m = numeric_limits<_Tp>::max();
699d2748964SZhihao Yuan                if (__m >= __a && __m - __a >= __b)
700d2748964SZhihao Yuan                {
701e39095a3SLouis Dionne                    __val = __a + __b;
702d2748964SZhihao Yuan                    return {__p, {}};
703d2748964SZhihao Yuan                }
704d2748964SZhihao Yuan            }
705d2748964SZhihao Yuan            return {__p, errc::result_out_of_range};
706d2748964SZhihao Yuan        });
707d2748964SZhihao Yuan}
708d2748964SZhihao Yuan
709769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0>
7103925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
711d2748964SZhihao Yuan__from_chars_atoi(const char* __first, const char* __last, _Tp& __value)
712d2748964SZhihao Yuan{
713c273f5efSMark de Wever    using __t = decltype(__to_unsigned_like(__value));
714d2748964SZhihao Yuan    return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>);
715d2748964SZhihao Yuan}
716d2748964SZhihao Yuan
717769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0>
7183925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
719d2748964SZhihao Yuan__from_chars_integral(const char* __first, const char* __last, _Tp& __value,
720d2748964SZhihao Yuan                      int __base)
721d2748964SZhihao Yuan{
722d2748964SZhihao Yuan    if (__base == 10)
723d2748964SZhihao Yuan        return __from_chars_atoi(__first, __last, __value);
724d2748964SZhihao Yuan
725d2748964SZhihao Yuan    return __subject_seq_combinator(
726d2748964SZhihao Yuan        __first, __last, __value,
727e39095a3SLouis Dionne        [](const char* __p, const char* __lastp, _Tp& __val,
728b48c5010SNikolas Klauser           int __b) -> from_chars_result {
729d2748964SZhihao Yuan            using __tl = numeric_limits<_Tp>;
730b48c5010SNikolas Klauser            auto __digits = __tl::digits / log2f(float(__b));
731b48c5010SNikolas Klauser            _Tp __x = __in_pattern(*__p++, __b).__val, __y = 0;
732d2748964SZhihao Yuan
733e39095a3SLouis Dionne            for (int __i = 1; __p != __lastp; ++__i, ++__p)
734d2748964SZhihao Yuan            {
735b48c5010SNikolas Klauser                if (auto __c = __in_pattern(*__p, __b))
736d2748964SZhihao Yuan                {
737d2748964SZhihao Yuan                    if (__i < __digits - 1)
738b48c5010SNikolas Klauser                        __x = __x * __b + __c.__val;
739d2748964SZhihao Yuan                    else
740d2748964SZhihao Yuan                    {
741b48c5010SNikolas Klauser                        if (!__itoa::__mul_overflowed(__x, __b, __x))
742d2748964SZhihao Yuan                            ++__p;
743b48c5010SNikolas Klauser                        __y = __c.__val;
744d2748964SZhihao Yuan                        break;
745d2748964SZhihao Yuan                    }
746d2748964SZhihao Yuan                }
747d2748964SZhihao Yuan                else
748d2748964SZhihao Yuan                    break;
749d2748964SZhihao Yuan            }
750d2748964SZhihao Yuan
751b48c5010SNikolas Klauser            if (__p == __lastp || !__in_pattern(*__p, __b))
752d2748964SZhihao Yuan            {
753b48c5010SNikolas Klauser                if (__tl::max() - __x >= __y)
754d2748964SZhihao Yuan                {
755b48c5010SNikolas Klauser                    __val = __x + __y;
756d2748964SZhihao Yuan                    return {__p, {}};
757d2748964SZhihao Yuan                }
758d2748964SZhihao Yuan            }
759d2748964SZhihao Yuan            return {__p, errc::result_out_of_range};
760d2748964SZhihao Yuan        },
761d2748964SZhihao Yuan        __base);
762d2748964SZhihao Yuan}
763d2748964SZhihao Yuan
764769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0>
7653925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
766d2748964SZhihao Yuan__from_chars_integral(const char* __first, const char* __last, _Tp& __value,
767d2748964SZhihao Yuan                      int __base)
768d2748964SZhihao Yuan{
769c273f5efSMark de Wever    using __t = decltype(__to_unsigned_like(__value));
770d2748964SZhihao Yuan    return __sign_combinator(__first, __last, __value,
771d2748964SZhihao Yuan                             __from_chars_integral<__t>, __base);
772d2748964SZhihao Yuan}
773d2748964SZhihao Yuan
774769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
7753925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
776d2748964SZhihao Yuanfrom_chars(const char* __first, const char* __last, _Tp& __value)
777d2748964SZhihao Yuan{
778d2748964SZhihao Yuan    return __from_chars_atoi(__first, __last, __value);
779d2748964SZhihao Yuan}
780d2748964SZhihao Yuan
781769c2459SMarshall Clowtemplate <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
7823925f98dSMark de Weverinline _LIBCPP_HIDE_FROM_ABI from_chars_result
783d2748964SZhihao Yuanfrom_chars(const char* __first, const char* __last, _Tp& __value, int __base)
784d2748964SZhihao Yuan{
785d2748964SZhihao Yuan    _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]");
786d2748964SZhihao Yuan    return __from_chars_integral(__first, __last, __value, __base);
787d2748964SZhihao Yuan}
788d2748964SZhihao Yuan
789abb5dd6eSMark de Wever// Floating-point implementation starts here.
790abb5dd6eSMark de Wever// Unlike the other parts of charconv this is only available in C++17 and newer.
791abb5dd6eSMark de Wever#if _LIBCPP_STD_VER > 14
792abb5dd6eSMark de Wever
793abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
794abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, float __value);
795abb5dd6eSMark de Wever
796abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
797abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, double __value);
798abb5dd6eSMark de Wever
799abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
800abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, long double __value);
801abb5dd6eSMark de Wever
802abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
803abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt);
804abb5dd6eSMark de Wever
805abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
806abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt);
807abb5dd6eSMark de Wever
808abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
809abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt);
810abb5dd6eSMark de Wever
811abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
812abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision);
813abb5dd6eSMark de Wever
814abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
815abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision);
816abb5dd6eSMark de Wever
817abb5dd6eSMark de Wever_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS
818abb5dd6eSMark de Weverto_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision);
819abb5dd6eSMark de Wever
820abb5dd6eSMark de Wever#  endif // _LIBCPP_STD_VER > 14
821769c2459SMarshall Clow#endif // _LIBCPP_CXX03_LANG
822d2748964SZhihao Yuan
823d2748964SZhihao Yuan_LIBCPP_END_NAMESPACE_STD
824d2748964SZhihao Yuan
82527e9fdb2SMarshall Clow_LIBCPP_POP_MACROS
82627e9fdb2SMarshall Clow
827d2748964SZhihao Yuan#endif // _LIBCPP_CHARCONV
828