some simplifications
This commit is contained in:
parent
5df04d4634
commit
e6cc388a2b
@ -31,46 +31,21 @@ template <typename T> struct NamedField {
|
|||||||
|
|
||||||
template <typename T> struct Extended { const T& value; };
|
template <typename T> struct Extended { const T& value; };
|
||||||
|
|
||||||
// fixme: Would probably be better to visit all name field elements directly in
|
|
||||||
// the Extended formatter instead of relying on user space specialization
|
|
||||||
// mechanism
|
|
||||||
/**
|
|
||||||
* Format a field name/value pair as ".{name}={value}"
|
|
||||||
* @tparam T
|
|
||||||
*/
|
|
||||||
template <typename T> struct fmt::formatter<NamedField<T>> {
|
|
||||||
template <typename FormatContext>
|
|
||||||
auto format(NamedField<T> const& t, FormatContext& ctx) {
|
|
||||||
*ctx.out()++ = '.';
|
|
||||||
std::copy(t.name.begin(), t.name.end(), ctx.out());
|
|
||||||
*ctx.out()++ = '=';
|
|
||||||
if constexpr (reflection<T>::available) {
|
|
||||||
return fmt::formatter<Extended<T>>{}.format(t.value, ctx);
|
|
||||||
} else {
|
|
||||||
return fmt::formatter<T>{}.format(t.value, ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats objects as they would be written using designated initializers.
|
* Formats objects as they would be written using designated initializers.
|
||||||
*
|
*
|
||||||
* E.g. {:e} will output Outer{.a=1, b=2, .inner=Inner{.x=3, .y=4, .z=5}}
|
* E.g. it will output "Outer{.a=1, b=2, .inner=Inner{.x=3, .y=4, .z=5}}"
|
||||||
*
|
*
|
||||||
* @tparam T The object to format.
|
|
||||||
* @tparam C The character type used.
|
* @tparam C The character type used.
|
||||||
*/
|
*/
|
||||||
// fixme remove T template parameter
|
template <typename C> struct CStyleFormatter {
|
||||||
template <typename T, typename C>
|
|
||||||
struct fmt::formatter<Extended<T>, C,
|
|
||||||
std::enable_if_t<reflection<T>::available, void>> {
|
|
||||||
template <typename ParseContext> constexpr auto parse(ParseContext& ctx) {
|
template <typename ParseContext> constexpr auto parse(ParseContext& ctx) {
|
||||||
auto it = ctx.begin();
|
auto it = ctx.begin();
|
||||||
if (*it != '}') throw format_error("configuration not yet supported");
|
if (*it != '}') throw format_error("configuration not yet supported");
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext>
|
template <typename T, typename FormatContext>
|
||||||
auto format(T const& t, FormatContext& ctx) {
|
auto format(T const& t, FormatContext& ctx) {
|
||||||
std::string name = reflection<T>::name();
|
std::string name = reflection<T>::name();
|
||||||
|
|
||||||
@ -83,22 +58,43 @@ struct fmt::formatter<Extended<T>, C,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// fixme remove this class and merge it with the fallback formatter in detail
|
// fixme: Would probably be better to visit all name field elements directly in
|
||||||
// namespace
|
// the Extended formatter instead of relying on user space specialization
|
||||||
|
// mechanism. That also will allow to reuse a configuration of the formatter
|
||||||
|
// for nested structures.
|
||||||
|
/**
|
||||||
|
* Format a field name/value pair as ".{name}={value}"
|
||||||
|
* @tparam T
|
||||||
|
*/
|
||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
struct fmt::formatter<T, Char,
|
struct fmt::formatter<NamedField<T>, Char> {
|
||||||
std::enable_if_t<reflection<T>::available, void>> {
|
template <typename FormatContext>
|
||||||
using extended = fmt::formatter<Extended<T>>;
|
auto format(NamedField<T> const& t, FormatContext& ctx) {
|
||||||
|
*ctx.out()++ = '.';
|
||||||
|
std::copy(t.name.begin(), t.name.end(), ctx.out());
|
||||||
|
*ctx.out()++ = '=';
|
||||||
|
if constexpr (reflection<T>::available) {
|
||||||
|
return CStyleFormatter<Char>{}.format(t.value, ctx);
|
||||||
|
} else {
|
||||||
|
return fmt::formatter<T>{}.format(t.value, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ParseContext> constexpr auto parse(ParseContext& ctx) {
|
namespace detail {
|
||||||
// Parse the presentation format and store it in the formatter:
|
/**
|
||||||
|
* Select a formatter matching the style requested in the format string.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Char>
|
||||||
|
struct fallback_formatter<T, Char, enable_if_t<reflection<T>::available>> {
|
||||||
|
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||||
|
-> decltype(ctx.begin()) {
|
||||||
auto it = ctx.begin(), end = ctx.end();
|
auto it = ctx.begin(), end = ctx.end();
|
||||||
if (*(it++) != 'e') {
|
if (*(it++) != 'e') { // fixme: e for extended.. rather arbitrary choice...
|
||||||
throw format_error("invalid format");
|
throw format_error("invalid format");
|
||||||
}
|
}
|
||||||
_extended = extended{};
|
|
||||||
ctx.advance_to(it);
|
ctx.advance_to(it);
|
||||||
_extended.parse(ctx);
|
it = CStyleFormatter<Char>{}.parse(ctx);
|
||||||
|
|
||||||
// Check if reached the end of the range:
|
// Check if reached the end of the range:
|
||||||
if (it != end && *it != '}') {
|
if (it != end && *it != '}') {
|
||||||
@ -109,34 +105,9 @@ struct fmt::formatter<T, Char,
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext>
|
|
||||||
auto format(T const& t, FormatContext& ctx) {
|
|
||||||
return _extended.format(t, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
extended _extended;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template <typename T, typename Char>
|
|
||||||
struct fallback_formatter<T, Char, enable_if_t<reflection<T>::available>> {
|
|
||||||
using extended = fmt::formatter<Extended<T>>;
|
|
||||||
|
|
||||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
|
||||||
-> decltype(ctx.begin()) {
|
|
||||||
auto it = formatter<basic_string_view<Char>, Char>::parse(ctx);
|
|
||||||
// fixme: not sure what to return, if the closing '}' remains (like required
|
|
||||||
// for formatter specialization)
|
|
||||||
// some internals will throw from ErrorHandler::on_error("invalid
|
|
||||||
// type specifier");
|
|
||||||
ctx.advance_to(it++); // fixme: also not sure
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
auto format(const T& value, FormatContext& ctx) {
|
auto format(const T& value, FormatContext& ctx) {
|
||||||
return extended{}.format(value, ctx);
|
return CStyleFormatter<Char>{}.format(value, ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user