Skip to content

Commit 15edf87

Browse files
authored
[libc++] Optimize num_put integral functions (#120859)
``` ------------------------------------------------------- Benchmark old new ------------------------------------------------------- BM_num_put<bool> 76.2 ns 32.0 ns BM_num_put<long> 76.9 ns 33.1 ns BM_num_put<long long> 77.9 ns 34.2 ns BM_num_put<unsigned long> 78.4 ns 33.1 ns BM_num_put<unsigned long long> 78.0 ns 34.4 ns BM_num_put<double> 224 ns 228 ns BM_num_put<long double> 239 ns 230 ns BM_num_put<const void*> 68.7 ns 35.1 ns ``` Fixes #40109.
1 parent 8c0e9ad commit 15edf87

File tree

13 files changed

+209
-149
lines changed

13 files changed

+209
-149
lines changed

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ Improvements and New Features
120120

121121
- Added :ref:`hardening mode <hardening>` support for ``forward_list`` and ``bitset``.
122122

123+
- The ``num_get::do_put`` integral overloads have been optimized, resulting in a performance improvement of up to 2.4x.
124+
123125
Deprecations and Removals
124126
-------------------------
125127

libcxx/include/__charconv/tables.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,22 @@
1919

2020
_LIBCPP_BEGIN_NAMESPACE_STD
2121

22-
#if _LIBCPP_STD_VER >= 17
23-
2422
namespace __itoa {
2523

26-
inline constexpr char __base_2_lut[64] = {
24+
inline _LIBCPP_CONSTEXPR const char __base_2_lut[64] = {
2725
'0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '0', '0', '0', '1',
2826
'0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '0', '1', '0', '0', '1', '1', '0', '1', '0',
2927
'1', '0', '1', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1', '1', '1'};
3028

31-
inline constexpr char __base_8_lut[128] = {
29+
inline _LIBCPP_CONSTEXPR const char __base_8_lut[128] = {
3230
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '1', '0', '1', '1', '1', '2',
3331
'1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5',
3432
'2', '6', '2', '7', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '4', '0',
3533
'4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '5', '0', '5', '1', '5', '2', '5', '3',
3634
'5', '4', '5', '5', '5', '6', '5', '7', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6',
3735
'6', '7', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7'};
3836

39-
inline constexpr char __base_16_lut[512] = {
37+
inline _LIBCPP_CONSTEXPR const char __base_16_lut[512] = {
4038
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0', 'a', '0',
4139
'b', '0', 'c', '0', 'd', '0', 'e', '0', 'f', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6',
4240
'1', '7', '1', '8', '1', '9', '1', 'a', '1', 'b', '1', 'c', '1', 'd', '1', 'e', '1', 'f', '2', '0', '2', '1', '2',
@@ -61,7 +59,7 @@ inline constexpr char __base_16_lut[512] = {
6159
'1', 'f', '2', 'f', '3', 'f', '4', 'f', '5', 'f', '6', 'f', '7', 'f', '8', 'f', '9', 'f', 'a', 'f', 'b', 'f', 'c',
6260
'f', 'd', 'f', 'e', 'f', 'f'};
6361

64-
inline constexpr uint32_t __pow10_32[10] = {
62+
inline _LIBCPP_CONSTEXPR const uint32_t __pow10_32[10] = {
6563
UINT32_C(0),
6664
UINT32_C(10),
6765
UINT32_C(100),
@@ -73,7 +71,7 @@ inline constexpr uint32_t __pow10_32[10] = {
7371
UINT32_C(100000000),
7472
UINT32_C(1000000000)};
7573

76-
inline constexpr uint64_t __pow10_64[20] = {
74+
inline _LIBCPP_CONSTEXPR const uint64_t __pow10_64[20] = {
7775
UINT64_C(0),
7876
UINT64_C(10),
7977
UINT64_C(100),
@@ -96,8 +94,8 @@ inline constexpr uint64_t __pow10_64[20] = {
9694
UINT64_C(10000000000000000000)};
9795

9896
# if _LIBCPP_HAS_INT128
99-
inline constexpr int __pow10_128_offset = 0;
100-
inline constexpr __uint128_t __pow10_128[40] = {
97+
inline _LIBCPP_CONSTEXPR const int __pow10_128_offset = 0;
98+
inline _LIBCPP_CONSTEXPR const __uint128_t __pow10_128[40] = {
10199
UINT64_C(0),
102100
UINT64_C(10),
103101
UINT64_C(100),
@@ -140,7 +138,7 @@ inline constexpr __uint128_t __pow10_128[40] = {
140138
(__uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000000000)) * 10};
141139
# endif
142140

143-
inline constexpr char __digits_base_10[200] = {
141+
inline _LIBCPP_CONSTEXPR const char __digits_base_10[200] = {
144142
// clang-format off
145143
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
146144
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
@@ -156,8 +154,6 @@ inline constexpr char __digits_base_10[200] = {
156154

157155
} // namespace __itoa
158156

159-
#endif // _LIBCPP_STD_VER >= 17
160-
161157
_LIBCPP_END_NAMESPACE_STD
162158

163159
#endif // _LIBCPP___CHARCONV_TABLES

libcxx/include/__charconv/to_chars_base_10.h

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,55 +26,53 @@ _LIBCPP_PUSH_MACROS
2626

2727
_LIBCPP_BEGIN_NAMESPACE_STD
2828

29-
#if _LIBCPP_STD_VER >= 17
30-
3129
namespace __itoa {
3230

33-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) noexcept {
31+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) _NOEXCEPT {
3432
*__first = '0' + static_cast<char>(__value);
3533
return __first + 1;
3634
}
3735

38-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) noexcept {
36+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) _NOEXCEPT {
3937
return std::copy_n(&__digits_base_10[__value * 2], 2, __first);
4038
}
4139

42-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) noexcept {
40+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) _NOEXCEPT {
4341
return __itoa::__append2(__itoa::__append1(__first, __value / 100), __value % 100);
4442
}
4543

46-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) noexcept {
44+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) _NOEXCEPT {
4745
return __itoa::__append2(__itoa::__append2(__first, __value / 100), __value % 100);
4846
}
4947

50-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) noexcept {
48+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) _NOEXCEPT {
5149
return __itoa::__append4(__itoa::__append1(__first, __value / 10000), __value % 10000);
5250
}
5351

54-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) noexcept {
52+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) _NOEXCEPT {
5553
return __itoa::__append4(__itoa::__append2(__first, __value / 10000), __value % 10000);
5654
}
5755

58-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) noexcept {
56+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) _NOEXCEPT {
5957
return __itoa::__append6(__itoa::__append1(__first, __value / 1000000), __value % 1000000);
6058
}
6159

62-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) noexcept {
60+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) _NOEXCEPT {
6361
return __itoa::__append6(__itoa::__append2(__first, __value / 1000000), __value % 1000000);
6462
}
6563

66-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) noexcept {
64+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) _NOEXCEPT {
6765
return __itoa::__append8(__itoa::__append1(__first, __value / 100000000), __value % 100000000);
6866
}
6967

7068
template <class _Tp>
71-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) noexcept {
69+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) _NOEXCEPT {
7270
return __itoa::__append8(__itoa::__append2(__first, static_cast<uint32_t>(__value / 100000000)),
7371
static_cast<uint32_t>(__value % 100000000));
7472
}
7573

7674
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
77-
__base_10_u32(char* __first, uint32_t __value) noexcept {
75+
__base_10_u32(char* __first, uint32_t __value) _NOEXCEPT {
7876
if (__value < 1000000) {
7977
if (__value < 10000) {
8078
if (__value < 100) {
@@ -110,7 +108,7 @@ __base_10_u32(char* __first, uint32_t __value) noexcept {
110108
}
111109

112110
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
113-
__base_10_u64(char* __buffer, uint64_t __value) noexcept {
111+
__base_10_u64(char* __buffer, uint64_t __value) _NOEXCEPT {
114112
if (__value <= UINT32_MAX)
115113
return __itoa::__base_10_u32(__buffer, static_cast<uint32_t>(__value));
116114

@@ -132,13 +130,13 @@ __base_10_u64(char* __buffer, uint64_t __value) noexcept {
132130
/// \note The lookup table contains a partial set of exponents limiting the
133131
/// range that can be used. However the range is sufficient for
134132
/// \ref __base_10_u128.
135-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) noexcept {
133+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) _NOEXCEPT {
136134
_LIBCPP_ASSERT_INTERNAL(__exp >= __pow10_128_offset, "Index out of bounds");
137135
return __pow10_128[__exp - __pow10_128_offset];
138136
}
139137

140138
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
141-
__base_10_u128(char* __buffer, __uint128_t __value) noexcept {
139+
__base_10_u128(char* __buffer, __uint128_t __value) _NOEXCEPT {
142140
_LIBCPP_ASSERT_INTERNAL(
143141
__value > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fails when this isn't true.");
144142

@@ -179,8 +177,6 @@ __base_10_u128(char* __buffer, __uint128_t __value) noexcept {
179177
# endif
180178
} // namespace __itoa
181179

182-
#endif // _LIBCPP_STD_VER >= 17
183-
184180
_LIBCPP_END_NAMESPACE_STD
185181

186182
_LIBCPP_POP_MACROS

libcxx/include/__charconv/to_chars_integral.h

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,12 @@ _LIBCPP_PUSH_MACROS
3939

4040
_LIBCPP_BEGIN_NAMESPACE_STD
4141

42-
#if _LIBCPP_STD_VER >= 17
43-
44-
to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
45-
4642
template <typename _Tp>
47-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
43+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
4844
__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type);
4945

5046
template <typename _Tp>
51-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
47+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
5248
__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) {
5349
auto __x = std::__to_unsigned_like(__value);
5450
if (__value < 0 && __first != __last) {
@@ -60,7 +56,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) {
6056
}
6157

6258
template <typename _Tp>
63-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
59+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
6460
__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) {
6561
using __tx = __itoa::__traits<_Tp>;
6662
auto __diff = __last - __first;
@@ -73,7 +69,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) {
7369

7470
# if _LIBCPP_HAS_INT128
7571
template <>
76-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
72+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
7773
__to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) {
7874
// When the value fits in 64-bits use the 64-bit code path. This reduces
7975
// the number of expensive calculations on 128-bit values.
@@ -92,20 +88,20 @@ __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) {
9288
}
9389
# endif
9490

95-
template <class _Tp>
96-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
97-
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type);
91+
template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> = 0>
92+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
93+
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base);
9894

99-
template <typename _Tp>
100-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
101-
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, true_type) {
95+
template <class _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
96+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
97+
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {
10298
auto __x = std::__to_unsigned_like(__value);
10399
if (__value < 0 && __first != __last) {
104100
*__first++ = '-';
105101
__x = std::__complement(__x);
106102
}
107103

108-
return std::__to_chars_integral(__first, __last, __x, __base, false_type());
104+
return std::__to_chars_integral(__first, __last, __x, __base);
109105
}
110106

111107
namespace __itoa {
@@ -116,15 +112,15 @@ struct _LIBCPP_HIDDEN __integral;
116112
template <>
117113
struct _LIBCPP_HIDDEN __integral<2> {
118114
template <typename _Tp>
119-
_LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
115+
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
120116
// If value == 0 still need one digit. If the value != this has no
121117
// effect since the code scans for the most significant bit set. (Note
122118
// that __libcpp_clz doesn't work for 0.)
123119
return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1);
124120
}
125121

126122
template <typename _Tp>
127-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
123+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result
128124
__to_chars(char* __first, char* __last, _Tp __value) {
129125
ptrdiff_t __cap = __last - __first;
130126
int __n = __width(__value);
@@ -152,15 +148,15 @@ struct _LIBCPP_HIDDEN __integral<2> {
152148
template <>
153149
struct _LIBCPP_HIDDEN __integral<8> {
154150
template <typename _Tp>
155-
_LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
151+
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
156152
// If value == 0 still need one digit. If the value != this has no
157153
// effect since the code scans for the most significat bit set. (Note
158154
// that __libcpp_clz doesn't work for 0.)
159155
return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3;
160156
}
161157

162158
template <typename _Tp>
163-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
159+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result
164160
__to_chars(char* __first, char* __last, _Tp __value) {
165161
ptrdiff_t __cap = __last - __first;
166162
int __n = __width(__value);
@@ -188,15 +184,15 @@ struct _LIBCPP_HIDDEN __integral<8> {
188184
template <>
189185
struct _LIBCPP_HIDDEN __integral<16> {
190186
template <typename _Tp>
191-
_LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
187+
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
192188
// If value == 0 still need one digit. If the value != this has no
193189
// effect since the code scans for the most significat bit set. (Note
194190
// that __libcpp_clz doesn't work for 0.)
195191
return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4;
196192
}
197193

198194
template <typename _Tp>
199-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
195+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result
200196
__to_chars(char* __first, char* __last, _Tp __value) {
201197
ptrdiff_t __cap = __last - __first;
202198
int __n = __width(__value);
@@ -235,13 +231,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_widt
235231
}
236232

237233
template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>
238-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
234+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
239235
__to_chars_integral(char* __first, char* __last, _Tp __value) {
240236
return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);
241237
}
242238

243239
template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>
244-
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
240+
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
245241
__to_chars_integral(char* __first, char* __last, _Tp __value) {
246242
return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));
247243
}
@@ -272,9 +268,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_widt
272268
__libcpp_unreachable();
273269
}
274270

275-
template <typename _Tp>
276-
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
277-
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type) {
271+
template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> >
272+
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
273+
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {
278274
if (__base == 10) [[likely]]
279275
return std::__to_chars_itoa(__first, __last, __value, false_type());
280276

@@ -302,6 +298,28 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_
302298
return {__last, errc(0)};
303299
}
304300

301+
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) {
302+
switch (__c) {
303+
case 'a':
304+
return 'A';
305+
case 'b':
306+
return 'B';
307+
case 'c':
308+
return 'C';
309+
case 'd':
310+
return 'D';
311+
case 'e':
312+
return 'E';
313+
case 'f':
314+
return 'F';
315+
}
316+
return __c;
317+
}
318+
319+
#if _LIBCPP_STD_VER >= 17
320+
321+
to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
322+
305323
template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
306324
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
307325
to_chars(char* __first, char* __last, _Tp __value) {
@@ -316,7 +334,7 @@ to_chars(char* __first, char* __last, _Tp __value, int __base) {
316334
_LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
317335

318336
using _Type = __make_32_64_or_128_bit_t<_Tp>;
319-
return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>());
337+
return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base);
320338
}
321339

322340
#endif // _LIBCPP_STD_VER >= 17

libcxx/include/__charconv/to_chars_result.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ struct _LIBCPP_EXPORTED_FROM_ABI to_chars_result {
3434

3535
#endif // _LIBCPP_STD_VER >= 17
3636

37+
struct __to_chars_result {
38+
char* __ptr;
39+
errc __ec;
40+
41+
#if _LIBCPP_STD_VER >= 17
42+
_LIBCPP_HIDE_FROM_ABI constexpr operator to_chars_result() { return {__ptr, __ec}; }
43+
#endif
44+
};
45+
3746
_LIBCPP_END_NAMESPACE_STD
3847

3948
#endif // _LIBCPP___CHARCONV_TO_CHARS_RESULT_H

0 commit comments

Comments
 (0)