Files
Cpp-in-Embedded-Systems/Chapter17/cib/libs/stdx/udls.hpp
Amar Mahmutbegovic 526e6ec009 rename chapters
2025-02-09 13:11:21 +01:00

168 lines
4.9 KiB
C++

#pragma once
#include <stdx/compiler.hpp>
#include <stdx/type_traits.hpp>
#include <cstddef>
#include <cstdint>
#include <type_traits>
namespace stdx {
inline namespace v1 {
namespace detail {
template <char C> constexpr static bool is_digit_sep_v = C == '\'';
template <char C>
constexpr static bool is_decimal_digit_v = C >= '0' and C <= '9';
template <char C>
constexpr static bool is_octal_digit_v = C >= '0' and C <= '7';
template <char C>
constexpr static bool is_binary_digit_v = C >= '0' and C <= '1';
template <char C>
constexpr static char force_lower_case = static_cast<unsigned char>(C) | 32u;
template <char C>
constexpr static bool is_hex_digit_v =
(C >= '0' and C <= '9') or
(force_lower_case<C> >= 'a' and force_lower_case<C> <= 'f');
template <char C>
constexpr static auto integral_value_v =
is_decimal_digit_v<C> ? C - '0' : force_lower_case<C> - 'a' + 10;
template <auto Base, char C, typename Sum>
CONSTEVAL auto maybe_add_digit(Sum s) {
if constexpr (not is_digit_sep_v<C>) {
s *= Base;
s += integral_value_v<C>;
}
return s;
}
template <auto Base, char... Cs> struct raw_parser {
template <typename T> CONSTEVAL static auto parse() {
using U = decltype(stdx::to_underlying(std::declval<T>()));
auto x = U{};
((x = maybe_add_digit<Base, Cs>(x)), ...);
return T{x};
}
};
template <char... Cs> struct parser : raw_parser<10, Cs...> {
static_assert((... and (is_decimal_digit_v<Cs> or is_digit_sep_v<Cs>)));
};
template <char... Cs> struct parser<'0', Cs...> : raw_parser<8, Cs...> {
static_assert((... and (is_octal_digit_v<Cs> or is_digit_sep_v<Cs>)));
};
template <char... Cs> struct parser<'0', 'x', Cs...> : raw_parser<16, Cs...> {
static_assert((... and (is_hex_digit_v<Cs> or is_digit_sep_v<Cs>)));
};
template <char... Cs>
struct parser<'0', 'X', Cs...> : parser<'0', 'x', Cs...> {};
template <char... Cs> struct parser<'0', 'b', Cs...> : raw_parser<2, Cs...> {
static_assert((... and (is_binary_digit_v<Cs> or is_digit_sep_v<Cs>)));
};
template <char... Cs>
struct parser<'0', 'B', Cs...> : parser<'0', 'b', Cs...> {};
} // namespace detail
template <typename T, char... Chars> CONSTEVAL auto parse_literal() -> T {
using parser_t = detail::parser<Chars...>;
return parser_t::template parse<T>();
}
template <auto I> using constant = std::integral_constant<decltype(I), I>;
template <auto I> constexpr static constant<I> _c{};
inline namespace literals {
template <char... Chars> CONSTEVAL auto operator""_c() {
return _c<parse_literal<std::uint32_t, Chars...>()>;
}
} // namespace literals
enum struct lsb_t : std::uint32_t {};
enum struct msb_t : std::uint32_t {};
enum struct length_t : std::uint32_t {};
inline namespace literals {
// NOLINTBEGIN(google-runtime-int)
CONSTEVAL auto operator""_lsb(unsigned long long int n) -> lsb_t {
return static_cast<lsb_t>(n);
}
CONSTEVAL auto operator""_msb(unsigned long long int n) -> msb_t {
return static_cast<msb_t>(n);
}
CONSTEVAL auto operator""_len(unsigned long long int n) -> length_t {
return static_cast<length_t>(n);
}
// NOLINTEND(google-runtime-int)
} // namespace literals
inline namespace literals {
CONSTEVAL auto operator""_b(char const *, std::size_t) -> bool { return true; }
CONSTEVAL auto operator""_true(char const *, std::size_t) -> bool {
return true;
}
CONSTEVAL auto operator""_false(char const *, std::size_t) -> bool {
return false;
}
// NOLINTBEGIN(google-runtime-int)
CONSTEVAL auto
operator""_k(unsigned long long int n) -> unsigned long long int {
return n * 1'000u;
}
CONSTEVAL auto
operator""_M(unsigned long long int n) -> unsigned long long int {
return n * 1'000'000u;
}
CONSTEVAL auto
operator""_G(unsigned long long int n) -> unsigned long long int {
return n * 1'000'000'000u;
}
CONSTEVAL auto
operator""_ki(unsigned long long int n) -> unsigned long long int {
return n * 1'024u;
}
CONSTEVAL auto
operator""_Mi(unsigned long long int n) -> unsigned long long int {
return n * 1'024ull * 1'024ull;
}
CONSTEVAL auto
operator""_Gi(unsigned long long int n) -> unsigned long long int {
return n * 1'024ull * 1'024ull * 1'024ull;
}
// NOLINTBEGIN(cppcoreguidelines-macro-usage)
#define STDX_SMALL_INT_LITERAL_DEF(x) \
CONSTEVAL auto operator""_##x(char const *, std::size_t) \
->std::integral_constant<std::size_t, x##u> { \
return {}; \
}
STDX_SMALL_INT_LITERAL_DEF(0)
STDX_SMALL_INT_LITERAL_DEF(1)
STDX_SMALL_INT_LITERAL_DEF(2)
STDX_SMALL_INT_LITERAL_DEF(3)
STDX_SMALL_INT_LITERAL_DEF(4)
STDX_SMALL_INT_LITERAL_DEF(5)
STDX_SMALL_INT_LITERAL_DEF(6)
STDX_SMALL_INT_LITERAL_DEF(7)
STDX_SMALL_INT_LITERAL_DEF(8)
STDX_SMALL_INT_LITERAL_DEF(9)
#undef STDX_SMALL_INT_LITERAL_DEF
// NOLINTEND(cppcoreguidelines-macro-usage)
// NOLINTEND(google-runtime-int)
} // namespace literals
} // namespace v1
} // namespace stdx