Make format_to_n part of the core API
This commit is contained in:
parent
98626093d2
commit
95d3abf95c
@ -48,6 +48,8 @@ participate in an overload resolution if the latter is not a string.
|
|||||||
.. doxygenfunction:: format(const S&, Args&&...)
|
.. doxygenfunction:: format(const S&, Args&&...)
|
||||||
.. doxygenfunction:: vformat(const S&, basic_format_args<buffer_context<type_identity_t<Char>>>)
|
.. doxygenfunction:: vformat(const S&, basic_format_args<buffer_context<type_identity_t<Char>>>)
|
||||||
|
|
||||||
|
.. doxygenfunction:: fmt::format_to(OutputIt, string_view, Args&&...)
|
||||||
|
.. doxygenfunction:: fmt::format_to_n(OutputIt, size_t, string_view, Args&&...)
|
||||||
.. doxygenfunction:: fmt::formatted_size(string_view, Args&&...)
|
.. doxygenfunction:: fmt::formatted_size(string_view, Args&&...)
|
||||||
|
|
||||||
.. _print:
|
.. _print:
|
||||||
|
@ -735,13 +735,33 @@ template <typename T> class buffer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A buffer that writes to an output iterator when flushed.
|
struct buffer_traits {
|
||||||
template <typename OutputIt, typename T>
|
explicit buffer_traits(size_t) {}
|
||||||
class iterator_buffer : public buffer<T> {
|
size_t count() const { return 0; }
|
||||||
private:
|
size_t limit(size_t size) { return size; }
|
||||||
enum { buffer_size = 256 };
|
};
|
||||||
|
|
||||||
|
class fixed_buffer_traits {
|
||||||
|
private:
|
||||||
|
size_t count_ = 0;
|
||||||
|
size_t limit_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
|
||||||
|
size_t count() const { return count_; }
|
||||||
|
size_t limit(size_t size) {
|
||||||
|
size_t n = limit_ - count_;
|
||||||
|
count_ += size;
|
||||||
|
return size < n ? size : n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A buffer that writes to an output iterator when flushed.
|
||||||
|
template <typename OutputIt, typename T, typename Traits = buffer_traits>
|
||||||
|
class iterator_buffer : public Traits, public buffer<T> {
|
||||||
|
private:
|
||||||
OutputIt out_;
|
OutputIt out_;
|
||||||
|
enum { buffer_size = 256 };
|
||||||
T data_[buffer_size];
|
T data_[buffer_size];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -751,14 +771,17 @@ class iterator_buffer : public buffer<T> {
|
|||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit iterator_buffer(OutputIt out)
|
explicit iterator_buffer(OutputIt out, size_t n = 0)
|
||||||
: buffer<T>(data_, 0, buffer_size), out_(out) {}
|
: Traits(n),
|
||||||
|
buffer<T>(data_, 0, n < size_t(buffer_size) ? n : size_t(buffer_size)),
|
||||||
|
out_(out) {}
|
||||||
~iterator_buffer() { flush(); }
|
~iterator_buffer() { flush(); }
|
||||||
|
|
||||||
OutputIt out() {
|
OutputIt out() {
|
||||||
flush();
|
flush();
|
||||||
return out_;
|
return out_;
|
||||||
}
|
}
|
||||||
|
size_t count() const { return Traits::count() + this->size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class iterator_buffer<T*, T> : public buffer<T> {
|
template <typename T> class iterator_buffer<T*, T> : public buffer<T> {
|
||||||
@ -766,7 +789,7 @@ template <typename T> class iterator_buffer<T*, T> : public buffer<T> {
|
|||||||
void grow(size_t) final {}
|
void grow(size_t) final {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit iterator_buffer(T* out) : buffer<T>(out, 0, ~size_t()) {}
|
explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {}
|
||||||
|
|
||||||
T* out() { return &*this->end(); }
|
T* out() { return &*this->end(); }
|
||||||
};
|
};
|
||||||
@ -781,7 +804,7 @@ class iterator_buffer<std::back_insert_iterator<Container>,
|
|||||||
Container& container_;
|
Container& container_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void grow(size_t capacity) FMT_OVERRIDE {
|
void grow(size_t capacity) final {
|
||||||
container_.resize(capacity);
|
container_.resize(capacity);
|
||||||
this->set(&container_[0], capacity);
|
this->set(&container_[0], capacity);
|
||||||
}
|
}
|
||||||
@ -789,7 +812,7 @@ class iterator_buffer<std::back_insert_iterator<Container>,
|
|||||||
public:
|
public:
|
||||||
explicit iterator_buffer(Container& c)
|
explicit iterator_buffer(Container& c)
|
||||||
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
||||||
explicit iterator_buffer(std::back_insert_iterator<Container> out)
|
explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
|
||||||
: iterator_buffer(get_container(out)) {}
|
: iterator_buffer(get_container(out)) {}
|
||||||
std::back_insert_iterator<Container> out() {
|
std::back_insert_iterator<Container> out() {
|
||||||
return std::back_inserter(container_);
|
return std::back_inserter(container_);
|
||||||
@ -1972,6 +1995,41 @@ inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
|
|||||||
return vformat_to(out, to_string_view(format_str), vargs);
|
return vformat_to(out, to_string_view(format_str), vargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename OutputIt> struct format_to_n_result {
|
||||||
|
/** Iterator past the end of the output range. */
|
||||||
|
OutputIt out;
|
||||||
|
/** Total (not truncated) output size. */
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename OutputIt, typename Char, typename... Args,
|
||||||
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
|
||||||
|
inline format_to_n_result<OutputIt> vformat_to_n(
|
||||||
|
OutputIt out, size_t n, basic_string_view<Char> format_str,
|
||||||
|
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||||
|
detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,
|
||||||
|
n);
|
||||||
|
detail::vformat_to(buf, format_str, args);
|
||||||
|
return {buf.out(), buf.count()};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Formats arguments, writes up to ``n`` characters of the result to the output
|
||||||
|
iterator ``out`` and returns the total output size and the iterator past the
|
||||||
|
end of the output range.
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename OutputIt, typename S, typename... Args,
|
||||||
|
FMT_ENABLE_IF(detail::is_string<S>::value&&
|
||||||
|
detail::is_output_iterator<OutputIt>::value)>
|
||||||
|
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||||
|
const S& format_str,
|
||||||
|
const Args&... args) {
|
||||||
|
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||||
|
return vformat_to_n(out, n, to_string_view(format_str), vargs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the number of characters in the output of
|
Returns the number of characters in the output of
|
||||||
``format(format_str, args...)``.
|
``format(format_str, args...)``.
|
||||||
|
@ -566,9 +566,9 @@ void buffer<T>::append(const U* begin, const U* end) {
|
|||||||
} while (begin != end);
|
} while (begin != end);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename T>
|
template <typename OutputIt, typename T, typename Traits>
|
||||||
void iterator_buffer<OutputIt, T>::flush() {
|
void iterator_buffer<OutputIt, T, Traits>::flush() {
|
||||||
out_ = std::copy(data_, data_ + this->size(), out_);
|
out_ = std::copy_n(data_, this->limit(this->size()), out_);
|
||||||
this->clear();
|
this->clear();
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -3530,13 +3530,6 @@ using format_context_t = basic_format_context<OutputIt, Char>;
|
|||||||
template <typename OutputIt, typename Char = char>
|
template <typename OutputIt, typename Char = char>
|
||||||
using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;
|
using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;
|
||||||
|
|
||||||
template <typename OutputIt> struct format_to_n_result {
|
|
||||||
/** Iterator past the end of the output range. */
|
|
||||||
OutputIt out;
|
|
||||||
/** Total (not truncated) output size. */
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Char = typename OutputIt::value_type>
|
template <typename OutputIt, typename Char = typename OutputIt::value_type>
|
||||||
using format_to_n_context FMT_DEPRECATED_ALIAS = buffer_context<Char>;
|
using format_to_n_context FMT_DEPRECATED_ALIAS = buffer_context<Char>;
|
||||||
|
|
||||||
@ -3550,33 +3543,6 @@ make_format_to_n_args(const Args&... args) {
|
|||||||
return format_arg_store<buffer_context<Char>, Args...>(args...);
|
return format_arg_store<buffer_context<Char>, Args...>(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename Char, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value)>
|
|
||||||
inline format_to_n_result<OutputIt> vformat_to_n(
|
|
||||||
OutputIt out, size_t n, basic_string_view<Char> format_str,
|
|
||||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
|
||||||
auto it = vformat_to(detail::truncating_iterator<OutputIt>(out, n),
|
|
||||||
format_str, args);
|
|
||||||
return {it.base(), it.count()};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Formats arguments, writes up to ``n`` characters of the result to the output
|
|
||||||
iterator ``out`` and returns the total output size and the iterator past the
|
|
||||||
end of the output range.
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename OutputIt, typename S, typename... Args,
|
|
||||||
FMT_ENABLE_IF(detail::is_string<S>::value&&
|
|
||||||
detail::is_output_iterator<OutputIt>::value)>
|
|
||||||
inline format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
|
||||||
const S& format_str,
|
|
||||||
const Args&... args) {
|
|
||||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
|
||||||
return vformat_to_n(out, n, to_string_view(format_str), vargs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
|
template <typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
|
||||||
std::basic_string<Char> detail::vformat(
|
std::basic_string<Char> detail::vformat(
|
||||||
basic_string_view<Char> format_str,
|
basic_string_view<Char> format_str,
|
||||||
|
Loading…
Reference in New Issue
Block a user