Reduce symbol sizes and simplify iterator use

This commit is contained in:
Victor Zverovich
2020-07-09 08:41:05 -07:00
parent c5adfc51c5
commit b998e0f30b
10 changed files with 53 additions and 44 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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));
}