Return iterator from the format method

This commit is contained in:
Victor Zverovich
2018-01-14 11:00:27 -08:00
parent 67928eae28
commit 91ee9c9acd
7 changed files with 66 additions and 38 deletions

View File

@@ -568,8 +568,8 @@ class value {
// iostreams.
template <typename T>
void set_pointer(T *p) {
using type = typename std::remove_const<T>::type;
static_assert(std::is_same<type, void>::value,
using nonconst_type = typename std::remove_const<T>::type;
static_assert(std::is_same<nonconst_type, void>::value,
"formatting of non-void pointers is disallowed");
set<POINTER>(pointer, p);
}
@@ -583,7 +583,7 @@ class value {
typename Context::template formatter_type<T> f;
auto &&parse_ctx = ctx.parse_context();
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));
}
};
@@ -710,6 +710,7 @@ inline typename std::enable_if<!IS_PACKED, basic_arg<Context>>::type
return make_arg<Context>(value);
}
// A map from argument names to their values for named arguments.
template <typename Context>
class arg_map {
private:
@@ -748,9 +749,13 @@ class arg_map {
template <typename Range, typename Context>
class context_base {
public:
using iterator = decltype(std::declval<Range>().begin());
private:
basic_parse_context<typename Range::value_type> parse_context_;
Range range_;
iterator out_;
basic_format_args<Context> args_;
protected:
@@ -790,6 +795,12 @@ class context_base {
void on_error(const char *message) { parse_context_.on_error(message); }
Range range() { return range_; }
// Returns an iterator to the beginning of the output range.
iterator begin() { return out_; }
// Advances the begin iterator to ``it``.
void advance_to(iterator it) { out_ = it; }
};
// A range that can grow dynamically.
@@ -833,6 +844,8 @@ class basic_context :
template <typename T>
using formatter_type = formatter<T, char_type>;
using range_type = Range;
private:
internal::arg_map<basic_context> map_;
@@ -843,6 +856,8 @@ class basic_context :
using base::get_arg;
public:
using typename base::iterator;
/**
\rst
Constructs a ``basic_context`` object. References to the arguments are
@@ -858,7 +873,7 @@ class basic_context :
}
format_arg get_arg(unsigned arg_id) { return this->do_get_arg(arg_id); }
// Checks if manual indexing is used and returns the argument with
// Checks if manual indexing is used and returns the argument with the
// specified name.
format_arg get_arg(basic_string_view<char_type> name);
};
@@ -878,7 +893,7 @@ class arg_store {
IS_PACKED, internal::value<Context>, basic_arg<Context>>::type;
// If the arguments are not packed, add one more element to mark the end.
value_type data_[NUM_ARGS + (IS_PACKED ? 0 : 1)];
value_type data_[NUM_ARGS + (IS_PACKED && NUM_ARGS != 0 ? 0 : 1)];
public:
static const uint64_t TYPES = IS_PACKED ?
@@ -984,6 +999,8 @@ struct named_arg_base {
// Serialized value<context>.
mutable char data[sizeof(basic_arg<context>)];
named_arg_base(basic_string_view<Char> name) : name(name) {}
template <typename Context>
basic_arg<Context> deserialize() const {
basic_arg<Context> arg;
@@ -997,7 +1014,7 @@ struct named_arg : named_arg_base<Char> {
const T &value;
named_arg(basic_string_view<Char> name, const T &val)
: named_arg_base<Char>{name}, value(val) {}
: named_arg_base<Char>(name), value(val) {}
};
}

View File

@@ -2789,14 +2789,16 @@ struct formatter<
return pointer_from(it);
}
template <typename Range>
void format(const T &val, basic_context<Range> &ctx) {
template <typename FormatContext>
typename FormatContext::iterator format(const T &val, FormatContext &ctx) {
internal::handle_dynamic_spec<internal::width_checker>(
specs_.width_, specs_.width_ref, ctx);
internal::handle_dynamic_spec<internal::precision_checker>(
specs_.precision_, specs_.precision_ref, ctx);
visit(arg_formatter<Range>(ctx.range(), ctx, specs_),
internal::make_arg<basic_context<Range>>(val));
using range = typename FormatContext::range_type;
visit(arg_formatter<range>(ctx.range(), ctx, specs_),
internal::make_arg<FormatContext>(val));
return ctx.begin();
}
private:
@@ -2834,8 +2836,8 @@ struct dynamic_formatter {
return pointer_from(it);
}
template <typename Range, typename T>
void format(const T &val, basic_context<Range> &ctx) {
template <typename T, typename FormatContext>
auto format(const T &val, FormatContext &ctx) -> decltype(ctx.begin()) {
handle_specs(ctx);
struct null_handler : internal::error_handler {
void on_align(alignment) {}
@@ -2861,8 +2863,10 @@ struct dynamic_formatter {
}
if (specs_.precision_ != -1)
checker.end_precision();
visit(arg_formatter<Range>(ctx.range(), ctx, specs_),
internal::make_arg<basic_context<Range>>(val));
using range = typename FormatContext::range_type;
visit(arg_formatter<range>(ctx.range(), ctx, specs_),
internal::make_arg<FormatContext>(val));
return ctx.begin();
}
private:

View File

@@ -103,11 +103,12 @@ struct formatter<T, Char,
: formatter<basic_string_view<Char>, Char> {
template <typename Context>
void format(const T &value, Context &ctx) {
auto format(const T &value, Context &ctx) -> decltype(ctx.begin()) {
basic_memory_buffer<Char> buffer;
internal::format_value(buffer, value);
basic_string_view<Char> str(buffer.data(), buffer.size());
formatter<basic_string_view<Char>, Char>::format(str, ctx);
return ctx.begin();
}
};

View File

@@ -285,11 +285,12 @@ class printf_arg_formatter : public internal::arg_formatter_base<Range> {
template <typename T>
struct printf_formatter {
template <typename ParseContext>
auto parse(ParseContext& ctx) { return ctx.begin(); }
auto parse(ParseContext &ctx) { return ctx.begin(); }
template <typename Range>
void format(const T &value, basic_printf_context<Range> &ctx) {
template <typename FormatContext>
auto format(const T &value, FormatContext &ctx) -> decltype(ctx.begin()) {
internal::format_value(ctx.range().container(), value);
return ctx.begin();
}
};
@@ -306,8 +307,8 @@ class basic_printf_context :
using formatter_type = printf_formatter<T>;
private:
typedef internal::context_base<Range, basic_printf_context> Base;
using format_arg = typename Base::format_arg;
using base = internal::context_base<Range, basic_printf_context>;
using format_arg = typename base::format_arg;
using format_specs = basic_format_specs<char_type>;
using iterator = internal::null_terminating_iterator<char_type>;
@@ -332,10 +333,12 @@ class basic_printf_context :
*/
basic_printf_context(Range range, basic_string_view<char_type> format_str,
basic_format_args<basic_printf_context> args)
: Base(range, format_str, args) {}
: base(range, format_str, args) {}
using Base::parse_context;
using Base::range;
using base::parse_context;
using base::range;
using base::begin;
using base::advance_to;
/** Formats stored arguments and writes the output to the range. */
FMT_API void format();
@@ -374,7 +377,7 @@ typename basic_printf_context<Range, AF>::format_arg
(void)it;
if (arg_index == std::numeric_limits<unsigned>::max())
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>

View File

@@ -30,7 +30,7 @@ struct formatter<std::tm> {
return pointer_from(end);
}
void format(const std::tm &tm, context &ctx) {
auto format(const std::tm &tm, context &ctx) -> decltype(ctx.begin()) {
buffer &buf = ctx.range().container();
std::size_t start = buf.size();
for (;;) {
@@ -50,6 +50,7 @@ struct formatter<std::tm> {
const std::size_t MIN_GROWTH = 10;
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
}
return ctx.begin();
}
memory_buffer tm_format;