| 1 | //===-- User literal for unsigned integers ----------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // This set of user defined literals allows uniform constructions of constants |
| 9 | // up to 256 bits and also help with unit tests (EXPECT_EQ requires the same |
| 10 | // type for LHS and RHS). |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #ifndef LLVM_LIBC_SRC___SUPPORT_INTEGER_LITERALS_H |
| 14 | #define LLVM_LIBC_SRC___SUPPORT_INTEGER_LITERALS_H |
| 15 | |
| 16 | #include "hdr/stdint_proxy.h" // uintxx_t |
| 17 | #include "src/__support/CPP/limits.h" // CHAR_BIT |
| 18 | #include "src/__support/ctype_utils.h" |
| 19 | #include "src/__support/macros/attributes.h" // LIBC_INLINE |
| 20 | #include "src/__support/macros/config.h" |
| 21 | #include "src/__support/uint128.h" // UInt128 |
| 22 | #include <stddef.h> // size_t |
| 23 | |
| 24 | namespace LIBC_NAMESPACE_DECL { |
| 25 | |
| 26 | LIBC_INLINE constexpr uint8_t operator""_u8 (unsigned long long value) { |
| 27 | return static_cast<uint8_t>(value); |
| 28 | } |
| 29 | |
| 30 | LIBC_INLINE constexpr uint16_t operator""_u16 (unsigned long long value) { |
| 31 | return static_cast<uint16_t>(value); |
| 32 | } |
| 33 | |
| 34 | LIBC_INLINE constexpr uint32_t operator""_u32 (unsigned long long value) { |
| 35 | return static_cast<uint32_t>(value); |
| 36 | } |
| 37 | |
| 38 | LIBC_INLINE constexpr uint64_t operator""_u64 (unsigned long long value) { |
| 39 | return static_cast<uint64_t>(value); |
| 40 | } |
| 41 | |
| 42 | namespace internal { |
| 43 | |
| 44 | // Creates a T by reading digits from an array. |
| 45 | template <typename T> |
| 46 | LIBC_INLINE constexpr T accumulate(int base, const uint8_t *digits, |
| 47 | size_t size) { |
| 48 | T value{}; |
| 49 | for (; size; ++digits, --size) { |
| 50 | value *= static_cast<unsigned int>(base); |
| 51 | value += *digits; |
| 52 | } |
| 53 | return value; |
| 54 | } |
| 55 | |
| 56 | // A static buffer to hold the digits for a T. |
| 57 | template <typename T, int base> struct DigitBuffer { |
| 58 | static_assert(base == 2 || base == 10 || base == 16); |
| 59 | // One character provides log2(base) bits. |
| 60 | // Base 2 and 16 provide exactly one and four bits per character respectively. |
| 61 | // For base 10, a character provides log2(10) ≈ 3.32... which we round to 3 |
| 62 | // for the purpose of buffer allocation. |
| 63 | LIBC_INLINE_VAR static constexpr size_t BITS_PER_DIGIT = base == 2 ? 1 |
| 64 | : base == 10 ? 3 |
| 65 | : base == 16 ? 4 |
| 66 | : 0; |
| 67 | LIBC_INLINE_VAR static constexpr size_t MAX_DIGITS = |
| 68 | sizeof(T) * CHAR_BIT / BITS_PER_DIGIT; |
| 69 | LIBC_INLINE_VAR static constexpr uint8_t INVALID_DIGIT = 255; |
| 70 | |
| 71 | uint8_t digits[MAX_DIGITS] = {}; |
| 72 | size_t size = 0; |
| 73 | |
| 74 | constexpr DigitBuffer(const char *str) { |
| 75 | for (; *str != '\0'; ++str) |
| 76 | push(c: *str); |
| 77 | } |
| 78 | |
| 79 | // Adds a single character to this buffer. |
| 80 | LIBC_INLINE constexpr void push(char c) { |
| 81 | if (c == '\'') |
| 82 | return; // ' is valid but not taken into account. |
| 83 | const int b36_val = internal::b36_char_to_int(ch: c); |
| 84 | const uint8_t value = static_cast<uint8_t>( |
| 85 | b36_val < base && (b36_val != 0 || c == '0') ? b36_val : INVALID_DIGIT); |
| 86 | if (value == INVALID_DIGIT || size >= MAX_DIGITS) { |
| 87 | // During constant evaluation `__builtin_unreachable` will halt the |
| 88 | // compiler as it is not executable. This is preferable over `assert` that |
| 89 | // will only trigger in debug mode. Also we can't use `static_assert` |
| 90 | // because `value` and `size` are not constant. |
| 91 | __builtin_unreachable(); // invalid or too many characters. |
| 92 | } |
| 93 | digits[size] = value; |
| 94 | ++size; |
| 95 | } |
| 96 | }; |
| 97 | |
| 98 | // Generic implementation for native types (including __uint128_t or ExtInt |
| 99 | // where available). |
| 100 | template <typename T> struct Parser { |
| 101 | template <int base> LIBC_INLINE static constexpr T parse(const char *str) { |
| 102 | const DigitBuffer<T, base> buffer(str); |
| 103 | return accumulate<T>(base, buffer.digits, buffer.size); |
| 104 | } |
| 105 | }; |
| 106 | |
| 107 | // Specialization for UInt<N>. |
| 108 | // Because this code runs at compile time we try to make it efficient. For |
| 109 | // binary and hexadecimal formats we read digits by chunks of 64 bits and |
| 110 | // produce the BigInt internal representation direcly. For decimal numbers we |
| 111 | // go the slow path and use slower BigInt arithmetic. |
| 112 | template <size_t N> struct Parser<LIBC_NAMESPACE::UInt<N>> { |
| 113 | using UIntT = UInt<N>; |
| 114 | template <int base> static constexpr UIntT parse(const char *str) { |
| 115 | const DigitBuffer<UIntT, base> buffer(str); |
| 116 | if constexpr (base == 10) { |
| 117 | // Slow path, we sum and multiply BigInt for each digit. |
| 118 | return accumulate<UIntT>(base, buffer.digits, buffer.size); |
| 119 | } else { |
| 120 | // Fast path, we consume blocks of WordType and creates the BigInt's |
| 121 | // internal representation directly. |
| 122 | using WordArrayT = decltype(UIntT::val); |
| 123 | using WordType = typename WordArrayT::value_type; |
| 124 | WordArrayT array = {}; |
| 125 | size_t size = buffer.size; |
| 126 | const uint8_t *digit_ptr = buffer.digits + size; |
| 127 | for (size_t i = 0; i < array.size(); ++i) { |
| 128 | constexpr size_t DIGITS = DigitBuffer<WordType, base>::MAX_DIGITS; |
| 129 | const size_t chunk = size > DIGITS ? DIGITS : size; |
| 130 | digit_ptr -= chunk; |
| 131 | size -= chunk; |
| 132 | array[i] = accumulate<WordType>(base, digit_ptr, chunk); |
| 133 | } |
| 134 | return UIntT(array); |
| 135 | } |
| 136 | } |
| 137 | }; |
| 138 | |
| 139 | // Detects the base of the number and dispatches to the right implementation. |
| 140 | template <typename T> |
| 141 | LIBC_INLINE constexpr T parse_with_prefix(const char *ptr) { |
| 142 | using P = Parser<T>; |
| 143 | if (ptr == nullptr) |
| 144 | return T(); |
| 145 | if (ptr[0] == '0') { |
| 146 | if (ptr[1] == 'b') |
| 147 | return P::template parse<2>(ptr + 2); |
| 148 | if (ptr[1] == 'x') |
| 149 | return P::template parse<16>(ptr + 2); |
| 150 | } |
| 151 | return P::template parse<10>(ptr); |
| 152 | } |
| 153 | |
| 154 | } // namespace internal |
| 155 | |
| 156 | LIBC_INLINE constexpr UInt<96> operator""_u96 (const char *x) { |
| 157 | return internal::parse_with_prefix<UInt<96>>(ptr: x); |
| 158 | } |
| 159 | |
| 160 | LIBC_INLINE constexpr UInt128 operator""_u128 (const char *x) { |
| 161 | return internal::parse_with_prefix<UInt128>(ptr: x); |
| 162 | } |
| 163 | |
| 164 | LIBC_INLINE constexpr auto operator""_u256 (const char *x) { |
| 165 | return internal::parse_with_prefix<UInt<256>>(ptr: x); |
| 166 | } |
| 167 | |
| 168 | template <typename T> LIBC_INLINE constexpr T parse_bigint(const char *ptr) { |
| 169 | if (ptr == nullptr) |
| 170 | return T(); |
| 171 | if (ptr[0] == '-' || ptr[0] == '+') { |
| 172 | auto positive = internal::parse_with_prefix<T>(ptr + 1); |
| 173 | return ptr[0] == '-' ? -positive : positive; |
| 174 | } |
| 175 | return internal::parse_with_prefix<T>(ptr); |
| 176 | } |
| 177 | |
| 178 | } // namespace LIBC_NAMESPACE_DECL |
| 179 | |
| 180 | #endif // LLVM_LIBC_SRC___SUPPORT_INTEGER_LITERALS_H |
| 181 | |