From f61a1e813248e7f05381e452086d1c35771e8629 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 5 Jun 2022 16:46:50 -0700 Subject: [PATCH] Add format_arg_types --- include/fmt/compile.h | 2 +- include/fmt/core.h | 134 +++++++++++++++++++++++------------------- 2 files changed, 74 insertions(+), 62 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index ac1a2c09..30cb0664 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -338,7 +338,7 @@ constexpr parse_specs_result parse_specs(basic_string_view str, size_t pos, int next_arg_id) { str.remove_prefix(pos); auto ctx = - compile_parse_context(str, max_value(), {}, next_arg_id); + compile_parse_context(str, format_arg_types<10>(), {}, next_arg_id); auto f = formatter(); auto end = f.parse(ctx); return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1, diff --git a/include/fmt/core.h b/include/fmt/core.h index aa0f26c9..6ca9da27 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -542,6 +542,70 @@ template struct char_t_impl::value>> { using type = typename result::value_type; }; +enum class type { + none_type, + // Integer types should go first, + int_type, + uint_type, + long_long_type, + ulong_long_type, + int128_type, + uint128_type, + bool_type, + char_type, + last_integer_type = char_type, + // followed by floating-point types. + float_type, + double_type, + long_double_type, + last_numeric_type = long_double_type, + cstring_type, + string_type, + pointer_type, + custom_type +}; + +// Maps core type T to the corresponding type enum constant. +template +struct type_constant : std::integral_constant {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template \ + struct type_constant \ + : std::integral_constant {} + +FMT_TYPE_CONSTANT(int, int_type); +FMT_TYPE_CONSTANT(unsigned, uint_type); +FMT_TYPE_CONSTANT(long long, long_long_type); +FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); +FMT_TYPE_CONSTANT(int128_opt, int128_type); +FMT_TYPE_CONSTANT(uint128_opt, uint128_type); +FMT_TYPE_CONSTANT(bool, bool_type); +FMT_TYPE_CONSTANT(Char, char_type); +FMT_TYPE_CONSTANT(float, float_type); +FMT_TYPE_CONSTANT(double, double_type); +FMT_TYPE_CONSTANT(long double, long_double_type); +FMT_TYPE_CONSTANT(const Char*, cstring_type); +FMT_TYPE_CONSTANT(basic_string_view, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr bool is_integral_type(type t) { + return t > type::none_type && t <= type::last_integer_type; +} + +constexpr bool is_arithmetic_type(type t) { + return t > type::none_type && t <= type::last_numeric_type; +} + +template struct format_arg_types { + type types[NUM_ARGS > 0 ? NUM_ARGS : 1]; +}; + +template +constexpr format_arg_types make_format_arg_types() { + return {type_constant::value...}; +} + FMT_NORETURN FMT_API void throw_format_error(const char* message); struct error_handler { @@ -645,14 +709,17 @@ class compile_parse_context : public basic_format_parse_context { private: int num_args_; + const type* types_; using base = basic_format_parse_context; public: + template explicit FMT_CONSTEXPR compile_parse_context( - basic_string_view format_str, - int num_args = (std::numeric_limits::max)(), ErrorHandler eh = {}, - int next_arg_id = 0) - : base(format_str, eh, next_arg_id), num_args_(num_args) {} + basic_string_view format_str, const format_arg_types& t, + ErrorHandler eh = {}, int next_arg_id = 0) + : base(format_str, eh, next_arg_id), + num_args_(NUM_ARGS), + types_(t.types) {} constexpr int num_args() const { return num_args_; } @@ -1115,61 +1182,6 @@ constexpr auto count_statically_named_args() -> size_t { return count::value...>(); } -enum class type { - none_type, - // Integer types should go first, - int_type, - uint_type, - long_long_type, - ulong_long_type, - int128_type, - uint128_type, - bool_type, - char_type, - last_integer_type = char_type, - // followed by floating-point types. - float_type, - double_type, - long_double_type, - last_numeric_type = long_double_type, - cstring_type, - string_type, - pointer_type, - custom_type -}; - -// Maps core type T to the corresponding type enum constant. -template -struct type_constant : std::integral_constant {}; - -#define FMT_TYPE_CONSTANT(Type, constant) \ - template \ - struct type_constant \ - : std::integral_constant {} - -FMT_TYPE_CONSTANT(int, int_type); -FMT_TYPE_CONSTANT(unsigned, uint_type); -FMT_TYPE_CONSTANT(long long, long_long_type); -FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); -FMT_TYPE_CONSTANT(int128_opt, int128_type); -FMT_TYPE_CONSTANT(uint128_opt, uint128_type); -FMT_TYPE_CONSTANT(bool, bool_type); -FMT_TYPE_CONSTANT(Char, char_type); -FMT_TYPE_CONSTANT(float, float_type); -FMT_TYPE_CONSTANT(double, double_type); -FMT_TYPE_CONSTANT(long double, long_double_type); -FMT_TYPE_CONSTANT(const Char*, cstring_type); -FMT_TYPE_CONSTANT(basic_string_view, string_type); -FMT_TYPE_CONSTANT(const void*, pointer_type); - -constexpr bool is_integral_type(type t) { - return t > type::none_type && t <= type::last_integer_type; -} - -constexpr bool is_arithmetic_type(type t) { - return t > type::none_type && t <= type::last_numeric_type; -} - struct unformattable {}; struct unformattable_char : unformattable {}; struct unformattable_const : unformattable {}; @@ -2881,7 +2893,7 @@ class format_string_checker { // here and will use is_constant_evaluated and downcasting to access the data // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1. using parse_context_type = compile_parse_context; - enum { num_args = sizeof...(Args) }; + static constexpr int num_args = sizeof...(Args); // Format specifier parsing function. using parse_func = const Char* (*)(parse_context_type&); @@ -2892,7 +2904,7 @@ class format_string_checker { public: explicit FMT_CONSTEXPR format_string_checker( basic_string_view format_str, ErrorHandler eh) - : context_(format_str, num_args, eh), + : context_(format_str, make_format_arg_types(), eh), parse_funcs_{&parse_format_specs...} {} FMT_CONSTEXPR void on_text(const Char*, const Char*) {}