@@ -11,22 +11,75 @@ namespace stdx {
1111inline namespace v1 {
1212
1313namespace detail {
14- template <typename T, char ... Chars> CONSTEVAL auto decimal () -> T {
15- static_assert ((... and (Chars >= ' 0' and Chars <= ' 9' )),
16- " decimal numbers only are supported" );
17- using U = decltype (stdx::to_underlying (std::declval<T>()));
18- auto x = U{};
19- ((x *= 10 , x += Chars - ' 0' ), ...);
20- return T{x};
14+ template <char C> constexpr static bool is_digit_sep_v = C == ' \' ' ;
15+ template <char C>
16+ constexpr static bool is_decimal_digit_v = C >= ' 0' and C <= ' 9' ;
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' ;
21+
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>;
38+ }
39+ return s;
2140}
41+
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...> {};
2270} // namespace detail
2371
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>();
75+ }
76+
2477template <auto I> using constant = std::integral_constant<decltype (I), I>;
2578template <auto I> constexpr static constant<I> _c{};
2679
2780inline namespace literals {
2881template <char ... Chars> CONSTEVAL auto operator " " _c() {
29- return _c<detail::decimal <std::uint32_t , Chars...>()>;
82+ return _c<parse_literal <std::uint32_t , Chars...>()>;
3083}
3184} // namespace literals
3285
0 commit comments