mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-26 04:00:05 +00:00
Return output iterator to the end from format_to_n
This commit is contained in:
parent
174087bfdb
commit
3cf0526316
@ -1069,7 +1069,7 @@ FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
|
|||||||
typedef typename Context::char_type char_type;
|
typedef typename Context::char_type char_type;
|
||||||
switch (arg.type_) {
|
switch (arg.type_) {
|
||||||
case internal::none_type:
|
case internal::none_type:
|
||||||
return vis(monostate());
|
break;
|
||||||
case internal::name_arg_type:
|
case internal::name_arg_type:
|
||||||
FMT_ASSERT(false, "invalid argument type");
|
FMT_ASSERT(false, "invalid argument type");
|
||||||
break;
|
break;
|
||||||
@ -1099,7 +1099,7 @@ FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
|
|||||||
case internal::custom_type:
|
case internal::custom_type:
|
||||||
return vis(typename basic_arg<Context>::handle(arg.value_.custom));
|
return vis(typename basic_arg<Context>::handle(arg.value_.custom));
|
||||||
}
|
}
|
||||||
return typename internal::result_of<Visitor(int)>::type();
|
return vis(monostate());
|
||||||
}
|
}
|
||||||
|
|
||||||
enum alignment {
|
enum alignment {
|
||||||
@ -1392,6 +1392,7 @@ template <typename Range>
|
|||||||
class arg_formatter_base {
|
class arg_formatter_base {
|
||||||
public:
|
public:
|
||||||
typedef typename Range::value_type char_type;
|
typedef typename Range::value_type char_type;
|
||||||
|
typedef decltype(internal::declval<Range>().begin()) iterator;
|
||||||
typedef basic_format_specs<char_type> format_specs;
|
typedef basic_format_specs<char_type> format_specs;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1422,6 +1423,7 @@ class arg_formatter_base {
|
|||||||
protected:
|
protected:
|
||||||
writer_type &writer() { return writer_; }
|
writer_type &writer() { return writer_; }
|
||||||
format_specs &spec() { return specs_; }
|
format_specs &spec() { return specs_; }
|
||||||
|
iterator out() { return writer_.out(); }
|
||||||
|
|
||||||
void write(bool value) {
|
void write(bool value) {
|
||||||
writer_.write_str(string_view(value ? "true" : "false"), specs_);
|
writer_.write_str(string_view(value ? "true" : "false"), specs_);
|
||||||
@ -1437,22 +1439,30 @@ class arg_formatter_base {
|
|||||||
public:
|
public:
|
||||||
arg_formatter_base(Range r, format_specs &s): writer_(r), specs_(s) {}
|
arg_formatter_base(Range r, format_specs &s): writer_(r), specs_(s) {}
|
||||||
|
|
||||||
void operator()(monostate) {
|
iterator operator()(monostate) {
|
||||||
FMT_ASSERT(false, "invalid argument type");
|
FMT_ASSERT(false, "invalid argument type");
|
||||||
|
return out();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<std::is_integral<T>::value>::type
|
typename std::enable_if<std::is_integral<T>::value, iterator>::type
|
||||||
operator()(T value) { writer_.write_int(value, specs_); }
|
operator()(T value) {
|
||||||
|
writer_.write_int(value, specs_);
|
||||||
|
return out();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<std::is_floating_point<T>::value>::type
|
typename std::enable_if<std::is_floating_point<T>::value, iterator>::type
|
||||||
operator()(T value) { writer_.write_double(value, specs_); }
|
operator()(T value) {
|
||||||
|
writer_.write_double(value, specs_);
|
||||||
|
return out();
|
||||||
|
}
|
||||||
|
|
||||||
void operator()(bool value) {
|
iterator operator()(bool value) {
|
||||||
if (specs_.type_)
|
if (specs_.type_)
|
||||||
return (*this)(value ? 1 : 0);
|
return (*this)(value ? 1 : 0);
|
||||||
write(value);
|
write(value);
|
||||||
|
return out();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct char_spec_handler : internal::error_handler {
|
struct char_spec_handler : internal::error_handler {
|
||||||
@ -1466,8 +1476,9 @@ class arg_formatter_base {
|
|||||||
void on_char() { formatter.write_char(value); }
|
void on_char() { formatter.write_char(value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void operator()(char_type value) {
|
iterator operator()(char_type value) {
|
||||||
internal::handle_char_specs(specs_, char_spec_handler(*this, value));
|
internal::handle_char_specs(specs_, char_spec_handler(*this, value));
|
||||||
|
return out();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cstring_spec_handler : internal::error_handler {
|
struct cstring_spec_handler : internal::error_handler {
|
||||||
@ -1481,19 +1492,22 @@ class arg_formatter_base {
|
|||||||
void on_pointer() { formatter.write_pointer(value); }
|
void on_pointer() { formatter.write_pointer(value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void operator()(const char_type *value) {
|
iterator operator()(const char_type *value) {
|
||||||
internal::handle_cstring_type_spec(
|
internal::handle_cstring_type_spec(
|
||||||
specs_.type_, cstring_spec_handler(*this, value));
|
specs_.type_, cstring_spec_handler(*this, value));
|
||||||
|
return out();
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(basic_string_view<char_type> value) {
|
iterator operator()(basic_string_view<char_type> value) {
|
||||||
internal::check_string_type_spec(specs_.type_, internal::error_handler());
|
internal::check_string_type_spec(specs_.type_, internal::error_handler());
|
||||||
writer_.write_str(value, specs_);
|
writer_.write_str(value, specs_);
|
||||||
|
return out();
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const void *value) {
|
iterator operator()(const void *value) {
|
||||||
check_pointer_type_spec(specs_.type_, internal::error_handler());
|
check_pointer_type_spec(specs_.type_, internal::error_handler());
|
||||||
write_pointer(value);
|
write_pointer(value);
|
||||||
|
return out();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2172,14 +2186,14 @@ class arg_formatter:
|
|||||||
public internal::function<void>, public internal::arg_formatter_base<Range> {
|
public internal::function<void>, public internal::arg_formatter_base<Range> {
|
||||||
private:
|
private:
|
||||||
typedef typename Range::value_type char_type;
|
typedef typename Range::value_type char_type;
|
||||||
typedef decltype(internal::declval<Range>().begin()) iterator;
|
|
||||||
typedef internal::arg_formatter_base<Range> base;
|
typedef internal::arg_formatter_base<Range> base;
|
||||||
typedef basic_context<iterator, char_type> context_type;
|
typedef basic_context<typename base::iterator, char_type> context_type;
|
||||||
|
|
||||||
context_type &ctx_;
|
context_type &ctx_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Range range;
|
typedef Range range;
|
||||||
|
typedef typename base::iterator iterator;
|
||||||
typedef typename base::format_specs format_specs;
|
typedef typename base::format_specs format_specs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2195,8 +2209,9 @@ class arg_formatter:
|
|||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
/** Formats an argument of a user-defined type. */
|
/** Formats an argument of a user-defined type. */
|
||||||
void operator()(typename basic_arg<context_type>::handle handle) const {
|
iterator operator()(typename basic_arg<context_type>::handle handle) {
|
||||||
handle.format(ctx_);
|
handle.format(ctx_);
|
||||||
|
return this->out();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2290,6 +2305,8 @@ class basic_writer {
|
|||||||
static char_type *get(char_type *p) { return p; }
|
static char_type *get(char_type *p) { return p; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
iterator out() const { return out_; }
|
||||||
|
|
||||||
// Attempts to reserve space for n extra characters in the output range.
|
// Attempts to reserve space for n extra characters in the output range.
|
||||||
// Returns a pointer to the reserved range or a reference to out_.
|
// Returns a pointer to the reserved range or a reference to out_.
|
||||||
auto reserve(std::size_t n) -> decltype(internal::reserve(out_, n)) {
|
auto reserve(std::size_t n) -> decltype(internal::reserve(out_, n)) {
|
||||||
@ -2668,7 +2685,6 @@ void basic_writer<Range>::write_padded(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
void basic_writer<Range>::write_str(
|
void basic_writer<Range>::write_str(
|
||||||
@ -3213,18 +3229,16 @@ struct format_handler : internal::error_handler {
|
|||||||
|
|
||||||
void on_replacement_field(iterator it) {
|
void on_replacement_field(iterator it) {
|
||||||
context.parse_context().advance_to(pointer_from(it));
|
context.parse_context().advance_to(pointer_from(it));
|
||||||
using internal::custom_formatter;
|
if (visit(internal::custom_formatter<Char, Context>(context), arg))
|
||||||
if (visit(custom_formatter<Char, Context>(context), arg))
|
|
||||||
return;
|
return;
|
||||||
basic_format_specs<Char> specs;
|
basic_format_specs<Char> specs;
|
||||||
visit(ArgFormatter(context, specs), arg);
|
context.advance_to(visit(ArgFormatter(context, specs), arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator on_format_specs(iterator it) {
|
iterator on_format_specs(iterator it) {
|
||||||
auto& parse_ctx = context.parse_context();
|
auto& parse_ctx = context.parse_context();
|
||||||
parse_ctx.advance_to(pointer_from(it));
|
parse_ctx.advance_to(pointer_from(it));
|
||||||
using internal::custom_formatter;
|
if (visit(internal::custom_formatter<Char, Context>(context), arg))
|
||||||
if (visit(custom_formatter<Char, Context>(context), arg))
|
|
||||||
return iterator(parse_ctx);
|
return iterator(parse_ctx);
|
||||||
basic_format_specs<Char> specs;
|
basic_format_specs<Char> specs;
|
||||||
using internal::specs_handler;
|
using internal::specs_handler;
|
||||||
@ -3234,7 +3248,7 @@ struct format_handler : internal::error_handler {
|
|||||||
if (*it != '}')
|
if (*it != '}')
|
||||||
on_error("missing '}' in format string");
|
on_error("missing '}' in format string");
|
||||||
parse_ctx.advance_to(pointer_from(it));
|
parse_ctx.advance_to(pointer_from(it));
|
||||||
visit(ArgFormatter(context, specs), arg);
|
context.advance_to(visit(ArgFormatter(context, specs), arg));
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,45 +246,49 @@ class printf_arg_formatter:
|
|||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
/** Formats an argument of type ``bool``. */
|
/** Formats an argument of type ``bool``. */
|
||||||
void operator()(bool value) {
|
iterator operator()(bool value) {
|
||||||
format_specs &fmt_spec = this->spec();
|
format_specs &fmt_spec = this->spec();
|
||||||
if (fmt_spec.type_ != 's')
|
if (fmt_spec.type_ != 's')
|
||||||
return (*this)(value ? 1 : 0);
|
return (*this)(value ? 1 : 0);
|
||||||
fmt_spec.type_ = 0;
|
fmt_spec.type_ = 0;
|
||||||
this->write(value);
|
this->write(value);
|
||||||
|
return this->out();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats a character. */
|
/** Formats a character. */
|
||||||
void operator()(char_type value) {
|
iterator operator()(char_type value) {
|
||||||
format_specs &fmt_spec = this->spec();
|
format_specs &fmt_spec = this->spec();
|
||||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||||
return (*this)(static_cast<int>(value));
|
return (*this)(static_cast<int>(value));
|
||||||
fmt_spec.flags_ = 0;
|
fmt_spec.flags_ = 0;
|
||||||
fmt_spec.align_ = ALIGN_RIGHT;
|
fmt_spec.align_ = ALIGN_RIGHT;
|
||||||
base::operator()(value);
|
return base::operator()(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats a null-terminated C string. */
|
/** Formats a null-terminated C string. */
|
||||||
void operator()(const char *value) {
|
iterator operator()(const char *value) {
|
||||||
if (value)
|
if (value)
|
||||||
base::operator()(value);
|
base::operator()(value);
|
||||||
else if (this->spec().type_ == 'p')
|
else if (this->spec().type_ == 'p')
|
||||||
write_null_pointer();
|
write_null_pointer();
|
||||||
else
|
else
|
||||||
this->write("(null)");
|
this->write("(null)");
|
||||||
|
return this->out();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats a pointer. */
|
/** Formats a pointer. */
|
||||||
void operator()(const void *value) {
|
iterator operator()(const void *value) {
|
||||||
if (value)
|
if (value)
|
||||||
return base::operator()(value);
|
return base::operator()(value);
|
||||||
this->spec().type_ = 0;
|
this->spec().type_ = 0;
|
||||||
write_null_pointer();
|
write_null_pointer();
|
||||||
|
return this->out();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats an argument of a custom (user-defined) type. */
|
/** Formats an argument of a custom (user-defined) type. */
|
||||||
void operator()(typename basic_arg<context_type>::handle handle) {
|
iterator operator()(typename basic_arg<context_type>::handle handle) {
|
||||||
handle.format(context_);
|
handle.format(context_);
|
||||||
|
return this->out();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ class custom_arg_formatter :
|
|||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
void operator()(double value) {
|
iterator operator()(double value) {
|
||||||
if (round(value * pow(10, spec().precision())) == 0)
|
if (round(value * pow(10, spec().precision())) == 0)
|
||||||
value = 0;
|
value = 0;
|
||||||
base::operator()(value);
|
return base::operator()(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1416,9 +1416,14 @@ class mock_arg_formatter:
|
|||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
void operator()(int value) { call(value); }
|
iterator operator()(int value) {
|
||||||
|
call(value);
|
||||||
|
return base::operator()(value);
|
||||||
|
}
|
||||||
|
|
||||||
void operator()(fmt::basic_arg<fmt::context>::handle) {}
|
iterator operator()(fmt::basic_arg<fmt::context>::handle) {
|
||||||
|
return base::operator()(fmt::monostate());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||||
@ -1510,7 +1515,12 @@ TEST(FormatTest, FormatToN) {
|
|||||||
buffer[3] = 'x';
|
buffer[3] = 'x';
|
||||||
auto result = fmt::format_to_n(buffer, 3, "{}", 12345);
|
auto result = fmt::format_to_n(buffer, 3, "{}", 12345);
|
||||||
EXPECT_EQ(5u, result.size);
|
EXPECT_EQ(5u, result.size);
|
||||||
|
EXPECT_EQ(buffer + 3, result.out);
|
||||||
EXPECT_EQ("123x", fmt::string_view(buffer, 4));
|
EXPECT_EQ("123x", fmt::string_view(buffer, 4));
|
||||||
|
result = fmt::format_to_n(buffer, 3, "{:s}", "foobar");
|
||||||
|
EXPECT_EQ(6u, result.size);
|
||||||
|
EXPECT_EQ(buffer + 3, result.out);
|
||||||
|
EXPECT_EQ("foox", fmt::string_view(buffer, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FMT_USE_CONSTEXPR
|
#if FMT_USE_CONSTEXPR
|
||||||
|
Loading…
Reference in New Issue
Block a user