mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-28 00:35:21 +00:00
Merge back_insert_iterator and appender
This commit is contained in:
parent
f348d1a211
commit
48d7fb265b
@ -331,31 +331,6 @@ struct monostate {
|
|||||||
constexpr monostate() {}
|
constexpr monostate() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// An implementation of back_insert_iterator to avoid dependency on <iterator>.
|
|
||||||
template <typename Container> class back_insert_iterator {
|
|
||||||
private:
|
|
||||||
Container* container_;
|
|
||||||
|
|
||||||
friend auto get_container(back_insert_iterator it) -> Container& {
|
|
||||||
return *it.container_;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using difference_type = ptrdiff_t;
|
|
||||||
FMT_UNCHECKED_ITERATOR(back_insert_iterator);
|
|
||||||
|
|
||||||
explicit back_insert_iterator(Container& c) : container_(&c) {}
|
|
||||||
|
|
||||||
auto operator=(const typename Container::value_type& value)
|
|
||||||
-> back_insert_iterator& {
|
|
||||||
container_->push_back(value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
auto operator*() -> back_insert_iterator& { return *this; }
|
|
||||||
auto operator++() -> back_insert_iterator& { return *this; }
|
|
||||||
auto operator++(int) -> back_insert_iterator { return *this; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// An enable_if helper to be used in template parameters which results in much
|
// An enable_if helper to be used in template parameters which results in much
|
||||||
// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
|
// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
|
||||||
// to workaround a bug in MSVC 2019 (see #1140 and #1186).
|
// to workaround a bug in MSVC 2019 (see #1140 and #1186).
|
||||||
@ -1141,30 +1116,32 @@ using has_formatter =
|
|||||||
std::is_constructible<typename Context::template formatter_type<T>>;
|
std::is_constructible<typename Context::template formatter_type<T>>;
|
||||||
|
|
||||||
// An output iterator that appends to a buffer. It is used instead of
|
// An output iterator that appends to a buffer. It is used instead of
|
||||||
// back_insert_iterator to reduce symbol sizes for the common case.
|
// back_insert_iterator to reduce symbol sizes and avoid <iterator> dependency.
|
||||||
class appender {
|
template <typename T> class basic_appender {
|
||||||
private:
|
private:
|
||||||
detail::buffer<char>* buffer_;
|
detail::buffer<T>* buffer_;
|
||||||
|
|
||||||
friend auto get_container(appender app) -> detail::buffer<char>& {
|
friend auto get_container(basic_appender app) -> detail::buffer<T>& {
|
||||||
return *app.buffer_;
|
return *app.buffer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
FMT_UNCHECKED_ITERATOR(appender);
|
FMT_UNCHECKED_ITERATOR(basic_appender);
|
||||||
|
|
||||||
appender(detail::buffer<char>& buf) : buffer_(&buf) {}
|
basic_appender(detail::buffer<T>& buf) : buffer_(&buf) {}
|
||||||
|
|
||||||
auto operator=(char c) -> appender& {
|
auto operator=(T c) -> basic_appender& {
|
||||||
buffer_->push_back(c);
|
buffer_->push_back(c);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
auto operator*() -> appender& { return *this; }
|
auto operator*() -> basic_appender& { return *this; }
|
||||||
auto operator++() -> appender& { return *this; }
|
auto operator++() -> basic_appender& { return *this; }
|
||||||
auto operator++(int) -> appender { return *this; }
|
auto operator++(int) -> basic_appender { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using appender = basic_appender<char>;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename Context, typename T>
|
template <typename Context, typename T>
|
||||||
@ -1183,18 +1160,14 @@ constexpr auto has_const_formatter() -> bool {
|
|||||||
return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));
|
return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> using buffer_appender = basic_appender<T>;
|
||||||
using buffer_appender = conditional_t<std::is_same<T, char>::value, appender,
|
|
||||||
back_insert_iterator<buffer<T>>>;
|
|
||||||
|
|
||||||
// Maps an output iterator to a buffer.
|
// Maps an output iterator to a buffer.
|
||||||
template <typename T, typename OutputIt>
|
template <typename T, typename OutputIt>
|
||||||
auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
|
auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
|
||||||
return iterator_buffer<OutputIt, T>(out);
|
return iterator_buffer<OutputIt, T>(out);
|
||||||
}
|
}
|
||||||
template <typename T, typename Buf,
|
template <typename T> auto get_buffer(basic_appender<T> out) -> buffer<T>& {
|
||||||
FMT_ENABLE_IF(std::is_base_of<buffer<char>, Buf>::value)>
|
|
||||||
auto get_buffer(back_insert_iterator<Buf> out) -> buffer<char>& {
|
|
||||||
return get_container(out);
|
return get_container(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1816,7 +1789,7 @@ template <typename OutputIt, typename Char> class basic_format_context {
|
|||||||
template <typename Char>
|
template <typename Char>
|
||||||
using buffer_context =
|
using buffer_context =
|
||||||
basic_format_context<detail::buffer_appender<Char>, Char>;
|
basic_format_context<detail::buffer_appender<Char>, Char>;
|
||||||
using format_context = buffer_context<char>;
|
using format_context = basic_format_context<appender, char>;
|
||||||
|
|
||||||
template <typename T, typename Char = char>
|
template <typename T, typename Char = char>
|
||||||
using is_formattable = bool_constant<!std::is_base_of<
|
using is_formattable = bool_constant<!std::is_base_of<
|
||||||
@ -2736,8 +2709,8 @@ void check_format_string(S format_str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Char = char> struct vformat_args {
|
template <typename Char = char> struct vformat_args {
|
||||||
using type = basic_format_args<
|
using type =
|
||||||
basic_format_context<back_insert_iterator<buffer<Char>>, Char>>;
|
basic_format_args<basic_format_context<basic_appender<Char>, Char>>;
|
||||||
};
|
};
|
||||||
template <> struct vformat_args<char> {
|
template <> struct vformat_args<char> {
|
||||||
using type = format_args;
|
using type = format_args;
|
||||||
|
@ -271,12 +271,7 @@ FMT_END_NAMESPACE
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <> struct iterator_traits<fmt::appender> {
|
template <typename T> struct iterator_traits<fmt::basic_appender<T>> {
|
||||||
using value_type = void;
|
|
||||||
using iterator_category = std::output_iterator_tag;
|
|
||||||
};
|
|
||||||
template <typename Container>
|
|
||||||
struct iterator_traits<fmt::back_insert_iterator<Container>> {
|
|
||||||
using value_type = void;
|
using value_type = void;
|
||||||
using iterator_category = std::output_iterator_tag;
|
using iterator_category = std::output_iterator_tag;
|
||||||
};
|
};
|
||||||
@ -556,8 +551,9 @@ auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
template <typename Char, typename InputIt>
|
template <typename Char, typename InputIt>
|
||||||
auto copy_str(InputIt begin, InputIt end, back_insert_iterator<std::string> out)
|
auto copy_str(InputIt begin, InputIt end,
|
||||||
-> back_insert_iterator<std::string> {
|
std::back_insert_iterator<std::string> out)
|
||||||
|
-> std::back_insert_iterator<std::string> {
|
||||||
get_container(out).append(begin, end);
|
get_container(out).append(begin, end);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,9 @@ struct format_string_char<S, enable_if_t<is_compile_string<S>::value>> {
|
|||||||
template <typename S>
|
template <typename S>
|
||||||
using format_string_char_t = typename format_string_char<S>::type;
|
using format_string_char_t = typename format_string_char<S>::type;
|
||||||
|
|
||||||
inline auto write_loc(back_insert_iterator<detail::buffer<wchar_t>> out,
|
inline auto write_loc(basic_appender<wchar_t> out, loc_value value,
|
||||||
loc_value value, const format_specs<wchar_t>& specs,
|
const format_specs<wchar_t>& specs, locale_ref loc)
|
||||||
locale_ref loc) -> bool {
|
-> bool {
|
||||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||||
auto& numpunct =
|
auto& numpunct =
|
||||||
std::use_facet<std::numpunct<wchar_t>>(loc.get<std::locale>());
|
std::use_facet<std::numpunct<wchar_t>>(loc.get<std::locale>());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user