@@ -11,36 +11,75 @@ namespace stdx {
11
11
inline namespace v1 {
12
12
13
13
namespace detail {
14
+ template <char C> constexpr static bool is_digit_sep_v = C == ' \' ' ;
14
15
template <char C>
15
16
constexpr static bool is_decimal_digit_v = C >= ' 0' and C <= ' 9' ;
16
- template <char C> constexpr static bool is_digit_sep_v = C == ' \' ' ;
17
+ template <char C>
18
+ constexpr static bool is_octal_digit_v = C >= ' 0' and C <= ' 7' ;
19
+ template <char C>
20
+ constexpr static bool is_binary_digit_v = C >= ' 0' and C <= ' 1' ;
17
21
18
- template <char C, typename Sum> CONSTEVAL auto maybe_add_digit (Sum s) {
19
- if constexpr (is_decimal_digit_v<C>) {
20
- s *= 10 ;
21
- s += C - ' 0' ;
22
+ template <char C>
23
+ constexpr static char force_lower_case = static_cast <unsigned char >(C) | 32u ;
24
+ template <char C>
25
+ constexpr static bool is_hex_digit_v =
26
+ (C >= ' 0' and C <= ' 9' ) or
27
+ (force_lower_case<C> >= ' a' and force_lower_case<C> <= ' f' );
28
+
29
+ template <char C>
30
+ constexpr static auto integral_value_v =
31
+ is_decimal_digit_v<C> ? C - ' 0' : force_lower_case<C> - ' a' + 10 ;
32
+
33
+ template <auto Base, char C, typename Sum>
34
+ CONSTEVAL auto maybe_add_digit (Sum s) {
35
+ if constexpr (not is_digit_sep_v<C>) {
36
+ s *= Base;
37
+ s += integral_value_v<C>;
22
38
}
23
39
return s;
24
40
}
25
41
26
- template <typename T, char ... Chars> CONSTEVAL auto decimal () -> T {
27
- static_assert (
28
- (... and (is_decimal_digit_v<Chars> or is_digit_sep_v<Chars>)),
29
- " decimal numbers only are supported" );
30
- using U = decltype (stdx::to_underlying (std::declval<T>()));
42
+ template <auto Base, char ... Cs> struct raw_parser {
43
+ template <typename T> CONSTEVAL static auto parse () {
44
+ using U = decltype (stdx::to_underlying (std::declval<T>()));
45
+ auto x = U{};
46
+ ((x = maybe_add_digit<Base, Cs>(x)), ...);
47
+ return T{x};
48
+ }
49
+ };
50
+
51
+ template <char ... Cs> struct parser : raw_parser<10 , Cs...> {
52
+ static_assert ((... and (is_decimal_digit_v<Cs> or is_digit_sep_v<Cs>)));
53
+ };
54
+
55
+ template <char ... Cs> struct parser <' 0' , Cs...> : raw_parser<8 , Cs...> {
56
+ static_assert ((... and (is_octal_digit_v<Cs> or is_digit_sep_v<Cs>)));
57
+ };
58
+
59
+ template <char ... Cs> struct parser <' 0' , ' x' , Cs...> : raw_parser<16 , Cs...> {
60
+ static_assert ((... and (is_hex_digit_v<Cs> or is_digit_sep_v<Cs>)));
61
+ };
62
+ template <char ... Cs>
63
+ struct parser <' 0' , ' X' , Cs...> : parser<' 0' , ' x' , Cs...> {};
64
+
65
+ template <char ... Cs> struct parser <' 0' , ' b' , Cs...> : raw_parser<2 , Cs...> {
66
+ static_assert ((... and (is_binary_digit_v<Cs> or is_digit_sep_v<Cs>)));
67
+ };
68
+ template <char ... Cs>
69
+ struct parser <' 0' , ' B' , Cs...> : parser<' 0' , ' b' , Cs...> {};
70
+ } // namespace detail
31
71
32
- auto x = U{};
33
- ((x = maybe_add_digit <Chars>(x)), ...) ;
34
- return T{x} ;
72
+ template < typename T, char ... Chars> CONSTEVAL auto parse_literal () -> T {
73
+ using parser_t = detail::parser <Chars...> ;
74
+ return parser_t :: template parse<T>() ;
35
75
}
36
- } // namespace detail
37
76
38
77
template <auto I> using constant = std::integral_constant<decltype (I), I>;
39
78
template <auto I> constexpr static constant<I> _c{};
40
79
41
80
inline namespace literals {
42
81
template <char ... Chars> CONSTEVAL auto operator " " _c() {
43
- return _c<detail::decimal <std::uint32_t , Chars...>()>;
82
+ return _c<parse_literal <std::uint32_t , Chars...>()>;
44
83
}
45
84
} // namespace literals
46
85
0 commit comments