brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.3 KiB · 6d42513 Raw
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