mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-22 02:20:06 +00:00
Cleanup base API
This commit is contained in:
parent
a6ecd25b80
commit
4eed488c66
@ -2308,8 +2308,7 @@ template <typename Context> class value {
|
||||
// Get the formatter type through the context to allow different contexts
|
||||
// have different extension points, e.g. `formatter<T>` for `format` and
|
||||
// `printf_formatter<T>` for `printf`.
|
||||
custom.format = format_custom_arg<
|
||||
value_type, typename Context::template formatter_type<value_type>>;
|
||||
custom.format = format_custom<value_type, formatter<value_type, char_type>>;
|
||||
}
|
||||
FMT_ALWAYS_INLINE value(const named_arg_info<char_type>* args, size_t size)
|
||||
: named_args{args, size} {}
|
||||
@ -2320,8 +2319,7 @@ template <typename Context> class value {
|
||||
private:
|
||||
// Formats an argument of a custom type, such as a user-defined class.
|
||||
template <typename T, typename Formatter>
|
||||
static void format_custom_arg(void* arg,
|
||||
typename Context::parse_context_type& parse_ctx,
|
||||
static void format_custom(void* arg, parse_context<char_type>& parse_ctx,
|
||||
Context& ctx) {
|
||||
auto f = Formatter();
|
||||
parse_ctx.advance_to(f.parse(parse_ctx));
|
||||
@ -2494,7 +2492,67 @@ struct format_arg_store<Context, NUM_ARGS, 0, DESC> {
|
||||
arg_t<Context, NUM_ARGS> args[NUM_ARGS != 0 ? NUM_ARGS : +1];
|
||||
};
|
||||
|
||||
// TYPE can be different from type_constant<T>, e.g. for __float128.
|
||||
template <typename T, typename Char, type TYPE> struct native_formatter {
|
||||
private:
|
||||
dynamic_format_specs<Char> specs_;
|
||||
|
||||
public:
|
||||
using nonlocking = void;
|
||||
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
|
||||
auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, TYPE);
|
||||
if (const_check(TYPE == type::char_type)) check_char_specs(specs_);
|
||||
return end;
|
||||
}
|
||||
|
||||
template <type U = TYPE,
|
||||
FMT_ENABLE_IF(U == type::string_type || U == type::cstring_type ||
|
||||
U == type::char_type)>
|
||||
FMT_CONSTEXPR void set_debug_format(bool set = true) {
|
||||
specs_.set_type(set ? presentation_type::debug : presentation_type::none);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
|
||||
-> decltype(ctx.out());
|
||||
};
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct locking
|
||||
: bool_constant<mapped_type_constant<T>::value == type::custom_type> {};
|
||||
template <typename T>
|
||||
struct locking<T, void_t<typename formatter<remove_cvref_t<T>>::nonlocking>>
|
||||
: std::false_type {};
|
||||
|
||||
template <typename T = int> FMT_CONSTEXPR inline auto is_locking() -> bool {
|
||||
return locking<T>::value;
|
||||
}
|
||||
template <typename T1, typename T2, typename... Tail>
|
||||
FMT_CONSTEXPR inline auto is_locking() -> bool {
|
||||
return locking<T1>::value || is_locking<T2, Tail...>();
|
||||
}
|
||||
|
||||
// Use vformat_args and avoid type_identity to keep symbols short.
|
||||
template <typename Char = char> struct vformat_args {
|
||||
using type = basic_format_args<buffered_context<Char>>;
|
||||
};
|
||||
template <> struct vformat_args<char> {
|
||||
using type = format_args;
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
|
||||
typename vformat_args<Char>::type args, locale_ref loc = {});
|
||||
|
||||
#ifdef _WIN32
|
||||
FMT_API void vprint_mojibake(FILE*, string_view, format_args, bool);
|
||||
#else
|
||||
inline void vprint_mojibake(FILE*, string_view, const format_args&, bool) {}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
// A formatting argument. Context is a template parameter for the compiled API
|
||||
@ -2522,16 +2580,15 @@ template <typename Context> class basic_format_arg {
|
||||
|
||||
public:
|
||||
class handle {
|
||||
private:
|
||||
detail::custom_value<Context> custom_;
|
||||
|
||||
public:
|
||||
explicit handle(detail::custom_value<Context> custom) : custom_(custom) {}
|
||||
|
||||
void format(typename Context::parse_context_type& parse_ctx,
|
||||
Context& ctx) const {
|
||||
void format(parse_context<char_type>& parse_ctx, Context& ctx) const {
|
||||
custom_.format(custom_.value, parse_ctx, ctx);
|
||||
}
|
||||
|
||||
private:
|
||||
detail::custom_value<Context> custom_;
|
||||
};
|
||||
|
||||
constexpr basic_format_arg() : type_(detail::type::none_type) {}
|
||||
@ -2582,7 +2639,7 @@ template <typename Context> class basic_format_arg {
|
||||
case detail::type::cstring_type:
|
||||
return vis(value_.string.data);
|
||||
case detail::type::string_type:
|
||||
using sv = basic_string_view<typename Context::char_type>;
|
||||
using sv = basic_string_view<char_type>;
|
||||
return vis(sv(value_.string.data, value_.string.size));
|
||||
case detail::type::pointer_type:
|
||||
return vis(value_.pointer);
|
||||
@ -2728,7 +2785,7 @@ class context {
|
||||
using iterator = appender;
|
||||
using format_arg = basic_format_arg<context>;
|
||||
using parse_context_type = parse_context<char>;
|
||||
template <typename T> using formatter_type = formatter<T, char>;
|
||||
template <typename T> using formatter_type FMT_DEPRECATED = formatter<T>;
|
||||
enum { builtin_types = FMT_BUILTIN_TYPES };
|
||||
|
||||
/// Constructs a `context` object. References to the arguments are stored
|
||||
@ -2755,71 +2812,6 @@ class context {
|
||||
|
||||
FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }
|
||||
};
|
||||
FMT_END_EXPORT
|
||||
|
||||
namespace detail {
|
||||
|
||||
// TYPE can be different from type_constant<T>, e.g. for __float128.
|
||||
template <typename T, typename Char, type TYPE> struct native_formatter {
|
||||
private:
|
||||
dynamic_format_specs<Char> specs_;
|
||||
|
||||
public:
|
||||
using nonlocking = void;
|
||||
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
|
||||
auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, TYPE);
|
||||
if (const_check(TYPE == type::char_type)) check_char_specs(specs_);
|
||||
return end;
|
||||
}
|
||||
|
||||
template <type U = TYPE,
|
||||
FMT_ENABLE_IF(U == type::string_type || U == type::cstring_type ||
|
||||
U == type::char_type)>
|
||||
FMT_CONSTEXPR void set_debug_format(bool set = true) {
|
||||
specs_.set_type(set ? presentation_type::debug : presentation_type::none);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
|
||||
-> decltype(ctx.out());
|
||||
};
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct locking
|
||||
: bool_constant<mapped_type_constant<T>::value == type::custom_type> {};
|
||||
template <typename T>
|
||||
struct locking<T, void_t<typename formatter<remove_cvref_t<T>>::nonlocking>>
|
||||
: std::false_type {};
|
||||
|
||||
template <typename T = int> FMT_CONSTEXPR inline auto is_locking() -> bool {
|
||||
return locking<T>::value;
|
||||
}
|
||||
template <typename T1, typename T2, typename... Tail>
|
||||
FMT_CONSTEXPR inline auto is_locking() -> bool {
|
||||
return locking<T1>::value || is_locking<T2, Tail...>();
|
||||
}
|
||||
|
||||
// Use vformat_args and avoid type_identity to keep symbols short.
|
||||
template <typename Char = char> struct vformat_args {
|
||||
using type = basic_format_args<buffered_context<Char>>;
|
||||
};
|
||||
template <> struct vformat_args<char> {
|
||||
using type = format_args;
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
|
||||
typename vformat_args<Char>::type args, locale_ref loc = {});
|
||||
|
||||
FMT_API void vprint_mojibake(FILE*, string_view, format_args, bool = false);
|
||||
#ifndef _WIN32
|
||||
inline void vprint_mojibake(FILE*, string_view, format_args, bool) {}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
template <typename Char = char> struct runtime_format_string {
|
||||
basic_string_view<Char> str;
|
||||
@ -3060,7 +3052,7 @@ FMT_API void vprintln(FILE* f, string_view fmt, format_args args);
|
||||
template <typename... T>
|
||||
FMT_INLINE void print(format_string<T...> fmt, T&&... args) {
|
||||
const auto& vargs = fmt::make_format_args(args...);
|
||||
if (!FMT_USE_UTF8) return detail::vprint_mojibake(stdout, fmt, vargs);
|
||||
if (!FMT_USE_UTF8) return detail::vprint_mojibake(stdout, fmt, vargs, false);
|
||||
return detail::is_locking<T...>() ? vprint_buffered(stdout, fmt, vargs)
|
||||
: vprint(fmt, vargs);
|
||||
}
|
||||
@ -3076,7 +3068,7 @@ FMT_INLINE void print(format_string<T...> fmt, T&&... args) {
|
||||
template <typename... T>
|
||||
FMT_INLINE void print(FILE* f, format_string<T...> fmt, T&&... args) {
|
||||
const auto& vargs = fmt::make_format_args(args...);
|
||||
if (!FMT_USE_UTF8) return detail::vprint_mojibake(f, fmt, vargs);
|
||||
if (!FMT_USE_UTF8) return detail::vprint_mojibake(f, fmt, vargs, false);
|
||||
return detail::is_locking<T...>() ? vprint_buffered(f, fmt, vargs)
|
||||
: vprint(f, fmt, vargs);
|
||||
}
|
||||
|
@ -276,27 +276,6 @@ TEST(base_test, get_buffer) {
|
||||
EXPECT_EQ(&back_inserter_result, buffer_ptr);
|
||||
}
|
||||
|
||||
struct custom_context {
|
||||
using char_type = char;
|
||||
using parse_context_type = fmt::format_parse_context;
|
||||
|
||||
bool called = false;
|
||||
|
||||
template <typename T> struct formatter_type {
|
||||
FMT_CONSTEXPR auto parse(fmt::format_parse_context& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
const char* format(const T&, custom_context& ctx) const {
|
||||
ctx.called = true;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
void advance_to(const char*) {}
|
||||
};
|
||||
|
||||
struct test_struct {};
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
@ -316,16 +295,6 @@ TEST(arg_test, format_args) {
|
||||
EXPECT_FALSE(args.get(1));
|
||||
}
|
||||
|
||||
TEST(arg_test, make_value_with_custom_context) {
|
||||
auto t = test_struct();
|
||||
auto arg = fmt::detail::value<custom_context>(
|
||||
fmt::detail::arg_mapper<custom_context>().map(t));
|
||||
auto ctx = custom_context();
|
||||
auto parse_ctx = fmt::format_parse_context("");
|
||||
arg.custom.format(&t, parse_ctx, ctx);
|
||||
EXPECT_TRUE(ctx.called);
|
||||
}
|
||||
|
||||
// Use a unique result type to make sure that there are no undesirable
|
||||
// conversions.
|
||||
struct test_result {};
|
||||
|
Loading…
Reference in New Issue
Block a user