AsmGrader 0.0.0
Loading...
Searching...
No Matches
cconstexpr.hpp
Go to the documentation of this file.
1
9#pragma once
10
12
13#include <libassert/assert.hpp>
14
15#include <cctype>
16#include <cmath>
17#include <concepts>
18#include <cstdlib>
19#include <functional>
20#include <limits>
21#include <type_traits>
22
23namespace asmgrader {
24
25namespace detail {
26
28constexpr bool in_range(auto&& val, auto&& low, auto&& high) {
29 return val >= low && val <= high;
30}
31
32template <typename Type>
33consteval decltype(auto) resolve_overload(auto&& overloaded) {
34 return static_cast<std::add_pointer_t<Type>>((overloaded));
35}
36
37namespace cctype {
38
39template <typename Ret, typename... ExtraArgs>
40consteval auto make_safe_wrapper(int (&cfunc)(int, ExtraArgs...)) {
41 return [&cfunc](char c, ExtraArgs... other_args) -> Ret {
42 return static_cast<Ret>(std::invoke(cfunc, static_cast<unsigned char>(c), other_args...));
43 };
44}
45
46constexpr bool islower(char c) {
47 return in_range(c, 'a', 'z');
48}
49
50constexpr bool isupper(char c) {
51 return in_range(c, 'A', 'Z');
52}
53
54constexpr char tolower(char c) {
55 if (isupper(c)) {
56 return c += ('a' - 'A');
57 }
58 return c;
59}
60
61constexpr char toupper(char c) {
62 if (islower(c)) {
63 return c -= ('a' - 'A');
64 }
65 return c;
66}
67
68constexpr bool isdigit(char c) {
69 return c >= '0' && c <= '9';
70}
71
72constexpr bool isxdigit(char c) {
73 return isdigit(c) || in_range(tolower(c), 'a', 'f');
74}
75
76constexpr bool isalpha(char c) {
77 return islower(c) || isupper(c);
78}
79
80constexpr bool isalnum(char c) {
81 return isalpha(c) || isdigit(c);
82}
83
84// Using C doc table for ASCII values ranges
85// See the table at the bottom of https://en.cppreference.com/w/cpp/string/byte/isgraph.html
86
87constexpr bool iscntrl(char c) {
88 return c <= '\x1F' || c == '\x7F';
89}
90
91constexpr bool isgraph(char c) {
92 return detail::in_range(c, '\x20', '\x7E');
93}
94
95constexpr bool isprint(char c) {
96 return isgraph(c) || c == ' ';
97}
98
99constexpr bool isblank(char c) {
100 return c == '\t' || c == ' ';
101}
102
103constexpr bool isspace(char c) {
104 return isblank(c) || detail::in_range(c, '\xA', '\xD');
105}
106
107constexpr bool ispunct(char c) {
108 using detail::in_range;
109 return in_range(c, '\x21', '\x2F') || in_range(c, '\x3A', '\x40') || in_range(c, '\x5B', '\x60') ||
110 in_range(c, '\x7B', '\x7E');
111}
112
113} // namespace cctype
114
115} // namespace detail
116
117#define CCTYPE_IMPL(name, ret_type) \
118 constexpr ret_type name(char c) { \
119 if (std::is_constant_evaluated()) { \
120 return detail::cctype::name(c); \
121 } \
122 return detail::cctype::make_safe_wrapper<ret_type>(std::name)(c); \
123 }
124
125CCTYPE_IMPL(isdigit, bool);
126CCTYPE_IMPL(isxdigit, bool);
127CCTYPE_IMPL(islower, bool);
128CCTYPE_IMPL(isupper, bool);
129CCTYPE_IMPL(isalpha, bool);
130CCTYPE_IMPL(isalnum, bool);
131CCTYPE_IMPL(iscntrl, bool);
132CCTYPE_IMPL(isgraph, bool);
133CCTYPE_IMPL(isprint, bool);
134CCTYPE_IMPL(isblank, bool);
135CCTYPE_IMPL(isspace, bool);
136CCTYPE_IMPL(ispunct, bool);
137
138CCTYPE_IMPL(toupper, char);
139CCTYPE_IMPL(tolower, char);
140
141#undef CCTYPE_IMPL
142
143template <typename T>
144 requires std::is_arithmetic_v<T>
145constexpr T abs(T val) {
146 if (std::is_constant_evaluated()) {
147 if constexpr (std::integral<T> && std::is_signed_v<T>) {
148 ASSERT(val != std::numeric_limits<T>::min(), "abs of signed minimum would be UB");
149 }
150 return (val < 0 ? -val : val);
151 }
152
153 return std::abs(val);
154}
155
156template <typename BaseT, std::unsigned_integral ExpT>
157 requires std::is_arithmetic_v<BaseT>
158constexpr std::common_type_t<BaseT, ExpT> pow(BaseT base, ExpT exp) {
159 if (std::is_constant_evaluated()) {
160 auto val = 1;
161 while (exp-- > 0) {
162 val *= base;
163 }
164 return val;
165 }
166
167 return std::pow(base, exp);
168}
169
170} // namespace asmgrader
#define CCTYPE_IMPL(name, ret_type)
Definition cconstexpr.hpp:117
constexpr bool isupper(char c)
Definition cconstexpr.hpp:50
constexpr char tolower(char c)
Definition cconstexpr.hpp:54
constexpr bool isalnum(char c)
Definition cconstexpr.hpp:80
constexpr bool isprint(char c)
Definition cconstexpr.hpp:95
constexpr bool isalpha(char c)
Definition cconstexpr.hpp:76
constexpr bool isdigit(char c)
Definition cconstexpr.hpp:68
consteval auto make_safe_wrapper(int(&cfunc)(int, ExtraArgs...))
Definition cconstexpr.hpp:40
constexpr bool ispunct(char c)
Definition cconstexpr.hpp:107
constexpr bool isspace(char c)
Definition cconstexpr.hpp:103
constexpr bool isxdigit(char c)
Definition cconstexpr.hpp:72
constexpr bool isblank(char c)
Definition cconstexpr.hpp:99
constexpr bool isgraph(char c)
Definition cconstexpr.hpp:91
constexpr char toupper(char c)
Definition cconstexpr.hpp:61
constexpr bool islower(char c)
Definition cconstexpr.hpp:46
constexpr bool iscntrl(char c)
Definition cconstexpr.hpp:87
consteval decltype(auto) resolve_overload(auto &&overloaded)
Definition cconstexpr.hpp:33
constexpr bool in_range(auto &&val, auto &&low, auto &&high)
inclusive
Definition cconstexpr.hpp:28
Definition asm_buffer.hpp:20
constexpr T abs(T val)
Definition cconstexpr.hpp:145
constexpr std::common_type_t< BaseT, ExpT > pow(BaseT base, ExpT exp)
Definition cconstexpr.hpp:158