|
@@ -11,12 +11,16 @@
|
|
|
#define _LIBCPP___FORMAT_BUFFER_H
|
|
|
|
|
|
#include <__algorithm/copy_n.h>
|
|
|
+#include <__algorithm/max.h>
|
|
|
+#include <__algorithm/min.h>
|
|
|
#include <__algorithm/unwrap_iter.h>
|
|
|
#include <__config>
|
|
|
#include <__format/enable_insertable.h>
|
|
|
+#include <__format/format_to_n_result.h>
|
|
|
#include <__format/formatter.h> // for __char_type TODO FMT Move the concept?
|
|
|
#include <__iterator/back_insert_iterator.h>
|
|
|
#include <__iterator/concepts.h>
|
|
|
+#include <__iterator/incrementable_traits.h>
|
|
|
#include <__iterator/iterator_traits.h>
|
|
|
#include <__iterator/wrap_iter.h>
|
|
|
#include <__utility/move.h>
|
|
@@ -28,6 +32,9 @@
|
|
|
# pragma GCC system_header
|
|
|
#endif
|
|
|
|
|
|
+_LIBCPP_PUSH_MACROS
|
|
|
+#include <__undef_macros>
|
|
|
+
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
|
#if _LIBCPP_STD_VER > 17
|
|
@@ -267,10 +274,97 @@ private:
|
|
|
size_t __size_{0};
|
|
|
};
|
|
|
|
|
|
+/// The base of a buffer that counts and limits the number of insertions.
|
|
|
+template <class _OutIt, __formatter::__char_type _CharT, bool>
|
|
|
+ requires(output_iterator<_OutIt, const _CharT&>)
|
|
|
+struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base {
|
|
|
+ using _Size = iter_difference_t<_OutIt>;
|
|
|
+
|
|
|
+public:
|
|
|
+ _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __n)
|
|
|
+ : __writer_(_VSTD::move(__out_it)), __n_(_VSTD::max(_Size(0), __n)) {}
|
|
|
+
|
|
|
+ _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) {
|
|
|
+ if (_Size(__size_) <= __n_)
|
|
|
+ __writer_.flush(__ptr, _VSTD::min(_Size(__size), __n_ - __size_));
|
|
|
+ __size_ += __size;
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ __internal_storage<_CharT> __storage_;
|
|
|
+ __output_buffer<_CharT> __output_{__storage_.begin(), __storage_.capacity(), this};
|
|
|
+ typename __writer_selector<_OutIt, _CharT>::type __writer_;
|
|
|
+
|
|
|
+ _Size __n_;
|
|
|
+ _Size __size_{0};
|
|
|
+};
|
|
|
+
|
|
|
+/// The base of a buffer that counts and limits the number of insertions.
|
|
|
+///
|
|
|
+/// This version is used when \c __enable_direct_output<_OutIt, _CharT> == true.
|
|
|
+///
|
|
|
+/// This class limits the size available the the direct writer so it will not
|
|
|
+/// exceed the maximum number of code units.
|
|
|
+template <class _OutIt, __formatter::__char_type _CharT>
|
|
|
+ requires(output_iterator<_OutIt, const _CharT&>)
|
|
|
+class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> {
|
|
|
+ using _Size = iter_difference_t<_OutIt>;
|
|
|
+
|
|
|
+public:
|
|
|
+ _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __n)
|
|
|
+ : __output_(_VSTD::__unwrap_iter(__out_it), __n, this), __writer_(_VSTD::move(__out_it)) {
|
|
|
+ if (__n <= 0) [[unlikely]]
|
|
|
+ __output_.reset(__storage_.begin(), __storage_.capacity());
|
|
|
+ }
|
|
|
+
|
|
|
+ _LIBCPP_HIDE_FROM_ABI void flush(_CharT* __ptr, size_t __size) {
|
|
|
+ // A flush to the direct writer happens in two occasions:
|
|
|
+ // - The format function has written the maximum number of allowed code
|
|
|
+ // units. At this point it's no longer valid to write to this writer. So
|
|
|
+ // switch to the internal storage. This internal storage doesn't need to
|
|
|
+ // be written anywhere so the flush for that storage writes no output.
|
|
|
+ // - The format_to_n function is finished. In this case there's no need to
|
|
|
+ // switch the buffer, but for simplicity the buffers are still switched.
|
|
|
+ // When the __n <= 0 the constructor already switched the buffers.
|
|
|
+ if (__size_ == 0 && __ptr != __storage_.begin()) {
|
|
|
+ __writer_.flush(__ptr, __size);
|
|
|
+ __output_.reset(__storage_.begin(), __storage_.capacity());
|
|
|
+ }
|
|
|
+
|
|
|
+ __size_ += __size;
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ __internal_storage<_CharT> __storage_;
|
|
|
+ __output_buffer<_CharT> __output_;
|
|
|
+ __writer_direct<_OutIt, _CharT> __writer_;
|
|
|
+
|
|
|
+ _Size __size_{0};
|
|
|
+};
|
|
|
+
|
|
|
+/// The buffer that counts and limits the number of insertions.
|
|
|
+template <class _OutIt, __formatter::__char_type _CharT>
|
|
|
+ requires(output_iterator<_OutIt, const _CharT&>)
|
|
|
+struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final
|
|
|
+ : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> {
|
|
|
+ using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>;
|
|
|
+ using _Size = iter_difference_t<_OutIt>;
|
|
|
+
|
|
|
+public:
|
|
|
+ _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __n) : _Base(_VSTD::move(__out_it), __n) {}
|
|
|
+ _LIBCPP_HIDE_FROM_ABI auto make_output_iterator() { return this->__output_.make_output_iterator(); }
|
|
|
+
|
|
|
+ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> result() && {
|
|
|
+ this->__output_.flush();
|
|
|
+ return {_VSTD::move(this->__writer_).out(), this->__size_};
|
|
|
+ }
|
|
|
+};
|
|
|
} // namespace __format
|
|
|
|
|
|
#endif //_LIBCPP_STD_VER > 17
|
|
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
|
+_LIBCPP_POP_MACROS
|
|
|
+
|
|
|
#endif // _LIBCPP___FORMAT_BUFFER_H
|