xref: /freebsd-src/contrib/llvm-project/libcxx/include/__charconv/to_chars_integral.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric // -*- C++ -*-
206c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
306c3fb27SDimitry Andric //
406c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
506c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
606c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
706c3fb27SDimitry Andric //
806c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
906c3fb27SDimitry Andric 
1006c3fb27SDimitry Andric #ifndef _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
1106c3fb27SDimitry Andric #define _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
1206c3fb27SDimitry Andric 
1306c3fb27SDimitry Andric #include <__algorithm/copy_n.h>
14*0fca6ea1SDimitry Andric #include <__assert>
1506c3fb27SDimitry Andric #include <__bit/countl.h>
1606c3fb27SDimitry Andric #include <__charconv/tables.h>
1706c3fb27SDimitry Andric #include <__charconv/to_chars_base_10.h>
1806c3fb27SDimitry Andric #include <__charconv/to_chars_result.h>
1906c3fb27SDimitry Andric #include <__charconv/traits.h>
2006c3fb27SDimitry Andric #include <__config>
2106c3fb27SDimitry Andric #include <__system_error/errc.h>
2206c3fb27SDimitry Andric #include <__type_traits/enable_if.h>
2306c3fb27SDimitry Andric #include <__type_traits/integral_constant.h>
2406c3fb27SDimitry Andric #include <__type_traits/is_same.h>
2506c3fb27SDimitry Andric #include <__type_traits/make_32_64_or_128_bit.h>
2606c3fb27SDimitry Andric #include <__type_traits/make_unsigned.h>
2706c3fb27SDimitry Andric #include <__utility/unreachable.h>
2806c3fb27SDimitry Andric #include <cstddef>
2906c3fb27SDimitry Andric #include <cstdint>
3006c3fb27SDimitry Andric #include <limits>
3106c3fb27SDimitry Andric 
3206c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
3306c3fb27SDimitry Andric #  pragma GCC system_header
3406c3fb27SDimitry Andric #endif
3506c3fb27SDimitry Andric 
3606c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
3706c3fb27SDimitry Andric #include <__undef_macros>
3806c3fb27SDimitry Andric 
3906c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
4006c3fb27SDimitry Andric 
4106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17
4206c3fb27SDimitry Andric 
4306c3fb27SDimitry Andric to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
4406c3fb27SDimitry Andric 
4506c3fb27SDimitry Andric template <typename _Tp>
4606c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
4706c3fb27SDimitry Andric __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type);
4806c3fb27SDimitry Andric 
4906c3fb27SDimitry Andric template <typename _Tp>
5006c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
5106c3fb27SDimitry Andric __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) {
5206c3fb27SDimitry Andric   auto __x = std::__to_unsigned_like(__value);
5306c3fb27SDimitry Andric   if (__value < 0 && __first != __last) {
5406c3fb27SDimitry Andric     *__first++ = '-';
5506c3fb27SDimitry Andric     __x        = std::__complement(__x);
5606c3fb27SDimitry Andric   }
5706c3fb27SDimitry Andric 
5806c3fb27SDimitry Andric   return std::__to_chars_itoa(__first, __last, __x, false_type());
5906c3fb27SDimitry Andric }
6006c3fb27SDimitry Andric 
6106c3fb27SDimitry Andric template <typename _Tp>
6206c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
6306c3fb27SDimitry Andric __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) {
6406c3fb27SDimitry Andric   using __tx  = __itoa::__traits<_Tp>;
6506c3fb27SDimitry Andric   auto __diff = __last - __first;
6606c3fb27SDimitry Andric 
6706c3fb27SDimitry Andric   if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)
6806c3fb27SDimitry Andric     return {__tx::__convert(__first, __value), errc(0)};
6906c3fb27SDimitry Andric   else
7006c3fb27SDimitry Andric     return {__last, errc::value_too_large};
7106c3fb27SDimitry Andric }
7206c3fb27SDimitry Andric 
7306c3fb27SDimitry Andric #  ifndef _LIBCPP_HAS_NO_INT128
7406c3fb27SDimitry Andric template <>
7506c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
7606c3fb27SDimitry Andric __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) {
7706c3fb27SDimitry Andric   // When the value fits in 64-bits use the 64-bit code path. This reduces
7806c3fb27SDimitry Andric   // the number of expensive calculations on 128-bit values.
7906c3fb27SDimitry Andric   //
8006c3fb27SDimitry Andric   // NOTE the 128-bit code path requires this optimization.
8106c3fb27SDimitry Andric   if (__value <= numeric_limits<uint64_t>::max())
8206c3fb27SDimitry Andric     return __to_chars_itoa(__first, __last, static_cast<uint64_t>(__value), false_type());
8306c3fb27SDimitry Andric 
8406c3fb27SDimitry Andric   using __tx  = __itoa::__traits<__uint128_t>;
8506c3fb27SDimitry Andric   auto __diff = __last - __first;
8606c3fb27SDimitry Andric 
8706c3fb27SDimitry Andric   if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)
8806c3fb27SDimitry Andric     return {__tx::__convert(__first, __value), errc(0)};
8906c3fb27SDimitry Andric   else
9006c3fb27SDimitry Andric     return {__last, errc::value_too_large};
9106c3fb27SDimitry Andric }
9206c3fb27SDimitry Andric #  endif
9306c3fb27SDimitry Andric 
9406c3fb27SDimitry Andric template <class _Tp>
9506c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
9606c3fb27SDimitry Andric __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type);
9706c3fb27SDimitry Andric 
9806c3fb27SDimitry Andric template <typename _Tp>
9906c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
10006c3fb27SDimitry Andric __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, true_type) {
10106c3fb27SDimitry Andric   auto __x = std::__to_unsigned_like(__value);
10206c3fb27SDimitry Andric   if (__value < 0 && __first != __last) {
10306c3fb27SDimitry Andric     *__first++ = '-';
10406c3fb27SDimitry Andric     __x        = std::__complement(__x);
10506c3fb27SDimitry Andric   }
10606c3fb27SDimitry Andric 
10706c3fb27SDimitry Andric   return std::__to_chars_integral(__first, __last, __x, __base, false_type());
10806c3fb27SDimitry Andric }
10906c3fb27SDimitry Andric 
11006c3fb27SDimitry Andric namespace __itoa {
11106c3fb27SDimitry Andric 
11206c3fb27SDimitry Andric template <unsigned _Base>
11306c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __integral;
11406c3fb27SDimitry Andric 
11506c3fb27SDimitry Andric template <>
11606c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __integral<2> {
11706c3fb27SDimitry Andric   template <typename _Tp>
11806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
11906c3fb27SDimitry Andric     // If value == 0 still need one digit. If the value != this has no
12006c3fb27SDimitry Andric     // effect since the code scans for the most significant bit set. (Note
12106c3fb27SDimitry Andric     // that __libcpp_clz doesn't work for 0.)
12206c3fb27SDimitry Andric     return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1);
12306c3fb27SDimitry Andric   }
12406c3fb27SDimitry Andric 
12506c3fb27SDimitry Andric   template <typename _Tp>
12606c3fb27SDimitry Andric   _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
12706c3fb27SDimitry Andric   __to_chars(char* __first, char* __last, _Tp __value) {
12806c3fb27SDimitry Andric     ptrdiff_t __cap = __last - __first;
12906c3fb27SDimitry Andric     int __n         = __width(__value);
13006c3fb27SDimitry Andric     if (__n > __cap)
13106c3fb27SDimitry Andric       return {__last, errc::value_too_large};
13206c3fb27SDimitry Andric 
13306c3fb27SDimitry Andric     __last                   = __first + __n;
13406c3fb27SDimitry Andric     char* __p                = __last;
13506c3fb27SDimitry Andric     const unsigned __divisor = 16;
13606c3fb27SDimitry Andric     while (__value > __divisor) {
13706c3fb27SDimitry Andric       unsigned __c = __value % __divisor;
13806c3fb27SDimitry Andric       __value /= __divisor;
13906c3fb27SDimitry Andric       __p -= 4;
14006c3fb27SDimitry Andric       std::copy_n(&__base_2_lut[4 * __c], 4, __p);
14106c3fb27SDimitry Andric     }
14206c3fb27SDimitry Andric     do {
14306c3fb27SDimitry Andric       unsigned __c = __value % 2;
14406c3fb27SDimitry Andric       __value /= 2;
14506c3fb27SDimitry Andric       *--__p = "01"[__c];
14606c3fb27SDimitry Andric     } while (__value != 0);
14706c3fb27SDimitry Andric     return {__last, errc(0)};
14806c3fb27SDimitry Andric   }
14906c3fb27SDimitry Andric };
15006c3fb27SDimitry Andric 
15106c3fb27SDimitry Andric template <>
15206c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __integral<8> {
15306c3fb27SDimitry Andric   template <typename _Tp>
15406c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
15506c3fb27SDimitry Andric     // If value == 0 still need one digit. If the value != this has no
15606c3fb27SDimitry Andric     // effect since the code scans for the most significat bit set. (Note
15706c3fb27SDimitry Andric     // that __libcpp_clz doesn't work for 0.)
15806c3fb27SDimitry Andric     return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3;
15906c3fb27SDimitry Andric   }
16006c3fb27SDimitry Andric 
16106c3fb27SDimitry Andric   template <typename _Tp>
16206c3fb27SDimitry Andric   _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
16306c3fb27SDimitry Andric   __to_chars(char* __first, char* __last, _Tp __value) {
16406c3fb27SDimitry Andric     ptrdiff_t __cap = __last - __first;
16506c3fb27SDimitry Andric     int __n         = __width(__value);
16606c3fb27SDimitry Andric     if (__n > __cap)
16706c3fb27SDimitry Andric       return {__last, errc::value_too_large};
16806c3fb27SDimitry Andric 
16906c3fb27SDimitry Andric     __last             = __first + __n;
17006c3fb27SDimitry Andric     char* __p          = __last;
17106c3fb27SDimitry Andric     unsigned __divisor = 64;
17206c3fb27SDimitry Andric     while (__value > __divisor) {
17306c3fb27SDimitry Andric       unsigned __c = __value % __divisor;
17406c3fb27SDimitry Andric       __value /= __divisor;
17506c3fb27SDimitry Andric       __p -= 2;
17606c3fb27SDimitry Andric       std::copy_n(&__base_8_lut[2 * __c], 2, __p);
17706c3fb27SDimitry Andric     }
17806c3fb27SDimitry Andric     do {
17906c3fb27SDimitry Andric       unsigned __c = __value % 8;
18006c3fb27SDimitry Andric       __value /= 8;
18106c3fb27SDimitry Andric       *--__p = "01234567"[__c];
18206c3fb27SDimitry Andric     } while (__value != 0);
18306c3fb27SDimitry Andric     return {__last, errc(0)};
18406c3fb27SDimitry Andric   }
18506c3fb27SDimitry Andric };
18606c3fb27SDimitry Andric 
18706c3fb27SDimitry Andric template <>
18806c3fb27SDimitry Andric struct _LIBCPP_HIDDEN __integral<16> {
18906c3fb27SDimitry Andric   template <typename _Tp>
19006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
19106c3fb27SDimitry Andric     // If value == 0 still need one digit. If the value != this has no
19206c3fb27SDimitry Andric     // effect since the code scans for the most significat bit set. (Note
19306c3fb27SDimitry Andric     // that __libcpp_clz doesn't work for 0.)
19406c3fb27SDimitry Andric     return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4;
19506c3fb27SDimitry Andric   }
19606c3fb27SDimitry Andric 
19706c3fb27SDimitry Andric   template <typename _Tp>
19806c3fb27SDimitry Andric   _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
19906c3fb27SDimitry Andric   __to_chars(char* __first, char* __last, _Tp __value) {
20006c3fb27SDimitry Andric     ptrdiff_t __cap = __last - __first;
20106c3fb27SDimitry Andric     int __n         = __width(__value);
20206c3fb27SDimitry Andric     if (__n > __cap)
20306c3fb27SDimitry Andric       return {__last, errc::value_too_large};
20406c3fb27SDimitry Andric 
20506c3fb27SDimitry Andric     __last             = __first + __n;
20606c3fb27SDimitry Andric     char* __p          = __last;
20706c3fb27SDimitry Andric     unsigned __divisor = 256;
20806c3fb27SDimitry Andric     while (__value > __divisor) {
20906c3fb27SDimitry Andric       unsigned __c = __value % __divisor;
21006c3fb27SDimitry Andric       __value /= __divisor;
21106c3fb27SDimitry Andric       __p -= 2;
21206c3fb27SDimitry Andric       std::copy_n(&__base_16_lut[2 * __c], 2, __p);
21306c3fb27SDimitry Andric     }
21406c3fb27SDimitry Andric     if (__first != __last)
21506c3fb27SDimitry Andric       do {
21606c3fb27SDimitry Andric         unsigned __c = __value % 16;
21706c3fb27SDimitry Andric         __value /= 16;
21806c3fb27SDimitry Andric         *--__p = "0123456789abcdef"[__c];
21906c3fb27SDimitry Andric       } while (__value != 0);
22006c3fb27SDimitry Andric     return {__last, errc(0)};
22106c3fb27SDimitry Andric   }
22206c3fb27SDimitry Andric };
22306c3fb27SDimitry Andric 
22406c3fb27SDimitry Andric } // namespace __itoa
22506c3fb27SDimitry Andric 
2265f757f3fSDimitry Andric template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>
22706c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) {
22806c3fb27SDimitry Andric   return __itoa::__integral<_Base>::__width(__value);
22906c3fb27SDimitry Andric }
23006c3fb27SDimitry Andric 
2315f757f3fSDimitry Andric template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>
23206c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) {
23306c3fb27SDimitry Andric   return std::__to_chars_integral_width<_Base>(static_cast<unsigned>(__value));
23406c3fb27SDimitry Andric }
23506c3fb27SDimitry Andric 
2365f757f3fSDimitry Andric template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>
23706c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
23806c3fb27SDimitry Andric __to_chars_integral(char* __first, char* __last, _Tp __value) {
23906c3fb27SDimitry Andric   return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);
24006c3fb27SDimitry Andric }
24106c3fb27SDimitry Andric 
2425f757f3fSDimitry Andric template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>
24306c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
24406c3fb27SDimitry Andric __to_chars_integral(char* __first, char* __last, _Tp __value) {
24506c3fb27SDimitry Andric   return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));
24606c3fb27SDimitry Andric }
24706c3fb27SDimitry Andric 
24806c3fb27SDimitry Andric template <typename _Tp>
24906c3fb27SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value, unsigned __base) {
2501db9f3b2SDimitry Andric   _LIBCPP_ASSERT_INTERNAL(__value >= 0, "The function requires a non-negative value.");
25106c3fb27SDimitry Andric 
25206c3fb27SDimitry Andric   unsigned __base_2 = __base * __base;
25306c3fb27SDimitry Andric   unsigned __base_3 = __base_2 * __base;
25406c3fb27SDimitry Andric   unsigned __base_4 = __base_2 * __base_2;
25506c3fb27SDimitry Andric 
25606c3fb27SDimitry Andric   int __r = 0;
25706c3fb27SDimitry Andric   while (true) {
25806c3fb27SDimitry Andric     if (__value < __base)
25906c3fb27SDimitry Andric       return __r + 1;
26006c3fb27SDimitry Andric     if (__value < __base_2)
26106c3fb27SDimitry Andric       return __r + 2;
26206c3fb27SDimitry Andric     if (__value < __base_3)
26306c3fb27SDimitry Andric       return __r + 3;
26406c3fb27SDimitry Andric     if (__value < __base_4)
26506c3fb27SDimitry Andric       return __r + 4;
26606c3fb27SDimitry Andric 
26706c3fb27SDimitry Andric     __value /= __base_4;
26806c3fb27SDimitry Andric     __r += 4;
26906c3fb27SDimitry Andric   }
27006c3fb27SDimitry Andric 
27106c3fb27SDimitry Andric   __libcpp_unreachable();
27206c3fb27SDimitry Andric }
27306c3fb27SDimitry Andric 
27406c3fb27SDimitry Andric template <typename _Tp>
27506c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
27606c3fb27SDimitry Andric __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type) {
27706c3fb27SDimitry Andric   if (__base == 10) [[likely]]
27806c3fb27SDimitry Andric     return std::__to_chars_itoa(__first, __last, __value, false_type());
27906c3fb27SDimitry Andric 
28006c3fb27SDimitry Andric   switch (__base) {
28106c3fb27SDimitry Andric   case 2:
28206c3fb27SDimitry Andric     return std::__to_chars_integral<2>(__first, __last, __value);
28306c3fb27SDimitry Andric   case 8:
28406c3fb27SDimitry Andric     return std::__to_chars_integral<8>(__first, __last, __value);
28506c3fb27SDimitry Andric   case 16:
28606c3fb27SDimitry Andric     return std::__to_chars_integral<16>(__first, __last, __value);
28706c3fb27SDimitry Andric   }
28806c3fb27SDimitry Andric 
28906c3fb27SDimitry Andric   ptrdiff_t __cap = __last - __first;
29006c3fb27SDimitry Andric   int __n         = std::__to_chars_integral_width(__value, __base);
29106c3fb27SDimitry Andric   if (__n > __cap)
29206c3fb27SDimitry Andric     return {__last, errc::value_too_large};
29306c3fb27SDimitry Andric 
29406c3fb27SDimitry Andric   __last    = __first + __n;
29506c3fb27SDimitry Andric   char* __p = __last;
29606c3fb27SDimitry Andric   do {
29706c3fb27SDimitry Andric     unsigned __c = __value % __base;
29806c3fb27SDimitry Andric     __value /= __base;
29906c3fb27SDimitry Andric     *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];
30006c3fb27SDimitry Andric   } while (__value != 0);
30106c3fb27SDimitry Andric   return {__last, errc(0)};
30206c3fb27SDimitry Andric }
30306c3fb27SDimitry Andric 
3045f757f3fSDimitry Andric template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
30506c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
30606c3fb27SDimitry Andric to_chars(char* __first, char* __last, _Tp __value) {
30706c3fb27SDimitry Andric   using _Type = __make_32_64_or_128_bit_t<_Tp>;
30806c3fb27SDimitry Andric   static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars");
30906c3fb27SDimitry Andric   return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>());
31006c3fb27SDimitry Andric }
31106c3fb27SDimitry Andric 
3125f757f3fSDimitry Andric template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
31306c3fb27SDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
31406c3fb27SDimitry Andric to_chars(char* __first, char* __last, _Tp __value, int __base) {
31506c3fb27SDimitry Andric   _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
31606c3fb27SDimitry Andric 
31706c3fb27SDimitry Andric   using _Type = __make_32_64_or_128_bit_t<_Tp>;
31806c3fb27SDimitry Andric   return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>());
31906c3fb27SDimitry Andric }
32006c3fb27SDimitry Andric 
32106c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17
32206c3fb27SDimitry Andric 
32306c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
32406c3fb27SDimitry Andric 
32506c3fb27SDimitry Andric _LIBCPP_POP_MACROS
32606c3fb27SDimitry Andric 
32706c3fb27SDimitry Andric #endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
328