Update std implementation
This commit is contained in:
parent
442fa1bd46
commit
e4572e5def
@ -1337,7 +1337,7 @@ struct char_t : std::enable_if<internal::is_string<S>::value,
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
template <typename Context>
|
template <typename Context>
|
||||||
FMT_CONSTEXPR basic_format_arg<Context> get_arg(Context& ctx, unsigned id) {
|
FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, unsigned id) {
|
||||||
auto arg = ctx.arg(id);
|
auto arg = ctx.arg(id);
|
||||||
if (!arg) ctx.on_error("argument index out of range");
|
if (!arg) ctx.on_error("argument index out of range");
|
||||||
return arg;
|
return arg;
|
||||||
|
@ -343,6 +343,7 @@ class basic_printf_context {
|
|||||||
public:
|
public:
|
||||||
/** The character type for the output. */
|
/** The character type for the output. */
|
||||||
typedef Char char_type;
|
typedef Char char_type;
|
||||||
|
typedef basic_format_arg<basic_printf_context> format_arg;
|
||||||
|
|
||||||
template <typename T> struct formatter_type {
|
template <typename T> struct formatter_type {
|
||||||
typedef printf_formatter<T> type;
|
typedef printf_formatter<T> type;
|
||||||
@ -350,7 +351,6 @@ class basic_printf_context {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
typedef internal::context_base<OutputIt, basic_printf_context, Char> base;
|
typedef internal::context_base<OutputIt, basic_printf_context, Char> base;
|
||||||
typedef basic_format_arg<basic_printf_context> format_arg;
|
|
||||||
typedef basic_format_specs<char_type> format_specs;
|
typedef basic_format_specs<char_type> format_specs;
|
||||||
|
|
||||||
OutputIt out_;
|
OutputIt out_;
|
||||||
|
@ -191,9 +191,8 @@ constexpr void basic_format_parse_context<charT>::check_arg_id(size_t) {
|
|||||||
namespace std {
|
namespace std {
|
||||||
template<class O, class charT> FMT_REQUIRES(OutputIterator<O, const charT&>)
|
template<class O, class charT> FMT_REQUIRES(OutputIterator<O, const charT&>)
|
||||||
class basic_format_context {
|
class basic_format_context {
|
||||||
basic_format_parse_context<charT> parse_context_; // exposition only
|
basic_format_args<basic_format_context> args_; // exposition only
|
||||||
basic_format_args<basic_format_context> args_; // exposition only
|
O out_; // exposition only
|
||||||
O out_; // exposition only
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using iterator = O;
|
using iterator = O;
|
||||||
@ -202,7 +201,6 @@ namespace std {
|
|||||||
template<class T>
|
template<class T>
|
||||||
using formatter_type = formatter<T>;
|
using formatter_type = formatter<T>;
|
||||||
|
|
||||||
basic_format_parse_context<charT>& parse_context() noexcept;
|
|
||||||
basic_format_arg<basic_format_context> arg(size_t id) const;
|
basic_format_arg<basic_format_context> arg(size_t id) const;
|
||||||
|
|
||||||
iterator out();
|
iterator out();
|
||||||
@ -210,11 +208,8 @@ namespace std {
|
|||||||
|
|
||||||
// Implementation details:
|
// Implementation details:
|
||||||
using format_arg = basic_format_arg<basic_format_context>;
|
using format_arg = basic_format_arg<basic_format_context>;
|
||||||
basic_format_context(O out, fmt::string_view fmt, basic_format_args<basic_format_context> args, fmt::internal::locale_ref)
|
basic_format_context(O out, basic_format_args<basic_format_context> args, fmt::internal::locale_ref)
|
||||||
: out_(out), parse_context_({fmt.data(), fmt.size()}), args_(args) {}
|
: out_(out), args_(args) {}
|
||||||
basic_format_arg<basic_format_context> next_arg() {
|
|
||||||
return arg(parse_context_.next_arg_id());
|
|
||||||
}
|
|
||||||
fmt::internal::error_handler error_handler() const { return {}; }
|
fmt::internal::error_handler error_handler() const { return {}; }
|
||||||
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
basic_format_arg<basic_format_context> arg(fmt::basic_string_view<charT>) const {
|
||||||
return {}; // unused: named arguments are not supported yet
|
return {}; // unused: named arguments are not supported yet
|
||||||
@ -224,9 +219,6 @@ namespace std {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template<class O, class charT>
|
|
||||||
basic_format_parse_context<charT>& basic_format_context<O, charT>::parse_context() noexcept { return parse_context_; }
|
|
||||||
|
|
||||||
template<class O, class charT>
|
template<class O, class charT>
|
||||||
basic_format_arg<basic_format_context<O, charT>> basic_format_context<O, charT>::arg(size_t id) const { return args_.get(id); }
|
basic_format_arg<basic_format_context<O, charT>> basic_format_context<O, charT>::arg(size_t id) const { return args_.get(id); }
|
||||||
|
|
||||||
@ -360,33 +352,39 @@ template<class Context>
|
|||||||
template<class T, typename>
|
template<class T, typename>
|
||||||
/* explicit */ basic_format_arg<Context>::basic_format_arg(const T& v) noexcept
|
/* explicit */ basic_format_arg<Context>::basic_format_arg(const T& v) noexcept
|
||||||
: value(handle(v)) {}
|
: value(handle(v)) {}
|
||||||
|
|
||||||
|
template<class Context>
|
||||||
|
/* explicit */ basic_format_arg<Context>::operator bool() const noexcept {
|
||||||
|
return !holds_alternative<monostate>(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template<class Context>
|
template<class Context>
|
||||||
class basic_format_arg<Context>::handle {
|
class basic_format_arg<Context>::handle {
|
||||||
const void* ptr_; // exposition only
|
const void* ptr_; // exposition only
|
||||||
void (*format_)(Context&, const void*); // exposition only
|
void (*format_)(basic_format_parse_context<char_type>&,
|
||||||
|
Context&, const void*); // exposition only
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class T> explicit handle(const T& val) noexcept; // exposition only
|
template<class T> explicit handle(const T& val) noexcept; // exposition only
|
||||||
|
|
||||||
void format(Context& ctx) const;
|
void format(basic_format_parse_context<char_type>&, Context& ctx) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template<class Context>
|
template<class Context>
|
||||||
template<class T> /* explicit */ basic_format_arg<Context>::handle::handle(const T& val) noexcept
|
template<class T> /* explicit */ basic_format_arg<Context>::handle::handle(const T& val) noexcept
|
||||||
: ptr_(&val), format_([](Context& ctx, const void* ptr) {
|
: ptr_(&val), format_([](basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx, const void* ptr) {
|
||||||
typename Context::template formatter_type<T> f;
|
typename Context::template formatter_type<T> f;
|
||||||
ctx.parse_context().advance_to(f.parse(ctx.parse_context()));
|
parse_ctx.advance_to(f.parse(parse_ctx));
|
||||||
ctx.advance_to(f.format(*static_cast<const T*>(ptr), ctx));
|
format_ctx.advance_to(f.format(*static_cast<const T*>(ptr), format_ctx));
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
template<class Context>
|
template<class Context>
|
||||||
void basic_format_arg<Context>::handle::format(Context& ctx) const {
|
void basic_format_arg<Context>::handle::format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const {
|
||||||
format_(ctx, ptr_);
|
format_(parse_ctx, format_ctx, ptr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://fmtlib.net/Text%20Formatting.html#format.visit
|
// http://fmtlib.net/Text%20Formatting.html#format.visit
|
||||||
@ -460,11 +458,13 @@ class arg_formatter
|
|||||||
typename fmt::internal::arg_formatter_base<Range>::iterator>,
|
typename fmt::internal::arg_formatter_base<Range>::iterator>,
|
||||||
public fmt::internal::arg_formatter_base<Range> {
|
public fmt::internal::arg_formatter_base<Range> {
|
||||||
private:
|
private:
|
||||||
typedef typename Range::value_type char_type;
|
using char_type = typename Range::value_type;
|
||||||
typedef fmt::internal::arg_formatter_base<Range> base;
|
using base = fmt::internal::arg_formatter_base<Range>;
|
||||||
typedef std::basic_format_context<typename base::iterator, char_type> context_type;
|
using format_context = std::basic_format_context<typename base::iterator, char_type>;
|
||||||
|
using parse_context = basic_format_parse_context<char_type>;
|
||||||
|
|
||||||
context_type& ctx_;
|
parse_context& parse_ctx_;
|
||||||
|
format_context& ctx_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Range range;
|
typedef Range range;
|
||||||
@ -478,14 +478,14 @@ class arg_formatter
|
|||||||
*spec* contains format specifier information for standard argument types.
|
*spec* contains format specifier information for standard argument types.
|
||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
explicit arg_formatter(context_type& ctx, fmt::format_specs* spec = FMT_NULL)
|
arg_formatter(parse_context& parse_ctx, format_context& ctx, fmt::format_specs* spec = FMT_NULL)
|
||||||
: base(Range(ctx.out()), spec, {}), ctx_(ctx) {}
|
: base(Range(ctx.out()), spec, {}), parse_ctx_(parse_ctx), ctx_(ctx) {}
|
||||||
|
|
||||||
using base::operator();
|
using base::operator();
|
||||||
|
|
||||||
/** Formats an argument of a user-defined type. */
|
/** Formats an argument of a user-defined type. */
|
||||||
iterator operator()(typename std::basic_format_arg<context_type>::handle handle) {
|
iterator operator()(typename std::basic_format_arg<format_context>::handle handle) {
|
||||||
handle.format(ctx_);
|
handle.format(parse_ctx_, ctx_);
|
||||||
return this->out();
|
return this->out();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,16 +528,18 @@ inline fmt::internal::type get_type(basic_format_arg<Context> arg) {
|
|||||||
}, arg);
|
}, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char, typename Context>
|
template <typename Context>
|
||||||
class custom_formatter {
|
class custom_formatter {
|
||||||
private:
|
private:
|
||||||
Context& ctx_;
|
using parse_context = basic_format_parse_context<typename Context::char_type>;
|
||||||
|
parse_context& parse_ctx_;
|
||||||
|
Context& format_ctx_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit custom_formatter(Context& ctx) : ctx_(ctx) {}
|
custom_formatter(parse_context& parse_ctx, Context& ctx) : parse_ctx_(parse_ctx), format_ctx_(ctx) {}
|
||||||
|
|
||||||
bool operator()(typename basic_format_arg<Context>::handle h) const {
|
bool operator()(typename basic_format_arg<Context>::handle h) const {
|
||||||
h.format(ctx_);
|
h.format(parse_ctx_, format_ctx_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,7 +553,7 @@ struct format_handler : fmt::internal::error_handler {
|
|||||||
format_handler(range r, basic_string_view<Char> str,
|
format_handler(range r, basic_string_view<Char> str,
|
||||||
basic_format_args<Context> format_args,
|
basic_format_args<Context> format_args,
|
||||||
fmt::internal::locale_ref loc)
|
fmt::internal::locale_ref loc)
|
||||||
: context(r.begin(), str, format_args, loc) {}
|
: parse_ctx(str), context(r.begin(), format_args, loc) {}
|
||||||
|
|
||||||
void on_text(const Char* begin, const Char* end) {
|
void on_text(const Char* begin, const Char* end) {
|
||||||
auto size = fmt::internal::to_unsigned(end - begin);
|
auto size = fmt::internal::to_unsigned(end - begin);
|
||||||
@ -561,24 +563,25 @@ struct format_handler : fmt::internal::error_handler {
|
|||||||
context.advance_to(out);
|
context.advance_to(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_arg_id() { arg = context.next_arg(); }
|
void on_arg_id() {
|
||||||
|
arg = context.arg(parse_ctx.next_arg_id());
|
||||||
|
}
|
||||||
void on_arg_id(unsigned id) {
|
void on_arg_id(unsigned id) {
|
||||||
context.parse_context().check_arg_id(id);
|
parse_ctx.check_arg_id(id);
|
||||||
arg = context.arg(id);
|
arg = context.arg(id);
|
||||||
}
|
}
|
||||||
void on_arg_id(fmt::basic_string_view<Char> id) {}
|
void on_arg_id(fmt::basic_string_view<Char> id) {}
|
||||||
|
|
||||||
void on_replacement_field(const Char* p) {
|
void on_replacement_field(const Char* p) {
|
||||||
context.parse_context().advance_to(p);
|
parse_ctx.advance_to(p);
|
||||||
custom_formatter<Char, Context> f(context);
|
custom_formatter<Context> f(parse_ctx, context);
|
||||||
if (!visit_format_arg(f, arg))
|
if (!visit_format_arg(f, arg))
|
||||||
context.advance_to(visit_format_arg(ArgFormatter(context), arg));
|
context.advance_to(visit_format_arg(ArgFormatter(parse_ctx, context), arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Char* on_format_specs(const Char* begin, const Char* end) {
|
const Char* on_format_specs(const Char* begin, const Char* end) {
|
||||||
auto& parse_ctx = context.parse_context();
|
|
||||||
parse_ctx.advance_to(begin);
|
parse_ctx.advance_to(begin);
|
||||||
custom_formatter<Char, Context> f(context);
|
custom_formatter<Context> f(parse_ctx, context);
|
||||||
if (visit_format_arg(f, arg)) return parse_ctx.begin();
|
if (visit_format_arg(f, arg)) return parse_ctx.begin();
|
||||||
fmt::basic_format_specs<Char> specs;
|
fmt::basic_format_specs<Char> specs;
|
||||||
using fmt::internal::specs_handler;
|
using fmt::internal::specs_handler;
|
||||||
@ -588,10 +591,11 @@ struct format_handler : fmt::internal::error_handler {
|
|||||||
begin = parse_format_specs(begin, end, handler);
|
begin = parse_format_specs(begin, end, handler);
|
||||||
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
if (begin == end || *begin != '}') on_error("missing '}' in format string");
|
||||||
parse_ctx.advance_to(begin);
|
parse_ctx.advance_to(begin);
|
||||||
context.advance_to(visit_format_arg(ArgFormatter(context, &specs), arg));
|
context.advance_to(visit_format_arg(ArgFormatter(parse_ctx, context, &specs), arg));
|
||||||
return begin;
|
return begin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
basic_format_parse_context<Char> parse_ctx;
|
||||||
Context context;
|
Context context;
|
||||||
basic_format_arg<Context> arg;
|
basic_format_arg<Context> arg;
|
||||||
};
|
};
|
||||||
@ -705,7 +709,7 @@ template<FMT_CONCEPT(OutputIterator<const wchar_t&>) O, class... Args>
|
|||||||
template<FMT_CONCEPT(OutputIterator<const char&>) O>
|
template<FMT_CONCEPT(OutputIterator<const char&>) O>
|
||||||
O vformat_to(O out, string_view fmt, format_args_t<O, char> args) {
|
O vformat_to(O out, string_view fmt, format_args_t<O, char> args) {
|
||||||
typedef fmt::output_range<O, char> range;
|
typedef fmt::output_range<O, char> range;
|
||||||
detail::format_handler<detail::arg_formatter<range>, char, format_context>
|
detail::format_handler<detail::arg_formatter<range>, char, basic_format_context<O, char>>
|
||||||
h(range(out), fmt, args, {});
|
h(range(out), fmt, args, {});
|
||||||
fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
fmt::internal::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||||
return h.context.out();
|
return h.context.out();
|
||||||
|
Loading…
Reference in New Issue
Block a user