mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-19 20:18:49 +00:00
More iterator support & fmt::count
This commit is contained in:
parent
e3b69efbe1
commit
64b349aee2
@ -929,6 +929,8 @@ class arg_store {
|
||||
arg_store(const Args &... args)
|
||||
: data_{internal::make_arg<IS_PACKED, Context>(args)...} {}
|
||||
|
||||
basic_format_args<Context> operator*() const { return *this; }
|
||||
|
||||
const value_type *data() const { return data_; }
|
||||
};
|
||||
|
||||
|
@ -619,6 +619,33 @@ constexpr const Char *pointer_from(null_terminating_iterator<Char> it) {
|
||||
return it.ptr_;
|
||||
}
|
||||
|
||||
// An output iterator that counts the number of objects written to it and
|
||||
// discards them.
|
||||
template <typename T>
|
||||
class counting_iterator {
|
||||
private:
|
||||
std::size_t& count_;
|
||||
mutable T blackhole_;
|
||||
|
||||
public:
|
||||
explicit counting_iterator(std::size_t &count): count_(count) {}
|
||||
counting_iterator(const counting_iterator &other): count_(other.count_) {}
|
||||
|
||||
counting_iterator& operator=(const counting_iterator &other) {
|
||||
count_ = other.count_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
counting_iterator& operator++() {
|
||||
++count_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
counting_iterator operator++(int) { return ++*this; }
|
||||
|
||||
T &operator*() const { return blackhole_; }
|
||||
};
|
||||
|
||||
// Returns true if value is negative, false otherwise.
|
||||
// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
|
||||
template <typename T>
|
||||
@ -3036,11 +3063,23 @@ inline void format_to(wmemory_buffer &buf, wstring_view format_str,
|
||||
vformat_to(buf, format_str, make_args<wcontext>(args...));
|
||||
}
|
||||
|
||||
template <typename Container, typename Context>
|
||||
typename std::enable_if<!is_contiguous<Container>::value>::type
|
||||
vformat_to(std::back_insert_iterator<Container> out,
|
||||
string_view format_str,
|
||||
basic_format_args<Context> args) {
|
||||
template <typename OutputIt, typename Char = char>
|
||||
using context_t = basic_context<output_range<OutputIt, Char>>;
|
||||
|
||||
template <typename OutputIt>
|
||||
using format_args_t = basic_format_args<context_t<OutputIt>>;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
inline void vformat_to(OutputIt out, string_view format_str,
|
||||
format_args_t<OutputIt> args) {
|
||||
using range = output_range<OutputIt, char>;
|
||||
do_vformat_to<arg_formatter<range>>(range(out), format_str, args);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
inline void format_to(OutputIt out, string_view format_str,
|
||||
const Args & ... args) {
|
||||
vformat_to(out, format_str, *make_args<context_t<OutputIt>>(args...));
|
||||
}
|
||||
|
||||
template <typename Container, typename... Args>
|
||||
@ -3050,15 +3089,6 @@ inline typename std::enable_if<is_contiguous<Container>::value>::type
|
||||
vformat_to(out, format_str, make_args(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
inline void format_to(OutputIt out, string_view format_str,
|
||||
const Args & ... args) {
|
||||
using range = output_range<OutputIt, char>;
|
||||
auto store = make_args<basic_context<range>>(args...);
|
||||
do_vformat_to<arg_formatter<range>>(
|
||||
range(out), format_str, basic_format_args<basic_context<range>>(store));
|
||||
}
|
||||
|
||||
inline std::string vformat(string_view format_str, format_args args) {
|
||||
memory_buffer buffer;
|
||||
vformat_to(buffer, format_str, args);
|
||||
@ -3081,6 +3111,15 @@ inline typename std::enable_if<
|
||||
(void)invalid_format;
|
||||
return vformat(format_str.value(), make_args(args...));
|
||||
}
|
||||
|
||||
// Counts the number of characters in the output of format(format_str, args...).
|
||||
template <typename... Args>
|
||||
inline std::size_t count(string_view format_str, const Args & ... args) {
|
||||
std::size_t size = 0;
|
||||
internal::counting_iterator<char> it(size);
|
||||
format_to(it, format_str, args...);
|
||||
return size;
|
||||
}
|
||||
} // namespace fmt
|
||||
|
||||
#if FMT_USE_USER_DEFINED_LITERALS
|
||||
|
@ -1910,7 +1910,7 @@ TEST(FormatTest, ToString) {
|
||||
EXPECT_EQ("42", fmt::to_string(42));
|
||||
}
|
||||
|
||||
TEST(WriterTest, OutputIterators) {
|
||||
TEST(FormatTest, OutputIterators) {
|
||||
std::list<char> out;
|
||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||
EXPECT_EQ("42", std::string(out.begin(), out.end()));
|
||||
@ -1918,3 +1918,7 @@ TEST(WriterTest, OutputIterators) {
|
||||
fmt::format_to(std::ostream_iterator<char>(s), "{}", 42);
|
||||
EXPECT_EQ("42", s.str());
|
||||
}
|
||||
|
||||
TEST(FormatTest, OutputSize) {
|
||||
EXPECT_EQ(2, fmt::count("{}", 42));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user