mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-26 12:35:32 +00:00
Reduce symbol sizes and simplify iterator use
This commit is contained in:
parent
c5adfc51c5
commit
b998e0f30b
@ -608,8 +608,7 @@ template <typename CompiledFormat, typename... Args,
|
||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
using context = buffer_context<Char>;
|
||||
detail::buffer<Char>& base = buffer;
|
||||
detail::cf::vformat_to<context>(std::back_inserter(base), cf,
|
||||
detail::cf::vformat_to<context>(detail::buffer_appender<Char>(buffer), cf,
|
||||
make_format_args<context>(args...));
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
@ -722,6 +722,17 @@ class container_buffer : public buffer<typename Container::value_type> {
|
||||
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
||||
};
|
||||
|
||||
// An output iterator that appends to the buffer.
|
||||
// It is used to reduce symbol sizes for the common case.
|
||||
template <typename T>
|
||||
class buffer_appender : public std::back_insert_iterator<buffer<T>> {
|
||||
public:
|
||||
explicit buffer_appender(buffer<T>& buf)
|
||||
: std::back_insert_iterator<buffer<T>>(buf) {}
|
||||
buffer_appender(std::back_insert_iterator<buffer<T>> it)
|
||||
: std::back_insert_iterator<buffer<T>>(it) {}
|
||||
};
|
||||
|
||||
// Extracts a reference to the container from back_insert_iterator.
|
||||
template <typename Container>
|
||||
inline Container& get_container(std::back_insert_iterator<Container> it) {
|
||||
@ -1356,13 +1367,13 @@ template <typename OutputIt, typename Char> class basic_format_context {
|
||||
|
||||
template <typename Char>
|
||||
using buffer_context =
|
||||
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>;
|
||||
basic_format_context<detail::buffer_appender<Char>, Char>;
|
||||
using format_context = buffer_context<char>;
|
||||
using wformat_context = buffer_context<wchar_t>;
|
||||
|
||||
// Workaround a bug in gcc: https://stackoverflow.com/q/62767544/471164.
|
||||
// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164.
|
||||
#define FMT_BUFFER_CONTEXT(Char) \
|
||||
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>
|
||||
basic_format_context<detail::buffer_appender<Char>, Char>
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -1772,7 +1783,7 @@ std::basic_string<Char> vformat(
|
||||
FMT_API std::string vformat(string_view format_str, format_args args);
|
||||
|
||||
template <typename Char>
|
||||
typename FMT_BUFFER_CONTEXT(Char)::iterator vformat_to(
|
||||
buffer_appender<Char> vformat_to(
|
||||
buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args);
|
||||
|
||||
|
@ -1296,6 +1296,19 @@ FMT_FUNC const char* utf8_decode(const char* buf, uint32_t* c, int* e) {
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
struct stringifier {
|
||||
template <typename T> FMT_INLINE std::string operator()(T value) const {
|
||||
return to_string(value);
|
||||
}
|
||||
std::string operator()(basic_format_arg<format_context>::handle h) const {
|
||||
memory_buffer buf;
|
||||
format_parse_context parse_ctx({});
|
||||
format_context format_ctx(buffer_appender<char>(buf), {}, {});
|
||||
h.format(parse_ctx, format_ctx);
|
||||
return to_string(buf);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <> struct formatter<detail::bigint> {
|
||||
@ -1384,20 +1397,6 @@ FMT_FUNC void report_system_error(int error_code,
|
||||
report_error(format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
struct stringifier {
|
||||
template <typename T> FMT_INLINE std::string operator()(T value) const {
|
||||
return to_string(value);
|
||||
}
|
||||
std::string operator()(basic_format_arg<format_context>::handle h) const {
|
||||
memory_buffer buf;
|
||||
detail::buffer<char>& base = buf;
|
||||
format_parse_context parse_ctx({});
|
||||
format_context format_ctx(std::back_inserter(base), {}, {});
|
||||
h.format(parse_ctx, format_ctx);
|
||||
return to_string(buf);
|
||||
}
|
||||
};
|
||||
|
||||
FMT_FUNC std::string detail::vformat(string_view format_str, format_args args) {
|
||||
if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
|
||||
auto arg = args.get(0);
|
||||
|
@ -371,6 +371,11 @@ reserve(std::back_insert_iterator<Container> it, size_t n) {
|
||||
return make_checked(get_data(c) + size, n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline checked_ptr<T> reserve(buffer_appender<T> it, size_t n) {
|
||||
return reserve(std::back_insert_iterator<buffer<T>>(it), n);
|
||||
}
|
||||
|
||||
template <typename Iterator> inline Iterator& reserve(Iterator& it, size_t) {
|
||||
return it;
|
||||
}
|
||||
@ -2933,7 +2938,7 @@ class arg_formatter : public arg_formatter_base<OutputIt, Char> {
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
using arg_formatter FMT_DEPRECATED_ALIAS =
|
||||
detail::arg_formatter<OutputIt, Char>;
|
||||
detail::arg_formatter<OutputIt, Char>;
|
||||
|
||||
/**
|
||||
An error returned by an operating system or a language runtime,
|
||||
@ -3445,11 +3450,11 @@ std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
typename buffer_context<Char>::iterator detail::vformat_to(
|
||||
detail::buffer_appender<Char> detail::vformat_to(
|
||||
detail::buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
||||
return vformat_to<af>(std::back_inserter(buf), to_string_view(format_str),
|
||||
return vformat_to<af>(buffer_appender<Char>(buf), to_string_view(format_str),
|
||||
args);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ typename buffer_context<Char>::iterator vformat_to(
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
||||
return vformat_to<af>(std::back_inserter(buf), to_string_view(format_str),
|
||||
return vformat_to<af>(buffer_appender<Char>(buf), to_string_view(format_str),
|
||||
args, detail::locale_ref(loc));
|
||||
}
|
||||
|
||||
|
@ -53,10 +53,7 @@ template <typename Char> struct formatter<test_struct, Char> {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
typedef std::back_insert_iterator<buffer<Char>> iterator;
|
||||
|
||||
auto format(test_struct, basic_format_context<iterator, char>& ctx)
|
||||
-> decltype(ctx.out()) {
|
||||
auto format(test_struct, format_context& ctx) -> decltype(ctx.out()) {
|
||||
const Char* test = "test";
|
||||
return std::copy_n(test, std::strlen(test), ctx.out());
|
||||
}
|
||||
@ -377,9 +374,9 @@ struct check_custom {
|
||||
test_buffer() : fmt::detail::buffer<char>(data, 0, 10) {}
|
||||
void grow(size_t) {}
|
||||
} buffer;
|
||||
fmt::detail::buffer<char>& base = buffer;
|
||||
fmt::format_parse_context parse_ctx("");
|
||||
fmt::format_context ctx(std::back_inserter(base), fmt::format_args());
|
||||
fmt::format_context ctx{
|
||||
fmt::detail::buffer_appender<char>(buffer), fmt::format_args()};
|
||||
h.format(parse_ctx, ctx);
|
||||
EXPECT_EQ("test", std::string(buffer.data, buffer.size()));
|
||||
return test_result();
|
||||
@ -388,8 +385,8 @@ struct check_custom {
|
||||
|
||||
TEST(ArgTest, CustomArg) {
|
||||
test_struct test;
|
||||
typedef mock_visitor<fmt::basic_format_arg<fmt::format_context>::handle>
|
||||
visitor;
|
||||
using visitor =
|
||||
mock_visitor<fmt::basic_format_arg<fmt::format_context>::handle>;
|
||||
testing::StrictMock<visitor> v;
|
||||
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke(check_custom()));
|
||||
fmt::visit_format_arg(v, make_arg<fmt::format_context>(test));
|
||||
|
@ -39,10 +39,9 @@ class custom_arg_formatter
|
||||
|
||||
std::string custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::detail::buffer<char>& base = buffer;
|
||||
// Pass custom argument formatter as a template arg to vwrite.
|
||||
fmt::vformat_to<custom_arg_formatter>(std::back_inserter(base), format_str,
|
||||
args);
|
||||
fmt::vformat_to<custom_arg_formatter>(
|
||||
fmt::detail::buffer_appender<char>(buffer), format_str, args);
|
||||
return std::string(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,9 @@ namespace std {
|
||||
|
||||
template<class Out, class charT> class basic_format_context;
|
||||
using format_context = basic_format_context<
|
||||
/* unspecified */ std::back_insert_iterator<fmt::detail::buffer<char>>, char>;
|
||||
/* unspecified */ fmt::detail::buffer_appender<char>, char>;
|
||||
using wformat_context = basic_format_context<
|
||||
/* unspecified */ std::back_insert_iterator<fmt::detail::buffer<wchar_t>>, wchar_t>;
|
||||
/* unspecified */ fmt::detail::buffer_appender<wchar_t>, wchar_t>;
|
||||
|
||||
template<class T, class charT = char> struct formatter {
|
||||
formatter() = delete;
|
||||
@ -714,7 +714,7 @@ string vformat(string_view fmt, format_args args) {
|
||||
fmt::detail::buffer<char>& buf = mbuf;
|
||||
using af = detail::arg_formatter<fmt::format_context::iterator, char>;
|
||||
detail::format_handler<af, char, format_context>
|
||||
h(std::back_inserter(buf), fmt, args, {});
|
||||
h(fmt::detail::buffer_appender<char>(buf), fmt, args, {});
|
||||
fmt::detail::parse_format_string<false>(fmt::to_string_view(fmt), h);
|
||||
return to_string(mbuf);
|
||||
}
|
||||
|
@ -1844,10 +1844,9 @@ class mock_arg_formatter
|
||||
};
|
||||
|
||||
static void custom_vformat(fmt::string_view format_str, fmt::format_args args) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::detail::buffer<char>& base = buffer;
|
||||
fmt::vformat_to<mock_arg_formatter>(std::back_inserter(base), format_str,
|
||||
args);
|
||||
fmt::memory_buffer buf;
|
||||
fmt::vformat_to<mock_arg_formatter>(fmt::detail::buffer_appender<char>(buf),
|
||||
format_str, args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
|
@ -75,8 +75,8 @@ struct test_arg_formatter
|
||||
|
||||
TEST(OStreamTest, CustomArg) {
|
||||
fmt::memory_buffer buffer;
|
||||
fmt::detail::buffer<char>& base = buffer;
|
||||
fmt::format_context ctx(std::back_inserter(base), fmt::format_args());
|
||||
fmt::format_context ctx(
|
||||
fmt::detail::buffer_appender<char>{buffer}, fmt::format_args());
|
||||
fmt::format_specs spec;
|
||||
test_arg_formatter af(ctx, spec);
|
||||
fmt::visit_format_arg(
|
||||
|
Loading…
x
Reference in New Issue
Block a user