345 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//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 _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H11#define _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H12 13#include <__algorithm/copy_n.h>14#include <__assert>15#include <__bit/countl.h>16#include <__charconv/tables.h>17#include <__charconv/to_chars_base_10.h>18#include <__charconv/to_chars_result.h>19#include <__charconv/traits.h>20#include <__config>21#include <__cstddef/ptrdiff_t.h>22#include <__system_error/errc.h>23#include <__type_traits/enable_if.h>24#include <__type_traits/integral_constant.h>25#include <__type_traits/is_integral.h>26#include <__type_traits/is_same.h>27#include <__type_traits/is_signed.h>28#include <__type_traits/make_32_64_or_128_bit.h>29#include <__type_traits/make_unsigned.h>30#include <__utility/unreachable.h>31#include <cstdint>32#include <limits>33 34#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)35# pragma GCC system_header36#endif37 38_LIBCPP_PUSH_MACROS39#include <__undef_macros>40 41_LIBCPP_BEGIN_NAMESPACE_STD42 43template <typename _Tp>44inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result45__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type);46 47template <typename _Tp>48inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result49__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) {50 auto __x = std::__to_unsigned_like(__value);51 if (__value < 0 && __first != __last) {52 *__first++ = '-';53 __x = std::__complement(__x);54 }55 56 return std::__to_chars_itoa(__first, __last, __x, false_type());57}58 59template <typename _Tp>60inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result61__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) {62 using __tx = __itoa::__traits<_Tp>;63 auto __diff = __last - __first;64 65 if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)66 return {__tx::__convert(__first, __value), errc(0)};67 else68 return {__last, errc::value_too_large};69}70 71# if _LIBCPP_HAS_INT12872template <>73inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result74__to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) {75 // When the value fits in 64-bits use the 64-bit code path. This reduces76 // the number of expensive calculations on 128-bit values.77 //78 // NOTE the 128-bit code path requires this optimization.79 if (__value <= numeric_limits<uint64_t>::max())80 return __to_chars_itoa(__first, __last, static_cast<uint64_t>(__value), false_type());81 82 using __tx = __itoa::__traits<__uint128_t>;83 auto __diff = __last - __first;84 85 if (__tx::digits <= __diff || __tx::__width(__value) <= __diff)86 return {__tx::__convert(__first, __value), errc(0)};87 else88 return {__last, errc::value_too_large};89}90# endif91 92template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> = 0>93inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result94__to_chars_integral(char* __first, char* __last, _Tp __value, int __base);95 96template <class _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>97inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result98__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {99 auto __x = std::__to_unsigned_like(__value);100 if (__value < 0 && __first != __last) {101 *__first++ = '-';102 __x = std::__complement(__x);103 }104 105 return std::__to_chars_integral(__first, __last, __x, __base);106}107 108namespace __itoa {109 110template <unsigned _Base>111struct _LIBCPP_HIDDEN __integral;112 113template <>114struct _LIBCPP_HIDDEN __integral<2> {115 template <typename _Tp>116 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {117 // If value == 0 still need one digit. If the value != this has no118 // effect since the code scans for the most significant bit set.119 return numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1);120 }121 122 template <typename _Tp>123 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result124 __to_chars(char* __first, char* __last, _Tp __value) {125 ptrdiff_t __cap = __last - __first;126 int __n = __width(__value);127 if (__n > __cap)128 return {__last, errc::value_too_large};129 130 __last = __first + __n;131 char* __p = __last;132 const unsigned __divisor = 16;133 while (__value > __divisor) {134 unsigned __c = __value % __divisor;135 __value /= __divisor;136 __p -= 4;137 std::copy_n(&__base_2_lut[4 * __c], 4, __p);138 }139 do {140 unsigned __c = __value % 2;141 __value /= 2;142 *--__p = "01"[__c];143 } while (__value != 0);144 return {__last, errc(0)};145 }146};147 148template <>149struct _LIBCPP_HIDDEN __integral<8> {150 template <typename _Tp>151 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {152 // If value == 0 still need one digit. If the value != this has no153 // effect since the code scans for the most significat bit set.154 return ((numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1)) + 2) / 3;155 }156 157 template <typename _Tp>158 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result159 __to_chars(char* __first, char* __last, _Tp __value) {160 ptrdiff_t __cap = __last - __first;161 int __n = __width(__value);162 if (__n > __cap)163 return {__last, errc::value_too_large};164 165 __last = __first + __n;166 char* __p = __last;167 unsigned __divisor = 64;168 while (__value > __divisor) {169 unsigned __c = __value % __divisor;170 __value /= __divisor;171 __p -= 2;172 std::copy_n(&__base_8_lut[2 * __c], 2, __p);173 }174 do {175 unsigned __c = __value % 8;176 __value /= 8;177 *--__p = "01234567"[__c];178 } while (__value != 0);179 return {__last, errc(0)};180 }181};182 183template <>184struct _LIBCPP_HIDDEN __integral<16> {185 template <typename _Tp>186 _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {187 // If value == 0 still need one digit. If the value != this has no188 // effect since the code scans for the most significat bit set.189 return (numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1) + 3) / 4;190 }191 192 template <typename _Tp>193 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result194 __to_chars(char* __first, char* __last, _Tp __value) {195 ptrdiff_t __cap = __last - __first;196 int __n = __width(__value);197 if (__n > __cap)198 return {__last, errc::value_too_large};199 200 __last = __first + __n;201 char* __p = __last;202 unsigned __divisor = 256;203 while (__value > __divisor) {204 unsigned __c = __value % __divisor;205 __value /= __divisor;206 __p -= 2;207 std::copy_n(&__base_16_lut[2 * __c], 2, __p);208 }209 if (__first != __last)210 do {211 unsigned __c = __value % 16;212 __value /= 16;213 *--__p = "0123456789abcdef"[__c];214 } while (__value != 0);215 return {__last, errc(0)};216 }217};218 219} // namespace __itoa220 221template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>222_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) {223 return __itoa::__integral<_Base>::__width(__value);224}225 226template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>227_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) {228 return std::__to_chars_integral_width<_Base>(static_cast<unsigned>(__value));229}230 231template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>232_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result233__to_chars_integral(char* __first, char* __last, _Tp __value) {234 return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);235}236 237template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>238_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result239__to_chars_integral(char* __first, char* __last, _Tp __value) {240 return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));241}242 243template <typename _Tp>244_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value, unsigned __base) {245 _LIBCPP_ASSERT_INTERNAL(__value >= 0, "The function requires a non-negative value.");246 247 unsigned __base_2 = __base * __base;248 unsigned __base_3 = __base_2 * __base;249 unsigned __base_4 = __base_2 * __base_2;250 251 int __r = 0;252 while (true) {253 if (__value < __base)254 return __r + 1;255 if (__value < __base_2)256 return __r + 2;257 if (__value < __base_3)258 return __r + 3;259 if (__value < __base_4)260 return __r + 4;261 262 __value /= __base_4;263 __r += 4;264 }265 266 __libcpp_unreachable();267}268 269template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> >270inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result271__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {272 if (__base == 10) [[likely]]273 return std::__to_chars_itoa(__first, __last, __value, false_type());274 275 switch (__base) {276 case 2:277 return std::__to_chars_integral<2>(__first, __last, __value);278 case 8:279 return std::__to_chars_integral<8>(__first, __last, __value);280 case 16:281 return std::__to_chars_integral<16>(__first, __last, __value);282 }283 284 ptrdiff_t __cap = __last - __first;285 int __n = std::__to_chars_integral_width(__value, __base);286 if (__n > __cap)287 return {__last, errc::value_too_large};288 289 __last = __first + __n;290 char* __p = __last;291 do {292 unsigned __c = __value % __base;293 __value /= __base;294 *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];295 } while (__value != 0);296 return {__last, errc(0)};297}298 299_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) {300 switch (__c) {301 case 'a':302 return 'A';303 case 'b':304 return 'B';305 case 'c':306 return 'C';307 case 'd':308 return 'D';309 case 'e':310 return 'E';311 case 'f':312 return 'F';313 }314 return __c;315}316 317#if _LIBCPP_STD_VER >= 17318 319to_chars_result to_chars(char*, char*, bool, int = 10) = delete;320 321template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>322inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result323to_chars(char* __first, char* __last, _Tp __value) {324 using _Type = __make_32_64_or_128_bit_t<_Tp>;325 static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars");326 return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>());327}328 329template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>330inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result331to_chars(char* __first, char* __last, _Tp __value, int __base) {332 _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");333 334 using _Type = __make_32_64_or_128_bit_t<_Tp>;335 return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base);336}337 338#endif // _LIBCPP_STD_VER >= 17339 340_LIBCPP_END_NAMESPACE_STD341 342_LIBCPP_POP_MACROS343 344#endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H345