Cleanup base API

This commit is contained in:
Victor Zverovich 2024-09-01 18:42:41 -07:00
parent 0b80978c27
commit 9ef160d309
3 changed files with 114 additions and 115 deletions

View File

@ -808,13 +808,8 @@ template <typename Char, typename T> struct named_arg : view {
named_arg(const Char* n, const T& v) : name(n), value(v) {}
};
template <typename Char> struct named_arg_info {
const Char* name;
int id;
};
template <typename T> struct is_named_arg : std::false_type {};
template <typename T> struct is_statically_named_arg : std::false_type {};
template <typename T> struct is_static_named_arg : std::false_type {};
template <typename Char, typename T>
struct is_named_arg<named_arg<Char, T>> : std::true_type {};
@ -838,7 +833,35 @@ template <typename... Args> constexpr auto count_named_args() -> size_t {
return count<is_named_arg<Args>::value...>();
}
template <typename... Args> constexpr auto count_static_named_args() -> size_t {
return count<is_statically_named_arg<Args>::value...>();
return count<is_static_named_arg<Args>::value...>();
}
template <typename Char> struct named_arg_info {
const Char* name;
int id;
};
template <typename Char, typename T, FMT_ENABLE_IF(!is_named_arg<T>::value)>
void init_named_arg(named_arg_info<Char>*, int& arg_index, int&, const T&) {
++arg_index;
}
template <typename Char, typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
void init_named_arg(named_arg_info<Char>* named_args, int& arg_index,
int& named_arg_index, const T& arg) {
named_args[named_arg_index++] = {arg.name, arg_index++};
}
template <typename T, typename Char,
FMT_ENABLE_IF(!is_static_named_arg<T>::value)>
FMT_CONSTEXPR void init_static_named_arg(named_arg_info<Char>*, int& arg_index,
int&) {
++arg_index;
}
template <typename T, typename Char,
FMT_ENABLE_IF(is_static_named_arg<T>::value)>
FMT_CONSTEXPR void init_static_named_arg(named_arg_info<Char>* named_args,
int& arg_index, int& named_arg_index) {
named_args[named_arg_index++] = {T::name, arg_index++};
}
// To minimize the number of types we need to deal with, long is translated
@ -1761,6 +1784,83 @@ FMT_CONSTEXPR inline auto check_char_specs(const format_specs& specs) -> bool {
return true;
}
// A base class for compile-time strings.
struct compile_string {};
template <typename T, typename Char>
FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769).
FMT_CONSTEXPR auto invoke_parse(parse_context<Char>& ctx) -> const Char* {
using mapper = arg_mapper<buffered_context<Char>>;
using mapped_type = remove_cvref_t<decltype(mapper::map(std::declval<T&>()))>;
#if defined(__cpp_if_constexpr)
if constexpr (std::is_default_constructible<formatter<mapped_type, Char>>())
return formatter<mapped_type, Char>().parse(ctx);
return ctx.begin(); // Ignore the error - it is reported by make_format_args.
#else
return formatter<mapped_type, Char>().parse(ctx);
#endif
}
template <typename... T> struct arg_pack {};
template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES>
class format_string_checker {
private:
type types_[NUM_ARGS > 0 ? NUM_ARGS : 1];
named_arg_info<Char> named_args_[NUM_NAMED_ARGS > 0 ? NUM_NAMED_ARGS : 1];
compile_parse_context<Char> context_;
using parse_func = auto (*)(parse_context<Char>&) -> const Char*;
parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1];
public:
template <typename... T>
explicit FMT_CONSTEXPR format_string_checker(basic_string_view<Char> fmt,
arg_pack<T...>)
: types_{mapped_type_constant<T, buffered_context<Char>>::value...},
named_args_{},
context_(fmt, NUM_ARGS, types_),
parse_funcs_{&invoke_parse<T, Char>...} {
using ignore = int[];
int arg_index = 0, named_arg_index = 0;
(void)ignore{
0, (init_static_named_arg<T>(named_args_, arg_index, named_arg_index),
0)...};
ignore_unused(arg_index, named_arg_index);
}
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }
FMT_CONSTEXPR auto on_arg_id(int id) -> int {
context_.check_arg_id(id);
return id;
}
FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
for (int i = 0; i < NUM_NAMED_ARGS; ++i) {
if (named_args_[i].name == id) return named_args_[i].id;
}
if (!DYNAMIC_NAMES) on_error("argument not found");
return -1;
}
FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) {
on_format_specs(id, begin, begin); // Call parse() on empty specs.
}
FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char* end)
-> const Char* {
context_.advance_to(begin);
if (id >= 0 && id < NUM_ARGS) return parse_funcs_[id](context_);
while (begin != end && *begin != '}') ++begin;
return begin;
}
FMT_NORETURN FMT_CONSTEXPR void on_error(const char* message) {
report_error(message);
}
};
/// A contiguous memory buffer with an optional growing ability. It is an
/// internal class and shouldn't be used directly, only via `memory_buffer`.
template <typename T> class buffer {
@ -2369,30 +2469,6 @@ template <typename Context, size_t NUM_ARGS>
using arg_t = conditional_t<NUM_ARGS <= max_packed_args, value<Context>,
basic_format_arg<Context>>;
template <typename Char, typename T, FMT_ENABLE_IF(!is_named_arg<T>::value)>
void init_named_arg(named_arg_info<Char>*, int& arg_index, int&, const T&) {
++arg_index;
}
template <typename Char, typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
void init_named_arg(named_arg_info<Char>* named_args, int& arg_index,
int& named_arg_index, const T& arg) {
named_args[named_arg_index++] = {arg.name, arg_index++};
}
template <typename T, typename Char,
FMT_ENABLE_IF(!is_statically_named_arg<T>::value)>
FMT_CONSTEXPR void init_statically_named_arg(named_arg_info<Char>*,
int& arg_index, int&) {
++arg_index;
}
template <typename T, typename Char,
FMT_ENABLE_IF(is_statically_named_arg<T>::value)>
FMT_CONSTEXPR void init_statically_named_arg(named_arg_info<Char>* named_args,
int& arg_index,
int& named_arg_index) {
named_args[named_arg_index++] = {T::name, arg_index++};
}
// An array of references to arguments. It can be implicitly converted to
// `fmt::basic_format_args` for passing into type-erased formatting functions
// such as `fmt::vformat`.
@ -2702,83 +2778,6 @@ FMT_END_EXPORT
namespace detail {
// A base class for compile-time strings.
struct compile_string {};
template <typename T, typename Char>
FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769).
FMT_CONSTEXPR auto invoke_parse(parse_context<Char>& ctx) -> const Char* {
using mapper = arg_mapper<buffered_context<Char>>;
using mapped_type = remove_cvref_t<decltype(mapper::map(std::declval<T&>()))>;
#if defined(__cpp_if_constexpr)
if constexpr (std::is_default_constructible<formatter<mapped_type, Char>>())
return formatter<mapped_type, Char>().parse(ctx);
return ctx.begin(); // Ignore the error - it is reported by make_format_args.
#else
return formatter<mapped_type, Char>().parse(ctx);
#endif
}
template <typename... T> struct arg_pack {};
template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES>
class format_string_checker {
private:
type types_[NUM_ARGS > 0 ? NUM_ARGS : 1];
named_arg_info<Char> named_args_[NUM_NAMED_ARGS > 0 ? NUM_NAMED_ARGS : 1];
compile_parse_context<Char> context_;
using parse_func = auto (*)(parse_context<Char>&) -> const Char*;
parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1];
public:
template <typename... T>
explicit FMT_CONSTEXPR format_string_checker(basic_string_view<Char> fmt,
arg_pack<T...>)
: types_{mapped_type_constant<T, buffered_context<Char>>::value...},
named_args_{},
context_(fmt, NUM_ARGS, types_),
parse_funcs_{&invoke_parse<T, Char>...} {
using ignore = int[];
int arg_index = 0, named_arg_index = 0;
(void)ignore{0, (init_statically_named_arg<T>(named_args_, arg_index,
named_arg_index),
0)...};
ignore_unused(arg_index, named_arg_index);
}
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }
FMT_CONSTEXPR auto on_arg_id(int id) -> int {
context_.check_arg_id(id);
return id;
}
FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
for (int i = 0; i < NUM_NAMED_ARGS; ++i) {
if (named_args_[i].name == id) return named_args_[i].id;
}
if (!DYNAMIC_NAMES) on_error("argument not found");
return -1;
}
FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) {
on_format_specs(id, begin, begin); // Call parse() on empty specs.
}
FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char* end)
-> const Char* {
context_.advance_to(begin);
if (id >= 0 && id < NUM_ARGS) return parse_funcs_[id](context_);
while (begin != end && *begin != '}') ++begin;
return begin;
}
FMT_NORETURN FMT_CONSTEXPR void on_error(const char* message) {
report_error(message);
}
};
// TYPE can be different from type_constant<T>, e.g. for __float128.
template <typename T, typename Char, type TYPE> struct native_formatter {
private:

View File

@ -74,7 +74,7 @@ constexpr const auto& get([[maybe_unused]] const T& first,
# if FMT_USE_NONTYPE_TEMPLATE_ARGS
template <int N, typename T, typename... Args, typename Char>
constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
if constexpr (is_statically_named_arg<T>()) {
if constexpr (is_static_named_arg<T>()) {
if (name == T::name) return N;
}
if constexpr (sizeof...(Args) > 0)

View File

@ -3769,27 +3769,27 @@ FMT_CONSTEXPR void handle_dynamic_spec(
# if FMT_USE_NONTYPE_TEMPLATE_ARGS
template <typename T, typename Char, size_t N,
fmt::detail_exported::fixed_string<Char, N> Str>
struct statically_named_arg : view {
struct static_named_arg : view {
static constexpr auto name = Str.data;
const T& value;
statically_named_arg(const T& v) : value(v) {}
static_named_arg(const T& v) : value(v) {}
};
template <typename T, typename Char, size_t N,
fmt::detail_exported::fixed_string<Char, N> Str>
struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
struct is_named_arg<static_named_arg<T, Char, N, Str>> : std::true_type {};
template <typename T, typename Char, size_t N,
fmt::detail_exported::fixed_string<Char, N> Str>
struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
: std::true_type {};
struct is_static_named_arg<static_named_arg<T, Char, N, Str>> : std::true_type {
};
template <typename Char, size_t N,
fmt::detail_exported::fixed_string<Char, N> Str>
struct udl_arg {
template <typename T> auto operator=(T&& value) const {
return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
return static_named_arg<T, Char, N, Str>(std::forward<T>(value));
}
};
# else