forked from fmtlib/fmt
More iteratification
This commit is contained in:
@ -624,7 +624,7 @@ class value {
|
|||||||
typename Context::template formatter_type<T> f;
|
typename Context::template formatter_type<T> f;
|
||||||
auto &&parse_ctx = ctx.parse_context();
|
auto &&parse_ctx = ctx.parse_context();
|
||||||
parse_ctx.advance_to(f.parse(parse_ctx));
|
parse_ctx.advance_to(f.parse(parse_ctx));
|
||||||
f.format(*static_cast<const T*>(arg), ctx);
|
ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -788,23 +788,23 @@ class arg_map {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Range, typename Context>
|
template <typename OutputIt, typename Context, typename Char>
|
||||||
class context_base {
|
class context_base {
|
||||||
public:
|
public:
|
||||||
using iterator = decltype(std::declval<Range>().begin());
|
using iterator = OutputIt;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
basic_parse_context<typename Range::value_type> parse_context_;
|
basic_parse_context<Char> parse_context_;
|
||||||
iterator out_;
|
iterator out_;
|
||||||
basic_format_args<Context> args_;
|
basic_format_args<Context> args_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using char_type = typename Range::value_type;
|
using char_type = Char;
|
||||||
using format_arg = basic_arg<Context>;
|
using format_arg = basic_arg<Context>;
|
||||||
|
|
||||||
context_base(Range r, basic_string_view<char_type> format_str,
|
context_base(OutputIt out, basic_string_view<char_type> format_str,
|
||||||
basic_format_args<Context> args)
|
basic_format_args<Context> args)
|
||||||
: parse_context_(format_str), out_(r.begin()), args_(args) {}
|
: parse_context_(format_str), out_(out), args_(args) {}
|
||||||
|
|
||||||
basic_format_args<Context> args() const { return args_; }
|
basic_format_args<Context> args() const { return args_; }
|
||||||
|
|
||||||
@ -824,7 +824,7 @@ class context_base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr basic_parse_context<char_type> &parse_context() {
|
basic_parse_context<char_type> &parse_context() {
|
||||||
return parse_context_;
|
return parse_context_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -882,24 +882,22 @@ class back_insert_range:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Formatting context.
|
// Formatting context.
|
||||||
template <typename Range>
|
template <typename OutputIt, typename Char>
|
||||||
class basic_context :
|
class basic_context :
|
||||||
public internal::context_base<Range, basic_context<Range>> {
|
public internal::context_base<OutputIt, basic_context<OutputIt, Char>, Char> {
|
||||||
public:
|
public:
|
||||||
/** The character type for the output. */
|
/** The character type for the output. */
|
||||||
using char_type = typename Range::value_type;
|
using char_type = Char;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using formatter_type = formatter<T, char_type>;
|
using formatter_type = formatter<T, char_type>;
|
||||||
|
|
||||||
using range_type = Range;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
internal::arg_map<basic_context> map_;
|
internal::arg_map<basic_context> map_;
|
||||||
|
|
||||||
FMT_DISALLOW_COPY_AND_ASSIGN(basic_context);
|
FMT_DISALLOW_COPY_AND_ASSIGN(basic_context);
|
||||||
|
|
||||||
using base = internal::context_base<Range, basic_context>;
|
using base = internal::context_base<OutputIt, basic_context, Char>;
|
||||||
using format_arg = typename base::format_arg;
|
using format_arg = typename base::format_arg;
|
||||||
using base::get_arg;
|
using base::get_arg;
|
||||||
|
|
||||||
@ -912,9 +910,9 @@ class basic_context :
|
|||||||
stored in the object so make sure they have appropriate lifetimes.
|
stored in the object so make sure they have appropriate lifetimes.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
basic_context(Range range, basic_string_view<char_type> format_str,
|
basic_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||||
basic_format_args<basic_context> args)
|
basic_format_args<basic_context> args)
|
||||||
: base(range, format_str, args) {}
|
: base(out, format_str, args) {}
|
||||||
|
|
||||||
format_arg next_arg() {
|
format_arg next_arg() {
|
||||||
return this->do_get_arg(this->parse_context().next_arg_id());
|
return this->do_get_arg(this->parse_context().next_arg_id());
|
||||||
@ -926,8 +924,10 @@ class basic_context :
|
|||||||
format_arg get_arg(basic_string_view<char_type> name);
|
format_arg get_arg(basic_string_view<char_type> name);
|
||||||
};
|
};
|
||||||
|
|
||||||
using context = basic_context<back_insert_range<internal::buffer>>;
|
using context = basic_context<
|
||||||
using wcontext = basic_context<back_insert_range<internal::wbuffer>>;
|
std::back_insert_iterator<internal::buffer>, char>;
|
||||||
|
using wcontext = basic_context<
|
||||||
|
std::back_insert_iterator<internal::wbuffer>, wchar_t>;
|
||||||
|
|
||||||
template <typename Context, typename ...Args>
|
template <typename Context, typename ...Args>
|
||||||
class arg_store {
|
class arg_store {
|
||||||
@ -1087,12 +1087,10 @@ inline internal::named_arg<T, wchar_t> arg(wstring_view name, const T &arg) {
|
|||||||
return internal::named_arg<T, wchar_t>(name, arg);
|
return internal::named_arg<T, wchar_t>(name, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following two functions are deleted intentionally to disable
|
// This function template is deleted intentionally to disable nested named
|
||||||
// nested named arguments as in ``format("{}", arg("a", arg("b", 42)))``.
|
// arguments as in ``format("{}", arg("a", arg("b", 42)))``.
|
||||||
template <typename T>
|
template <typename S, typename... T>
|
||||||
void arg(string_view, internal::named_arg<T, char>) FMT_DELETED;
|
void arg(S, internal::named_arg<T...>) FMT_DELETED;
|
||||||
template <typename T>
|
|
||||||
void arg(wstring_view, internal::named_arg<T, wchar_t>) FMT_DELETED;
|
|
||||||
|
|
||||||
enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
|
enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
|
||||||
|
|
||||||
|
@ -2058,10 +2058,12 @@ void handle_dynamic_spec(
|
|||||||
template <typename Range>
|
template <typename Range>
|
||||||
class arg_formatter: public internal::arg_formatter_base<Range> {
|
class arg_formatter: public internal::arg_formatter_base<Range> {
|
||||||
private:
|
private:
|
||||||
basic_context<Range> &ctx_;
|
|
||||||
|
|
||||||
using char_type = typename Range::value_type;
|
using char_type = typename Range::value_type;
|
||||||
|
using iterator = decltype(std::declval<Range>().begin());
|
||||||
using base = internal::arg_formatter_base<Range>;
|
using base = internal::arg_formatter_base<Range>;
|
||||||
|
using context_type = basic_context<iterator, char_type>;
|
||||||
|
|
||||||
|
context_type &ctx_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using range = Range;
|
using range = Range;
|
||||||
@ -2074,13 +2076,13 @@ class arg_formatter: public internal::arg_formatter_base<Range> {
|
|||||||
*spec* contains format specifier information for standard argument types.
|
*spec* contains format specifier information for standard argument types.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
arg_formatter(basic_context<Range> &ctx, format_specs &spec)
|
arg_formatter(context_type &ctx, format_specs &spec)
|
||||||
: base(Range(ctx.begin()), spec), ctx_(ctx) {}
|
: base(Range(ctx.begin()), spec), ctx_(ctx) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
/** Formats an argument of a custom (user-defined) type. */
|
/** Formats an argument of a custom (user-defined) type. */
|
||||||
void operator()(typename basic_arg<basic_context<Range>>::handle handle) {
|
void operator()(typename basic_arg<context_type>::handle handle) {
|
||||||
handle.format(ctx_);
|
handle.format(ctx_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2851,7 +2853,8 @@ struct formatter<
|
|||||||
specs_.width_, specs_.width_ref, ctx);
|
specs_.width_, specs_.width_ref, ctx);
|
||||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||||
specs_.precision_, specs_.precision_ref, ctx);
|
specs_.precision_, specs_.precision_ref, ctx);
|
||||||
using range = typename FormatContext::range_type;
|
using range = output_range<
|
||||||
|
typename FormatContext::iterator, typename FormatContext::char_type>;
|
||||||
visit(arg_formatter<range>(ctx, specs_),
|
visit(arg_formatter<range>(ctx, specs_),
|
||||||
internal::make_arg<FormatContext>(val));
|
internal::make_arg<FormatContext>(val));
|
||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
@ -2919,7 +2922,9 @@ struct dynamic_formatter {
|
|||||||
}
|
}
|
||||||
if (specs_.precision_ != -1)
|
if (specs_.precision_ != -1)
|
||||||
checker.end_precision();
|
checker.end_precision();
|
||||||
visit(arg_formatter<typename FormatContext::range_type>(ctx, specs_),
|
using range = output_range<
|
||||||
|
typename FormatContext::iterator, typename FormatContext::char_type>;
|
||||||
|
visit(arg_formatter<range>(ctx, specs_),
|
||||||
internal::make_arg<FormatContext>(val));
|
internal::make_arg<FormatContext>(val));
|
||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
}
|
}
|
||||||
@ -2936,9 +2941,9 @@ struct dynamic_formatter {
|
|||||||
internal::dynamic_format_specs<Char> specs_;
|
internal::dynamic_format_specs<Char> specs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Range>
|
template <typename Range, typename Char>
|
||||||
typename basic_context<Range>::format_arg
|
typename basic_context<Range, Char>::format_arg
|
||||||
basic_context<Range>::get_arg(basic_string_view<char_type> name) {
|
basic_context<Range, Char>::get_arg(basic_string_view<char_type> name) {
|
||||||
map_.init(this->args());
|
map_.init(this->args());
|
||||||
format_arg arg = map_.find(name);
|
format_arg arg = map_.find(name);
|
||||||
if (arg.type() == internal::NONE)
|
if (arg.type() == internal::NONE)
|
||||||
@ -2957,7 +2962,7 @@ void do_vformat_to(typename ArgFormatter::range out,
|
|||||||
struct handler : internal::error_handler {
|
struct handler : internal::error_handler {
|
||||||
handler(range r, basic_string_view<Char> str,
|
handler(range r, basic_string_view<Char> str,
|
||||||
basic_format_args<Context> format_args)
|
basic_format_args<Context> format_args)
|
||||||
: context(r, str, format_args) {}
|
: context(r.begin(), str, format_args) {}
|
||||||
|
|
||||||
void on_text(iterator begin, iterator end) {
|
void on_text(iterator begin, iterator end) {
|
||||||
size_t size = end - begin;
|
size_t size = end - begin;
|
||||||
@ -3089,10 +3094,10 @@ inline void format_to(wmemory_buffer &buf, wstring_view format_str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char = char>
|
template <typename OutputIt, typename Char = char>
|
||||||
using context_t = basic_context<output_range<OutputIt, Char>>;
|
using context_t = basic_context<OutputIt, Char>;
|
||||||
|
|
||||||
template <typename OutputIt>
|
template <typename OutputIt, typename Char = char>
|
||||||
using format_args_t = basic_format_args<context_t<OutputIt>>;
|
using format_args_t = basic_format_args<context_t<OutputIt, Char>>;
|
||||||
|
|
||||||
template <typename OutputIt, typename... Args>
|
template <typename OutputIt, typename... Args>
|
||||||
inline void vformat_to(OutputIt out, string_view format_str,
|
inline void vformat_to(OutputIt out, string_view format_str,
|
||||||
|
@ -201,7 +201,10 @@ class PrintfWidthHandler {
|
|||||||
template <typename Range>
|
template <typename Range>
|
||||||
class printf_arg_formatter;
|
class printf_arg_formatter;
|
||||||
|
|
||||||
template <typename Range, typename ArgFormatter = printf_arg_formatter<Range>>
|
template <
|
||||||
|
typename OutputIt, typename Char,
|
||||||
|
typename ArgFormatter =
|
||||||
|
printf_arg_formatter<back_insert_range<internal::basic_buffer<Char>>>>
|
||||||
class basic_printf_context;
|
class basic_printf_context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -212,16 +215,18 @@ class basic_printf_context;
|
|||||||
template <typename Range>
|
template <typename Range>
|
||||||
class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
||||||
private:
|
private:
|
||||||
basic_printf_context<Range> &context_;
|
using char_type = typename Range::value_type;
|
||||||
|
using iterator = decltype(std::declval<Range>().begin());
|
||||||
|
using base = internal::arg_formatter_base<Range>;
|
||||||
|
using context_type = basic_printf_context<iterator, char_type>;
|
||||||
|
|
||||||
|
context_type &context_;
|
||||||
|
|
||||||
void write_null_pointer() {
|
void write_null_pointer() {
|
||||||
this->spec().type_ = 0;
|
this->spec().type_ = 0;
|
||||||
this->write("(nil)");
|
this->write("(nil)");
|
||||||
}
|
}
|
||||||
|
|
||||||
using char_type = typename Range::value_type;
|
|
||||||
using base = internal::arg_formatter_base<Range>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using format_specs = typename base::format_specs;
|
using format_specs = typename base::format_specs;
|
||||||
|
|
||||||
@ -233,8 +238,9 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
printf_arg_formatter(internal::basic_buffer<char_type> &buffer,
|
printf_arg_formatter(internal::basic_buffer<char_type> &buffer,
|
||||||
format_specs &spec, basic_printf_context<Range> &ctx)
|
format_specs &spec, context_type &ctx)
|
||||||
: base(buffer, spec), context_(ctx) {}
|
: base(back_insert_range<internal::basic_buffer<char_type>>(buffer), spec),
|
||||||
|
context_(ctx) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
@ -276,8 +282,7 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Formats an argument of a custom (user-defined) type. */
|
/** Formats an argument of a custom (user-defined) type. */
|
||||||
void operator()(
|
void operator()(typename basic_arg<context_type>::handle handle) {
|
||||||
typename basic_arg<basic_printf_context<Range>>::handle handle) {
|
|
||||||
handle.format(context_);
|
handle.format(context_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -295,19 +300,19 @@ struct printf_formatter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** This template formats data and writes the output to a writer. */
|
/** This template formats data and writes the output to a writer. */
|
||||||
template <typename Range, typename ArgFormatter>
|
template <typename OutputIt, typename Char, typename ArgFormatter>
|
||||||
class basic_printf_context :
|
class basic_printf_context :
|
||||||
private internal::context_base<
|
private internal::context_base<
|
||||||
Range, basic_printf_context<Range, ArgFormatter>> {
|
OutputIt, basic_printf_context<OutputIt, Char, ArgFormatter>, Char> {
|
||||||
public:
|
public:
|
||||||
/** The character type for the output. */
|
/** The character type for the output. */
|
||||||
using char_type = typename Range::value_type;
|
using char_type = Char;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using formatter_type = printf_formatter<T>;
|
using formatter_type = printf_formatter<T>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using base = internal::context_base<Range, basic_printf_context>;
|
using base = internal::context_base<OutputIt, basic_printf_context, Char>;
|
||||||
using format_arg = typename base::format_arg;
|
using format_arg = typename base::format_arg;
|
||||||
using format_specs = basic_format_specs<char_type>;
|
using format_specs = basic_format_specs<char_type>;
|
||||||
using iterator = internal::null_terminating_iterator<char_type>;
|
using iterator = internal::null_terminating_iterator<char_type>;
|
||||||
@ -331,9 +336,9 @@ class basic_printf_context :
|
|||||||
appropriate lifetimes.
|
appropriate lifetimes.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
basic_printf_context(Range range, basic_string_view<char_type> format_str,
|
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||||
basic_format_args<basic_printf_context> args)
|
basic_format_args<basic_printf_context> args)
|
||||||
: base(range, format_str, args) {}
|
: base(out, format_str, args) {}
|
||||||
|
|
||||||
using base::parse_context;
|
using base::parse_context;
|
||||||
using base::begin;
|
using base::begin;
|
||||||
@ -343,8 +348,8 @@ class basic_printf_context :
|
|||||||
FMT_API void format();
|
FMT_API void format();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Range, typename AF>
|
template <typename OutputIt, typename Char, typename AF>
|
||||||
void basic_printf_context<Range, AF>::parse_flags(
|
void basic_printf_context<OutputIt, Char, AF>::parse_flags(
|
||||||
format_specs &spec, iterator &it) {
|
format_specs &spec, iterator &it) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (*it++) {
|
switch (*it++) {
|
||||||
@ -370,17 +375,18 @@ void basic_printf_context<Range, AF>::parse_flags(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range, typename AF>
|
template <typename OutputIt, typename Char, typename AF>
|
||||||
typename basic_printf_context<Range, AF>::format_arg
|
typename basic_printf_context<OutputIt, Char, AF>::format_arg
|
||||||
basic_printf_context<Range, AF>::get_arg(iterator it, unsigned arg_index) {
|
basic_printf_context<OutputIt, Char, AF>::get_arg(
|
||||||
|
iterator it, unsigned arg_index) {
|
||||||
(void)it;
|
(void)it;
|
||||||
if (arg_index == std::numeric_limits<unsigned>::max())
|
if (arg_index == std::numeric_limits<unsigned>::max())
|
||||||
return this->do_get_arg(this->parse_context().next_arg_id());
|
return this->do_get_arg(this->parse_context().next_arg_id());
|
||||||
return base::get_arg(arg_index - 1);
|
return base::get_arg(arg_index - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range, typename AF>
|
template <typename OutputIt, typename Char, typename AF>
|
||||||
unsigned basic_printf_context<Range, AF>::parse_header(
|
unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
|
||||||
iterator &it, format_specs &spec) {
|
iterator &it, format_specs &spec) {
|
||||||
unsigned arg_index = std::numeric_limits<unsigned>::max();
|
unsigned arg_index = std::numeric_limits<unsigned>::max();
|
||||||
char_type c = *it;
|
char_type c = *it;
|
||||||
@ -416,8 +422,8 @@ unsigned basic_printf_context<Range, AF>::parse_header(
|
|||||||
return arg_index;
|
return arg_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Range, typename AF>
|
template <typename OutputIt, typename Char, typename AF>
|
||||||
void basic_printf_context<Range, AF>::format() {
|
void basic_printf_context<OutputIt, Char, AF>::format() {
|
||||||
auto &buffer = internal::get_container(this->begin());
|
auto &buffer = internal::get_container(this->begin());
|
||||||
auto start = iterator(this->parse_context());
|
auto start = iterator(this->parse_context());
|
||||||
auto it = start;
|
auto it = start;
|
||||||
@ -506,8 +512,7 @@ void basic_printf_context<Range, AF>::format() {
|
|||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
// TODO: handle wchar_t
|
// TODO: handle wchar_t
|
||||||
visit(internal::CharConverter<basic_printf_context<Range, AF>>(arg),
|
visit(internal::CharConverter<basic_printf_context>(arg), arg);
|
||||||
arg);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -523,11 +528,12 @@ void basic_printf_context<Range, AF>::format() {
|
|||||||
template <typename Char, typename Context>
|
template <typename Char, typename Context>
|
||||||
void printf(internal::basic_buffer<Char> &buf, basic_string_view<Char> format,
|
void printf(internal::basic_buffer<Char> &buf, basic_string_view<Char> format,
|
||||||
basic_format_args<Context> args) {
|
basic_format_args<Context> args) {
|
||||||
Context(buf, format, args).format();
|
Context(std::back_inserter(buf), format, args).format();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
using printf_context = basic_printf_context<back_insert_range<Buffer>>;
|
using printf_context = basic_printf_context<
|
||||||
|
std::back_insert_iterator<Buffer>, typename Buffer::value_type>;
|
||||||
|
|
||||||
using printf_args = basic_format_args<printf_context<internal::buffer>>;
|
using printf_args = basic_format_args<printf_context<internal::buffer>>;
|
||||||
|
|
||||||
|
@ -18,9 +18,11 @@ class CustomArgFormatter :
|
|||||||
public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> {
|
public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> {
|
||||||
public:
|
public:
|
||||||
using range = fmt::back_insert_range<fmt::internal::buffer>;
|
using range = fmt::back_insert_range<fmt::internal::buffer>;
|
||||||
|
using iterator = decltype(std::declval<range>().begin());
|
||||||
using base = fmt::arg_formatter<range>;
|
using base = fmt::arg_formatter<range>;
|
||||||
|
|
||||||
CustomArgFormatter(fmt::basic_context<range> &ctx, fmt::format_specs &s)
|
CustomArgFormatter(fmt::basic_context<iterator, char> &ctx,
|
||||||
|
fmt::format_specs &s)
|
||||||
: base(ctx, s) {}
|
: base(ctx, s) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
@ -58,14 +58,17 @@ TEST(OStreamTest, Enum) {
|
|||||||
EXPECT_EQ("0", fmt::format("{}", A));
|
EXPECT_EQ("0", fmt::format("{}", A));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct test_arg_formatter : fmt::arg_formatter<fmt::context::range_type> {
|
using range = fmt::back_insert_range<fmt::internal::buffer>;
|
||||||
|
|
||||||
|
struct test_arg_formatter: fmt::arg_formatter<range> {
|
||||||
test_arg_formatter(fmt::context &ctx, fmt::format_specs &s)
|
test_arg_formatter(fmt::context &ctx, fmt::format_specs &s)
|
||||||
: fmt::arg_formatter<fmt::context::range_type>(ctx, s) {}
|
: fmt::arg_formatter<range>(ctx, s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(OStreamTest, CustomArg) {
|
TEST(OStreamTest, CustomArg) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
fmt::context ctx(buffer, "", fmt::format_args());
|
fmt::internal::buffer &base = buffer;
|
||||||
|
fmt::context ctx(std::back_inserter(base), "", fmt::format_args());
|
||||||
fmt::format_specs spec;
|
fmt::format_specs spec;
|
||||||
test_arg_formatter af(ctx, spec);
|
test_arg_formatter af(ctx, spec);
|
||||||
visit(af, fmt::internal::make_arg<fmt::context>(TestEnum()));
|
visit(af, fmt::internal::make_arg<fmt::context>(TestEnum()));
|
||||||
|
@ -81,9 +81,10 @@ struct formatter<Test, Char> {
|
|||||||
return ctx.begin();
|
return ctx.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
using range = fmt::back_insert_range<basic_buffer<Char>>;
|
using iterator = std::back_insert_iterator<basic_buffer<Char>>;
|
||||||
|
|
||||||
auto format(Test, basic_context<range> &ctx) -> decltype(ctx.begin()) {
|
auto format(Test, basic_context<iterator, char> &ctx)
|
||||||
|
-> decltype(ctx.begin()) {
|
||||||
const Char *test = "test";
|
const Char *test = "test";
|
||||||
return std::copy_n(test, std::strlen(test), ctx.begin());
|
return std::copy_n(test, std::strlen(test), ctx.begin());
|
||||||
}
|
}
|
||||||
@ -521,8 +522,8 @@ VISIT_TYPE(float, double);
|
|||||||
#define CHECK_ARG_(Char, expected, value) { \
|
#define CHECK_ARG_(Char, expected, value) { \
|
||||||
testing::StrictMock<MockVisitor<decltype(expected)>> visitor; \
|
testing::StrictMock<MockVisitor<decltype(expected)>> visitor; \
|
||||||
EXPECT_CALL(visitor, visit(expected)); \
|
EXPECT_CALL(visitor, visit(expected)); \
|
||||||
using range = fmt::back_insert_range<basic_buffer<Char>>; \
|
using iterator = std::back_insert_iterator<basic_buffer<Char>>; \
|
||||||
fmt::visit(visitor, make_arg<fmt::basic_context<range>>(value)); \
|
fmt::visit(visitor, make_arg<fmt::basic_context<iterator, Char>>(value)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_ARG(value) { \
|
#define CHECK_ARG(value) { \
|
||||||
@ -600,7 +601,8 @@ TEST(UtilTest, CustomArg) {
|
|||||||
testing::StrictMock<visitor> v;
|
testing::StrictMock<visitor> v;
|
||||||
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke([&](handle h) {
|
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke([&](handle h) {
|
||||||
fmt::memory_buffer buffer;
|
fmt::memory_buffer buffer;
|
||||||
fmt::context ctx(buffer, "", fmt::format_args());
|
fmt::internal::basic_buffer<char> &base = buffer;
|
||||||
|
fmt::context ctx(std::back_inserter(base), "", fmt::format_args());
|
||||||
h.format(ctx);
|
h.format(ctx);
|
||||||
EXPECT_EQ("test", std::string(buffer.data(), buffer.size()));
|
EXPECT_EQ("test", std::string(buffer.data(), buffer.size()));
|
||||||
return visitor::Result();
|
return visitor::Result();
|
||||||
|
Reference in New Issue
Block a user