mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-31 11:17:35 +02:00
Merge vformat_to overloads
This commit is contained in:
@ -1943,7 +1943,8 @@ FMT_API std::string vformat(string_view format_str, format_args args);
|
|||||||
template <typename Char>
|
template <typename Char>
|
||||||
buffer_appender<Char> vformat_to(
|
buffer_appender<Char> vformat_to(
|
||||||
buffer<Char>& buf, basic_string_view<Char> format_str,
|
buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||||
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args);
|
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,
|
||||||
|
detail::locale_ref loc = {});
|
||||||
|
|
||||||
template <typename Char, typename Args,
|
template <typename Char, typename Args,
|
||||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||||
|
@ -3579,25 +3579,6 @@ FMT_CONSTEXPR void advance_to(
|
|||||||
ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
|
ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats arguments and writes the output to the range. */
|
|
||||||
template <typename ArgFormatter, typename Char, typename Context>
|
|
||||||
typename Context::iterator vformat_to(
|
|
||||||
typename ArgFormatter::iterator out, basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<Context> args,
|
|
||||||
detail::locale_ref loc = detail::locale_ref()) {
|
|
||||||
if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) {
|
|
||||||
auto arg = args.get(0);
|
|
||||||
if (!arg) detail::error_handler().on_error("argument not found");
|
|
||||||
using iterator = typename ArgFormatter::iterator;
|
|
||||||
return visit_format_arg(
|
|
||||||
detail::default_arg_formatter<iterator, Char>{out, args, loc}, arg);
|
|
||||||
}
|
|
||||||
detail::format_handler<ArgFormatter, Char, Context> h(out, format_str, args,
|
|
||||||
loc);
|
|
||||||
detail::parse_format_string<false>(format_str, h);
|
|
||||||
return h.context.out();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\rst
|
\rst
|
||||||
Converts ``p`` to ``const void*`` for pointer formatting.
|
Converts ``p`` to ``const void*`` for pointer formatting.
|
||||||
@ -3767,14 +3748,27 @@ std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
|
|||||||
template <typename Char>
|
template <typename Char>
|
||||||
detail::buffer_appender<Char> detail::vformat_to(
|
detail::buffer_appender<Char> detail::vformat_to(
|
||||||
detail::buffer<Char>& buf, basic_string_view<Char> format_str,
|
detail::buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args,
|
||||||
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
detail::locale_ref loc) {
|
||||||
return vformat_to<af>(buffer_appender<Char>(buf), format_str, args);
|
using iterator = typename buffer_context<Char>::iterator;
|
||||||
|
auto out = buffer_appender<Char>(buf);
|
||||||
|
if (format_str.size() == 2 && detail::equal2(format_str.data(), "{}")) {
|
||||||
|
auto arg = args.get(0);
|
||||||
|
if (!arg) detail::error_handler().on_error("argument not found");
|
||||||
|
return visit_format_arg(
|
||||||
|
detail::default_arg_formatter<iterator, Char>{out, args, loc}, arg);
|
||||||
|
}
|
||||||
|
detail::format_handler<arg_formatter<iterator, Char>, Char,
|
||||||
|
buffer_context<Char>>
|
||||||
|
h(out, format_str, args, loc);
|
||||||
|
detail::parse_format_string<false>(format_str, h);
|
||||||
|
return h.context.out();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
extern template format_context::iterator detail::vformat_to(
|
extern template format_context::iterator detail::vformat_to(
|
||||||
detail::buffer<char>&, string_view, basic_format_args<format_context>);
|
detail::buffer<char>&, string_view, basic_format_args<format_context>,
|
||||||
|
detail::locale_ref);
|
||||||
namespace detail {
|
namespace detail {
|
||||||
extern template FMT_API std::string grouping_impl<char>(locale_ref loc);
|
extern template FMT_API std::string grouping_impl<char>(locale_ref loc);
|
||||||
extern template FMT_API std::string grouping_impl<wchar_t>(locale_ref loc);
|
extern template FMT_API std::string grouping_impl<wchar_t>(locale_ref loc);
|
||||||
|
@ -20,9 +20,8 @@ typename buffer_context<Char>::iterator vformat_to(
|
|||||||
const std::locale& loc, buffer<Char>& buf,
|
const std::locale& loc, buffer<Char>& buf,
|
||||||
basic_string_view<Char> format_str,
|
basic_string_view<Char> format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
return vformat_to(buf, to_string_view(format_str), args,
|
||||||
return vformat_to<af>(buffer_appender<Char>(buf), to_string_view(format_str),
|
detail::locale_ref(loc));
|
||||||
args, detail::locale_ref(loc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
@ -56,10 +55,7 @@ inline OutputIt vformat_to(
|
|||||||
OutputIt out, const std::locale& loc, const S& format_str,
|
OutputIt out, const std::locale& loc, const S& format_str,
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||||
using af =
|
vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
|
||||||
detail::arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
|
||||||
vformat_to<af>(detail::buffer_appender<Char>(buf), to_string_view(format_str),
|
|
||||||
args, detail::locale_ref(loc));
|
|
||||||
return detail::get_iterator(buf);
|
return detail::get_iterator(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
|||||||
|
|
||||||
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
|
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
|
||||||
detail::buffer<char>&, string_view,
|
detail::buffer<char>&, string_view,
|
||||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>);
|
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
|
||||||
|
|
||||||
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
||||||
detail::buffer<char>&);
|
detail::buffer<char>&);
|
||||||
|
@ -1842,62 +1842,6 @@ TEST(FormatTest, StrongEnum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using buffer_iterator = fmt::format_context::iterator;
|
|
||||||
|
|
||||||
class mock_arg_formatter
|
|
||||||
: public fmt::detail::arg_formatter_base<buffer_iterator, char> {
|
|
||||||
private:
|
|
||||||
#if FMT_USE_INT128
|
|
||||||
MOCK_METHOD1(call, void(__int128_t value));
|
|
||||||
#else
|
|
||||||
MOCK_METHOD1(call, void(long long value));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
using base = fmt::detail::arg_formatter_base<buffer_iterator, char>;
|
|
||||||
|
|
||||||
mock_arg_formatter(fmt::format_context& ctx, fmt::format_parse_context*,
|
|
||||||
fmt::format_specs* s = nullptr, const char* = nullptr)
|
|
||||||
: base(ctx.out(), s, ctx.locale()) {
|
|
||||||
EXPECT_CALL(*this, call(42));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<fmt::detail::is_integral<T>::value &&
|
|
||||||
fmt::detail::is_signed<T>::value,
|
|
||||||
iterator>::type
|
|
||||||
operator()(T value) {
|
|
||||||
call(value);
|
|
||||||
return base::operator()(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<!(fmt::detail::is_integral<T>::value &&
|
|
||||||
fmt::detail::is_signed<T>::value),
|
|
||||||
iterator>::type
|
|
||||||
operator()(T value) {
|
|
||||||
return base::operator()(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator operator()(fmt::basic_format_arg<fmt::format_context>::handle) {
|
|
||||||
return base::operator()(fmt::monostate());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
|
||||||
fmt::memory_buffer buf;
|
|
||||||
fmt::vformat_to<mock_arg_formatter>(fmt::detail::buffer_appender<char>(buf),
|
|
||||||
format_str, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
void custom_format(const char* format_str, const Args&... args) {
|
|
||||||
auto va = fmt::make_format_args(args...);
|
|
||||||
return custom_vformat(format_str, va);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(FormatTest, CustomArgFormatter) { custom_format("{}", 42); }
|
|
||||||
|
|
||||||
TEST(FormatTest, NonNullTerminatedFormatString) {
|
TEST(FormatTest, NonNullTerminatedFormatString) {
|
||||||
EXPECT_EQ("42", format(string_view("{}foo", 2), 42));
|
EXPECT_EQ("42", format(string_view("{}foo", 2), 42));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user