diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -28,12 +28,16 @@ #include <__iterator/iterator_traits.h> #include <__iterator/wrap_iter.h> #include <__memory/addressof.h> +#include <__memory/allocate_at_least.h> +#include <__memory/allocator_traits.h> +#include <__memory/construct_at.h> +#include <__memory/ranges_construct_at.h> +#include <__memory/uninitialized_algorithms.h> #include <__type_traits/add_pointer.h> #include <__type_traits/conditional.h> #include <__utility/move.h> #include #include -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -512,8 +516,13 @@ // context and the format arguments need to be retargeted to the new context. // This retargeting is done by a basic_format_context specialized for the // __iterator of this container. +// +// This class uses its own buffer management, since using vector +// would lead to a circular include with formatter for vector. template <__fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __retarget_buffer { + using _Alloc = allocator<_CharT>; + public: using value_type = _CharT; @@ -537,31 +546,90 @@ __retarget_buffer* __buffer_; }; - _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { __buffer_.reserve(__size_hint); } + __retarget_buffer(const __retarget_buffer&) = delete; + __retarget_buffer& operator=(const __retarget_buffer&) = delete; + + _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { +# if _LIBCPP_STD_VER >= 23 + allocation_result __result = std::allocate_at_least(__alloc_, __size_hint ? __size_hint : 256 / sizeof(_CharT)); +# else + __allocation_result __result = std::__allocate_at_least(__alloc_, __size_hint ? __size_hint : 256 / sizeof(_CharT)); +# endif + __ptr_ = __result.ptr; + __capacity_ = __result.count; + } + + _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() { + ranges::destroy_n(__ptr_, __size_); + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); + } _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; } - _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { __buffer_.push_back(__c); } + _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { + std::construct_at(__ptr_ + __size_++, __c); + + if (__size_ == __capacity_) + __grow_buffer(); + } template <__fmt_char_type _InCharT> _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { - __buffer_.insert(__buffer_.end(), __str.begin(), __str.end()); + size_t __n = __str.size(); + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_); + __size_ += __n; } template <__fmt_char_type _InCharT, class _UnaryOperation> _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { _LIBCPP_ASSERT(__first <= __last, "not a valid range"); - std::transform(__first, __last, std::back_inserter(__buffer_), std::move(__operation)); + + size_t __n = static_cast(__last - __first); + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_default_construct_n(__ptr_ + __size_, __n); + std::transform(__first, __last, __ptr_ + __size_, std::move(__operation)); + __size_ += __n; } - _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __buffer_.insert(__buffer_.end(), __n, __value); } + _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); - _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__buffer_.data(), __buffer_.size()}; } + std::uninitialized_fill_n(__ptr_ + __size_, __n, __value); + __size_ += __n; + } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; } private: - // Use vector instead of string to avoid adding zeros after every append - // operation. The buffer is exposed as a string_view and not as a c-string. - vector<_CharT> __buffer_; + _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); } + + _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { + _LIBCPP_ASSERT(__capacity > __capacity_, "the buffer must grow"); +# if _LIBCPP_STD_VER >= 23 + allocation_result __result = std::allocate_at_least(__alloc_, __capacity); +# else + __allocation_result __result = std::__allocate_at_least(__alloc_, __capacity); +# endif + std::uninitialized_move_n(__ptr_, __size_, __result.ptr); + ranges::destroy_n(__ptr_, __size_); + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); + + __ptr_ = __result.ptr; + __capacity_ = __result.count; + } + _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; + _CharT* __ptr_; + size_t __capacity_; + size_t __size_{0}; }; } // namespace __format diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -331,7 +331,6 @@ format string format string_view format tuple -format vector format version forward_list algorithm forward_list atomic @@ -395,7 +394,6 @@ functional vector functional version future atomic -future cerrno future chrono future cstddef future cstdint @@ -830,15 +828,12 @@ strstream version system_error cerrno system_error compare -system_error cstddef system_error cstdint system_error cstring system_error limits -system_error stdexcept system_error string system_error type_traits system_error version -thread array thread cerrno thread chrono thread compare @@ -849,16 +844,13 @@ thread functional thread iosfwd thread limits -thread locale thread new thread ratio thread stdexcept thread string -thread string_view thread system_error thread tuple thread type_traits -thread vector thread version tuple compare tuple cstddef @@ -953,7 +945,9 @@ variant utility variant version vector algorithm +vector array vector atomic +vector cerrno vector climits vector compare vector concepts @@ -964,8 +958,11 @@ vector initializer_list vector iosfwd vector limits +vector locale vector new vector stdexcept +vector string +vector string_view vector tuple vector type_traits vector typeinfo diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -331,7 +331,6 @@ format string format string_view format tuple -format vector format version forward_list algorithm forward_list atomic @@ -395,7 +394,6 @@ functional vector functional version future atomic -future cerrno future chrono future cstddef future cstdint @@ -831,15 +829,12 @@ strstream version system_error cerrno system_error compare -system_error cstddef system_error cstdint system_error cstring system_error limits -system_error stdexcept system_error string system_error type_traits system_error version -thread array thread cerrno thread chrono thread compare @@ -850,16 +845,13 @@ thread functional thread iosfwd thread limits -thread locale thread new thread ratio thread stdexcept thread string -thread string_view thread system_error thread tuple thread type_traits -thread vector thread version tuple compare tuple cstddef @@ -954,7 +946,9 @@ variant utility variant version vector algorithm +vector array vector atomic +vector cerrno vector climits vector compare vector concepts @@ -965,8 +959,11 @@ vector initializer_list vector iosfwd vector limits +vector locale vector new vector stdexcept +vector string +vector string_view vector tuple vector type_traits vector typeinfo diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -333,7 +333,6 @@ format string format string_view format tuple -format vector format version forward_list algorithm forward_list atomic @@ -397,7 +396,6 @@ functional vector functional version future atomic -future cerrno future chrono future cstddef future cstdint @@ -833,15 +831,12 @@ strstream version system_error cerrno system_error compare -system_error cstddef system_error cstdint system_error cstring system_error limits -system_error stdexcept system_error string system_error type_traits system_error version -thread array thread cerrno thread chrono thread compare @@ -852,16 +847,13 @@ thread functional thread iosfwd thread limits -thread locale thread new thread ratio thread stdexcept thread string -thread string_view thread system_error thread tuple thread type_traits -thread vector thread version tuple compare tuple cstddef @@ -956,7 +948,9 @@ variant utility variant version vector algorithm +vector array vector atomic +vector cerrno vector climits vector compare vector concepts @@ -967,8 +961,11 @@ vector initializer_list vector iosfwd vector limits +vector locale vector new vector stdexcept +vector string +vector string_view vector tuple vector type_traits vector typeinfo diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -333,7 +333,6 @@ format string format string_view format tuple -format vector format version forward_list algorithm forward_list atomic @@ -397,7 +396,6 @@ functional vector functional version future atomic -future cerrno future chrono future cstddef future cstdint @@ -833,15 +831,12 @@ strstream version system_error cerrno system_error compare -system_error cstddef system_error cstdint system_error cstring system_error limits -system_error stdexcept system_error string system_error type_traits system_error version -thread array thread cerrno thread chrono thread compare @@ -852,16 +847,13 @@ thread functional thread iosfwd thread limits -thread locale thread new thread ratio thread stdexcept thread string -thread string_view thread system_error thread tuple thread type_traits -thread vector thread version tuple compare tuple cstddef @@ -956,7 +948,9 @@ variant utility variant version vector algorithm +vector array vector atomic +vector cerrno vector climits vector compare vector concepts @@ -967,8 +961,11 @@ vector initializer_list vector iosfwd vector limits +vector locale vector new vector stdexcept +vector string +vector string_view vector tuple vector type_traits vector typeinfo diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -127,7 +127,6 @@ chrono string_view chrono tuple chrono type_traits -chrono vector chrono version cinttypes cstdint cmath type_traits @@ -340,7 +339,6 @@ format string format string_view format tuple -format vector format version forward_list algorithm forward_list atomic @@ -404,7 +402,6 @@ functional vector functional version future atomic -future cerrno future cstddef future cstdint future cstdlib @@ -839,35 +836,28 @@ strstream version system_error cerrno system_error compare -system_error cstddef system_error cstdint system_error cstring system_error limits -system_error stdexcept system_error string system_error type_traits system_error version -thread array thread cerrno thread compare thread cstddef thread cstdint -thread cstdlib thread cstring thread ctime thread functional thread iosfwd thread limits -thread locale thread new thread ratio thread stdexcept thread string -thread string_view thread system_error thread tuple thread type_traits -thread vector thread version tuple compare tuple cstddef @@ -962,7 +952,9 @@ variant utility variant version vector algorithm +vector array vector atomic +vector cerrno vector climits vector compare vector concepts @@ -973,8 +965,11 @@ vector initializer_list vector iosfwd vector limits +vector locale vector new vector stdexcept +vector string +vector string_view vector tuple vector type_traits vector typeinfo diff --git a/libcxx/test/libcxx/transitive_includes/cxx2b.csv b/libcxx/test/libcxx/transitive_includes/cxx2b.csv --- a/libcxx/test/libcxx/transitive_includes/cxx2b.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx2b.csv @@ -71,6 +71,7 @@ chrono initializer_list chrono limits chrono locale +chrono new chrono optional chrono ostream chrono ratio @@ -79,7 +80,6 @@ chrono string chrono string_view chrono tuple -chrono vector chrono version cinttypes cstdint cmath version @@ -222,6 +222,7 @@ format initializer_list format limits format locale +format new format optional format queue format stack @@ -229,7 +230,6 @@ format string format string_view format tuple -format vector format version forward_list compare forward_list cstddef @@ -571,12 +571,12 @@ thread iosfwd thread limits thread locale +thread new thread ratio thread stdexcept thread string thread string_view thread tuple -thread vector thread version tuple compare tuple cstddef @@ -635,15 +635,21 @@ variant new variant tuple variant version +vector array +vector cerrno vector climits vector compare vector cstddef vector cstdint +vector cstdlib vector cstring vector initializer_list vector iosfwd vector limits +vector locale vector new vector stdexcept +vector string +vector string_view vector tuple vector version