[libc++][format] Removes vector dependency.

During the review of D140653 it was suggested to use vector in
__retarget_buffer instead of manually managing the memory. Due to the
requirements of the Standard it turns out format needs to include vector
leading to a cycle. Therefore switching back to manual memory
management.

This is a preparation to fix https://llvm.org/PR61314

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D148826
This commit is contained in:
Mark de Wever 2023-04-20 20:39:00 +02:00
parent 8d3ff24e11
commit 03c7b93aab
7 changed files with 81 additions and 24 deletions

View File

@ -28,12 +28,17 @@
#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/exception_guard.h>
#include <__utility/move.h>
#include <cstddef>
#include <string_view>
#include <vector>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@ -512,8 +517,13 @@ public:
// 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<bool>.
template <__fmt_char_type _CharT>
class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
using _Alloc = allocator<_CharT>;
public:
using value_type = _CharT;
@ -537,31 +547,89 @@ public:
__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) {
auto __result = std::__allocate_at_least(__alloc_, __size_hint ? __size_hint : 256 / sizeof(_CharT));
__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);
++__size_;
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<size_t>(__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");
auto __result = std::__allocate_at_least(__alloc_, __capacity);
auto __guard = std::__make_exception_guard([&] {
allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count);
});
// This shouldn't throw, but just to be safe. Not that at -O1 this
// guard is optimized away so there is no runtime overhead.
std::uninitialized_move_n(__ptr_, __size_, __result.ptr);
__guard.__complete();
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

View File

@ -333,7 +333,6 @@ format stdexcept
format string
format string_view
format tuple
format vector
format version
forward_list algorithm
forward_list atomic
@ -869,7 +868,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
thread vector
thread version
tuple compare
tuple cstddef

1 algorithm atomic
333 format string
334 format string_view
335 format tuple
format vector
336 format version
337 forward_list algorithm
338 forward_list atomic
868 thread system_error
869 thread tuple
870 thread type_traits
thread vector
871 thread version
872 tuple compare
873 tuple cstddef

View File

@ -333,7 +333,6 @@ format stdexcept
format string
format string_view
format tuple
format vector
format version
forward_list algorithm
forward_list atomic
@ -870,7 +869,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
thread vector
thread version
tuple compare
tuple cstddef

1 algorithm atomic
333 format string
334 format string_view
335 format tuple
format vector
336 format version
337 forward_list algorithm
338 forward_list atomic
869 thread system_error
870 thread tuple
871 thread type_traits
thread vector
872 thread version
873 tuple compare
874 tuple cstddef

View File

@ -335,7 +335,6 @@ format stdexcept
format string
format string_view
format tuple
format vector
format version
forward_list algorithm
forward_list atomic
@ -872,7 +871,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
thread vector
thread version
tuple compare
tuple cstddef

1 algorithm atomic
335 format string
336 format string_view
337 format tuple
format vector
338 format version
339 forward_list algorithm
340 forward_list atomic
871 thread system_error
872 thread tuple
873 thread type_traits
thread vector
874 thread version
875 tuple compare
876 tuple cstddef

View File

@ -335,7 +335,6 @@ format stdexcept
format string
format string_view
format tuple
format vector
format version
forward_list algorithm
forward_list atomic
@ -872,7 +871,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
thread vector
thread version
tuple compare
tuple cstddef

1 algorithm atomic
335 format string
336 format string_view
337 format tuple
format vector
338 format version
339 forward_list algorithm
340 forward_list atomic
871 thread system_error
872 thread tuple
873 thread type_traits
thread vector
874 thread version
875 tuple compare
876 tuple cstddef

View File

@ -127,7 +127,6 @@ chrono string
chrono string_view
chrono tuple
chrono type_traits
chrono vector
chrono version
cinttypes cstdint
cmath type_traits
@ -343,7 +342,6 @@ format stdexcept
format string
format string_view
format tuple
format vector
format version
forward_list algorithm
forward_list atomic
@ -878,7 +876,6 @@ thread string_view
thread system_error
thread tuple
thread type_traits
thread vector
thread version
tuple compare
tuple cstddef

1 algorithm atomic
127 chrono string_view
128 chrono tuple
129 chrono type_traits
chrono vector
130 chrono version
131 cinttypes cstdint
132 cmath type_traits
342 format string
343 format string_view
344 format tuple
format vector
345 format version
346 forward_list algorithm
347 forward_list atomic
876 thread system_error
877 thread tuple
878 thread type_traits
thread vector
879 thread version
880 tuple compare
881 tuple cstddef

View File

@ -71,6 +71,7 @@ chrono ctime
chrono initializer_list
chrono limits
chrono locale
chrono new
chrono optional
chrono ostream
chrono ratio
@ -79,7 +80,6 @@ chrono stdexcept
chrono string
chrono string_view
chrono tuple
chrono vector
chrono version
cinttypes cstdint
cmath version
@ -225,6 +225,7 @@ format cstdlib
format initializer_list
format limits
format locale
format new
format optional
format queue
format stack
@ -232,7 +233,6 @@ format stdexcept
format string
format string_view
format tuple
format vector
format version
forward_list compare
forward_list cstddef
@ -582,12 +582,12 @@ thread ctime
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

1 algorithm climits
71 chrono initializer_list
72 chrono limits
73 chrono locale
74 chrono new
75 chrono optional
76 chrono ostream
77 chrono ratio
80 chrono string
81 chrono string_view
82 chrono tuple
chrono vector
83 chrono version
84 cinttypes cstdint
85 cmath version
225 format initializer_list
226 format limits
227 format locale
228 format new
229 format optional
230 format queue
231 format stack
233 format string
234 format string_view
235 format tuple
format vector
236 format version
237 forward_list compare
238 forward_list cstddef
582 thread iosfwd
583 thread limits
584 thread locale
585 thread new
586 thread ratio
587 thread stdexcept
588 thread string
589 thread string_view
590 thread tuple
thread vector
591 thread version
592 tuple compare
593 tuple cstddef