diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-04-05 01:46:13 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-05 01:46:13 -0400 |
| commit | 0cd31fc7ff157551cfbba5da35cd79f118d2a2e3 (patch) | |
| tree | a308488f5d85184c8ec402fb3f55f1cf2704443e /lib/libcxx/include/__format | |
| parent | 8acedfd5baabab705946ad097746f9183ef62420 (diff) | |
| parent | cefe65c1b8abe65a22d4b68410db1be264fdeda0 (diff) | |
| download | zig-0cd31fc7ff157551cfbba5da35cd79f118d2a2e3.tar.gz zig-0cd31fc7ff157551cfbba5da35cd79f118d2a2e3.zip | |
Merge pull request #22780 from ziglang/llvm20
LLVM 20
Diffstat (limited to 'lib/libcxx/include/__format')
32 files changed, 620 insertions, 490 deletions
diff --git a/lib/libcxx/include/__format/buffer.h b/lib/libcxx/include/__format/buffer.h index 8598f0a1c0..0c054bbc3a 100644 --- a/lib/libcxx/include/__format/buffer.h +++ b/lib/libcxx/include/__format/buffer.h @@ -14,6 +14,7 @@ #include <__algorithm/fill_n.h> #include <__algorithm/max.h> #include <__algorithm/min.h> +#include <__algorithm/ranges_copy.h> #include <__algorithm/ranges_copy_n.h> #include <__algorithm/transform.h> #include <__algorithm/unwrap_iter.h> @@ -29,6 +30,7 @@ #include <__iterator/wrap_iter.h> #include <__memory/addressof.h> #include <__memory/allocate_at_least.h> +#include <__memory/allocator.h> #include <__memory/allocator_traits.h> #include <__memory/construct_at.h> #include <__memory/ranges_construct_at.h> @@ -37,7 +39,7 @@ #include <__type_traits/conditional.h> #include <__utility/exception_guard.h> #include <__utility/move.h> -#include <cstddef> +#include <stdexcept> #include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -53,24 +55,147 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __format { +// A helper to limit the total size of code units written. +class _LIBCPP_HIDE_FROM_ABI __max_output_size { +public: + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __max_output_size(size_t __max_size) : __max_size_{__max_size} {} + + // This function adjusts the size of a (bulk) write operations. It ensures the + // number of code units written by a __output_buffer never exceeds + // __max_size_ code units. + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __write_request(size_t __code_units) { + size_t __result = + __code_units_written_ < __max_size_ ? std::min(__code_units, __max_size_ - __code_units_written_) : 0; + __code_units_written_ += __code_units; + return __result; + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __code_units_written() const noexcept { return __code_units_written_; } + +private: + size_t __max_size_; + // The code units that would have been written if there was no limit. + // format_to_n returns this value. + size_t __code_units_written_{0}; +}; + /// A "buffer" that handles writing to the proper iterator. /// /// This helper is used together with the @ref back_insert_iterator to offer /// type-erasure for the formatting functions. This reduces the number to /// template instantiations. +/// +/// The design is the following: +/// - There is an external object that connects the buffer to the output. +/// - This buffer object: +/// - inherits publicly from this class. +/// - has a static or dynamic buffer. +/// - has a static member function to make space in its buffer write +/// operations. This can be done by increasing the size of the internal +/// buffer or by writing the contents of the buffer to the output iterator. +/// +/// This member function is a constructor argument, so its name is not +/// fixed. The code uses the name __prepare_write. +/// - The number of output code units can be limited by a __max_output_size +/// object. This is used in format_to_n This object: +/// - Contains the maximum number of code units to be written. +/// - Contains the number of code units that are requested to be written. +/// This number is returned to the user of format_to_n. +/// - The write functions call the object's __request_write member function. +/// This function: +/// - Updates the number of code units that are requested to be written. +/// - Returns the number of code units that can be written without +/// exceeding the maximum number of code units to be written. +/// +/// Documentation for the buffer usage members: +/// - __ptr_ +/// The start of the buffer. +/// - __capacity_ +/// The number of code units that can be written. This means +/// [__ptr_, __ptr_ + __capacity_) is a valid range to write to. +/// - __size_ +/// The number of code units written in the buffer. The next code unit will +/// be written at __ptr_ + __size_. This __size_ may NOT contain the total +/// number of code units written by the __output_buffer. Whether or not it +/// does depends on the sub-class used. Typically the total number of code +/// units written is not interesting. It is interesting for format_to_n which +/// has its own way to track this number. +/// +/// Documentation for the modifying buffer operations: +/// The subclasses have a function with the following signature: +/// +/// static void __prepare_write( +/// __output_buffer<_CharT>& __buffer, size_t __code_units); +/// +/// This function is called when a write function writes more code units than +/// the buffer's available space. When an __max_output_size object is provided +/// the number of code units is the number of code units returned from +/// __max_output_size::__request_write function. +/// +/// - The __buffer contains *this. Since the class containing this function +/// inherits from __output_buffer it's safe to cast it to the subclass being +/// used. +/// - The __code_units is the number of code units the caller will write + 1. +/// - This value does not take the available space of the buffer into account. +/// - The push_back function is more efficient when writing before resizing, +/// this means the buffer should always have room for one code unit. Hence +/// the + 1 is the size. +/// - When the function returns there is room for at least one additional code +/// unit. There is no requirement there is room for __code_units code units: +/// - The class has some "bulk" operations. For example, __copy which copies +/// the contents of a basic_string_view to the output. If the sub-class has +/// a fixed size buffer the size of the basic_string_view may be larger +/// than the buffer. In that case it's impossible to honor the requested +/// size. +/// - When the buffer has room for at least one code unit the function may be +/// a no-op. +/// - When the function makes space for more code units it uses one for these +/// functions to signal the change: +/// - __buffer_flushed() +/// - This function is typically used for a fixed sized buffer. +/// - The current contents of [__ptr_, __ptr_ + __size_) have been +/// processed. +/// - __ptr_ remains unchanged. +/// - __capacity_ remains unchanged. +/// - __size_ will be set to 0. +/// - __buffer_moved(_CharT* __ptr, size_t __capacity) +/// - This function is typically used for a dynamic sized buffer. There the +/// location of the buffer changes due to reallocations. +/// - __ptr_ will be set to __ptr. (This value may be the old value of +/// __ptr_). +/// - __capacity_ will be set to __capacity. (This value may be the old +/// value of __capacity_). +/// - __size_ remains unchanged, +/// - The range [__ptr, __ptr + __size_) contains the original data of the +/// range [__ptr_, __ptr_ + __size_). +/// +/// The push_back function expects a valid buffer and a capacity of at least 1. +/// This means: +/// - The class is constructed with a valid buffer, +/// - __buffer_moved is called with a valid buffer is used before the first +/// write operation, +/// - no write function is ever called, or +/// - the class is constructed with a __max_output_size object with __max_size 0. +/// +/// The latter option allows formatted_size to use the output buffer without +/// ever writing anything to the buffer. template <__fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __output_buffer { public: - using value_type = _CharT; + using value_type _LIBCPP_NODEBUG = _CharT; + using __prepare_write_type _LIBCPP_NODEBUG = void (*)(__output_buffer<_CharT>&, size_t); - template <class _Tp> - _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, _Tp* __obj) - : __ptr_(__ptr), - __capacity_(__capacity), - __flush_([](_CharT* __p, size_t __n, void* __o) { static_cast<_Tp*>(__o)->__flush(__p, __n); }), - __obj_(__obj) {} + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __output_buffer(_CharT* __ptr, size_t __capacity, __prepare_write_type __function) + : __output_buffer{__ptr, __capacity, __function, nullptr} {} - _LIBCPP_HIDE_FROM_ABI void __reset(_CharT* __ptr, size_t __capacity) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __output_buffer( + _CharT* __ptr, size_t __capacity, __prepare_write_type __function, __max_output_size* __max_output_size) + : __ptr_(__ptr), __capacity_(__capacity), __prepare_write_(__function), __max_output_size_(__max_output_size) {} + + _LIBCPP_HIDE_FROM_ABI void __buffer_flushed() { __size_ = 0; } + + _LIBCPP_HIDE_FROM_ABI void __buffer_moved(_CharT* __ptr, size_t __capacity) { __ptr_ = __ptr; __capacity_ = __capacity; } @@ -79,12 +204,18 @@ public: // Used in std::back_insert_iterator. _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { + if (__max_output_size_ && __max_output_size_->__write_request(1) == 0) + return; + + _LIBCPP_ASSERT_INTERNAL( + __ptr_ && __size_ < __capacity_ && __available() >= 1, "attempted to write outside the buffer"); + __ptr_[__size_++] = __c; // Profiling showed flushing after adding is more efficient than flushing // when entering the function. if (__size_ == __capacity_) - __flush(); + __prepare_write(0); } /// Copies the input __str to the buffer. @@ -105,25 +236,20 @@ public: // upper case. For integral these strings are short. // TODO FMT Look at the improvements above. size_t __n = __str.size(); - - __flush_on_overflow(__n); - if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). - std::copy_n(__str.data(), __n, std::addressof(__ptr_[__size_])); - __size_ += __n; - return; + if (__max_output_size_) { + __n = __max_output_size_->__write_request(__n); + if (__n == 0) + return; } - // The output doesn't fit in the internal buffer. - // Copy the data in "__capacity_" sized chunks. - _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); const _InCharT* __first = __str.data(); do { - size_t __chunk = std::min(__n, __capacity_); + __prepare_write(__n); + size_t __chunk = std::min(__n, __available()); std::copy_n(__first, __chunk, std::addressof(__ptr_[__size_])); - __size_ = __chunk; + __size_ += __chunk; __first += __chunk; __n -= __chunk; - __flush(); } while (__n); } @@ -137,121 +263,59 @@ public: _LIBCPP_ASSERT_INTERNAL(__first <= __last, "not a valid range"); size_t __n = static_cast<size_t>(__last - __first); - __flush_on_overflow(__n); - if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). - std::transform(__first, __last, std::addressof(__ptr_[__size_]), std::move(__operation)); - __size_ += __n; - return; + if (__max_output_size_) { + __n = __max_output_size_->__write_request(__n); + if (__n == 0) + return; } - // The output doesn't fit in the internal buffer. - // Transform the data in "__capacity_" sized chunks. - _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); do { - size_t __chunk = std::min(__n, __capacity_); + __prepare_write(__n); + size_t __chunk = std::min(__n, __available()); std::transform(__first, __first + __chunk, std::addressof(__ptr_[__size_]), __operation); - __size_ = __chunk; + __size_ += __chunk; __first += __chunk; __n -= __chunk; - __flush(); } while (__n); } /// A \c fill_n wrapper. _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { - __flush_on_overflow(__n); - if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). - std::fill_n(std::addressof(__ptr_[__size_]), __n, __value); - __size_ += __n; - return; + if (__max_output_size_) { + __n = __max_output_size_->__write_request(__n); + if (__n == 0) + return; } - // The output doesn't fit in the internal buffer. - // Fill the buffer in "__capacity_" sized chunks. - _LIBCPP_ASSERT_INTERNAL(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); do { - size_t __chunk = std::min(__n, __capacity_); + __prepare_write(__n); + size_t __chunk = std::min(__n, __available()); std::fill_n(std::addressof(__ptr_[__size_]), __chunk, __value); - __size_ = __chunk; + __size_ += __chunk; __n -= __chunk; - __flush(); } while (__n); } - _LIBCPP_HIDE_FROM_ABI void __flush() { - __flush_(__ptr_, __size_, __obj_); - __size_ = 0; - } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __capacity() const { return __capacity_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __size() const { return __size_; } private: _CharT* __ptr_; size_t __capacity_; size_t __size_{0}; - void (*__flush_)(_CharT*, size_t, void*); - void* __obj_; + void (*__prepare_write_)(__output_buffer<_CharT>&, size_t); + __max_output_size* __max_output_size_; - /// Flushes the buffer when the output operation would overflow the buffer. - /// - /// A simple approach for the overflow detection would be something along the - /// lines: - /// \code - /// // The internal buffer is large enough. - /// if (__n <= __capacity_) { - /// // Flush when we really would overflow. - /// if (__size_ + __n >= __capacity_) - /// __flush(); - /// ... - /// } - /// \endcode - /// - /// This approach works for all cases but one: - /// A __format_to_n_buffer_base where \ref __enable_direct_output is true. - /// In that case the \ref __capacity_ of the buffer changes during the first - /// \ref __flush. During that operation the output buffer switches from its - /// __writer_ to its __storage_. The \ref __capacity_ of the former depends - /// on the value of n, of the latter is a fixed size. For example: - /// - a format_to_n call with a 10'000 char buffer, - /// - the buffer is filled with 9'500 chars, - /// - adding 1'000 elements would overflow the buffer so the buffer gets - /// changed and the \ref __capacity_ decreases from 10'000 to - /// __buffer_size (256 at the time of writing). - /// - /// This means that the \ref __flush for this class may need to copy a part of - /// the internal buffer to the proper output. In this example there will be - /// 500 characters that need this copy operation. - /// - /// Note it would be more efficient to write 500 chars directly and then swap - /// the buffers. This would make the code more complex and \ref format_to_n is - /// not the most common use case. Therefore the optimization isn't done. - _LIBCPP_HIDE_FROM_ABI void __flush_on_overflow(size_t __n) { - if (__size_ + __n >= __capacity_) - __flush(); - } -}; - -/// A storage using an internal buffer. -/// -/// This storage is used when writing a single element to the output iterator -/// is expensive. -template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __internal_storage { -public: - _LIBCPP_HIDE_FROM_ABI _CharT* __begin() { return __buffer_; } - - static constexpr size_t __buffer_size = 256 / sizeof(_CharT); + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __available() const { return __capacity_ - __size_; } -private: - _CharT __buffer_[__buffer_size]; + _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __code_units) { + // Always have space for one additional code unit. This is a precondition of the push_back function. + __code_units += 1; + if (__available() < __code_units) + __prepare_write_(*this, __code_units + 1); + } }; -/// A storage writing directly to the storage. -/// -/// This requires the storage to be a contiguous buffer of \a _CharT. -/// Since the output is directly written to the underlying storage this class -/// is just an empty class. -template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __direct_storage {}; - template <class _OutIt, class _CharT> concept __enable_direct_output = __fmt_char_type<_CharT> && @@ -260,40 +324,6 @@ concept __enable_direct_output = // `#ifdef`. || same_as<_OutIt, __wrap_iter<_CharT*>>); -/// Write policy for directly writing to the underlying output. -template <class _OutIt, __fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __writer_direct { -public: - _LIBCPP_HIDE_FROM_ABI explicit __writer_direct(_OutIt __out_it) : __out_it_(__out_it) {} - - _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() { return __out_it_; } - - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT*, size_t __n) { - // _OutIt can be a __wrap_iter<CharT*>. Therefore the original iterator - // is adjusted. - __out_it_ += __n; - } - -private: - _OutIt __out_it_; -}; - -/// Write policy for copying the buffer to the output. -template <class _OutIt, __fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __writer_iterator { -public: - _LIBCPP_HIDE_FROM_ABI explicit __writer_iterator(_OutIt __out_it) : __out_it_{std::move(__out_it)} {} - - _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return std::move(__out_it_); } - - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { - __out_it_ = std::ranges::copy_n(__ptr, __n, std::move(__out_it_)).out; - } - -private: - _OutIt __out_it_; -}; - /// Concept to see whether a \a _Container is insertable. /// /// The concept is used to validate whether multiple calls to a @@ -311,196 +341,220 @@ concept __insertable = /// Extract the container type of a \ref back_insert_iterator. template <class _It> struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container { - using type = void; + using type _LIBCPP_NODEBUG = void; }; template <__insertable _Container> struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container<back_insert_iterator<_Container>> { - using type = _Container; + using type _LIBCPP_NODEBUG = _Container; }; -/// Write policy for inserting the buffer in a container. -template <class _Container> -class _LIBCPP_TEMPLATE_VIS __writer_container { +// A dynamically growing buffer. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> { public: - using _CharT = typename _Container::value_type; + __allocating_buffer(const __allocating_buffer&) = delete; + __allocating_buffer& operator=(const __allocating_buffer&) = delete; - _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it) - : __container_{__out_it.__get_container()} {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __allocating_buffer() : __allocating_buffer{nullptr} {} - _LIBCPP_HIDE_FROM_ABI auto __out_it() { return std::back_inserter(*__container_); } + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __allocating_buffer(__max_output_size* __max_output_size) + : __output_buffer<_CharT>{__small_buffer_, __buffer_size_, __prepare_write, __max_output_size} {} - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { - __container_->insert(__container_->end(), __ptr, __ptr + __n); + _LIBCPP_HIDE_FROM_ABI ~__allocating_buffer() { + if (__ptr_ != __small_buffer_) + _Alloc{}.deallocate(__ptr_, this->__capacity()); } -private: - _Container* __container_; -}; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, this->__size()}; } -/// Selects the type of the writer used for the output iterator. -template <class _OutIt, class _CharT> -class _LIBCPP_TEMPLATE_VIS __writer_selector { - using _Container = typename __back_insert_iterator_container<_OutIt>::type; +private: + using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; -public: - using type = - conditional_t<!same_as<_Container, void>, - __writer_container<_Container>, - conditional_t<__enable_direct_output<_OutIt, _CharT>, - __writer_direct<_OutIt, _CharT>, - __writer_iterator<_OutIt, _CharT>>>; -}; + // Since allocating is expensive the class has a small internal buffer. When + // its capacity is exceeded a dynamic buffer will be allocated. + static constexpr size_t __buffer_size_ = 256; + _CharT __small_buffer_[__buffer_size_]; -/// The generic formatting buffer. -template <class _OutIt, __fmt_char_type _CharT> - requires(output_iterator<_OutIt, const _CharT&>) -class _LIBCPP_TEMPLATE_VIS __format_buffer { - using _Storage = - conditional_t<__enable_direct_output<_OutIt, _CharT>, __direct_storage<_CharT>, __internal_storage<_CharT>>; + _CharT* __ptr_{__small_buffer_}; -public: - _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it) - requires(same_as<_Storage, __internal_storage<_CharT>>) - : __output_(__storage_.__begin(), __storage_.__buffer_size, this), __writer_(std::move(__out_it)) {} + _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { + if (__capacity < __buffer_size_) + return; - _LIBCPP_HIDE_FROM_ABI explicit __format_buffer(_OutIt __out_it) - requires(same_as<_Storage, __direct_storage<_CharT>>) - : __output_(std::__unwrap_iter(__out_it), size_t(-1), this), __writer_(std::move(__out_it)) {} + _LIBCPP_ASSERT_INTERNAL(__capacity > this->__capacity(), "the buffer must grow"); - _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); } + // _CharT is an implicit lifetime type so can be used without explicit + // construction or destruction. + _Alloc __alloc; + auto __result = std::__allocate_at_least(__alloc, __capacity); + std::copy_n(__ptr_, this->__size(), __result.ptr); + if (__ptr_ != __small_buffer_) + __alloc.deallocate(__ptr_, this->__capacity()); - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { __writer_.__flush(__ptr, __n); } + __ptr_ = __result.ptr; + this->__buffer_moved(__ptr_, __result.count); + } - _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { - __output_.__flush(); - return std::move(__writer_).__out_it(); + _LIBCPP_HIDE_FROM_ABI void __prepare_write(size_t __size_hint) { + __grow_buffer(std::max<size_t>(this->__capacity() + __size_hint, this->__capacity() * 1.6)); } -private: - _LIBCPP_NO_UNIQUE_ADDRESS _Storage __storage_; - __output_buffer<_CharT> __output_; - typename __writer_selector<_OutIt, _CharT>::type __writer_; + _LIBCPP_HIDE_FROM_ABI static void __prepare_write(__output_buffer<_CharT>& __buffer, size_t __size_hint) { + static_cast<__allocating_buffer<_CharT>&>(__buffer).__prepare_write(__size_hint); + } }; -/// A buffer that counts the number of insertions. -/// -/// Since \ref formatted_size only needs to know the size, the output itself is -/// discarded. -template <__fmt_char_type _CharT> -class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { +// A buffer that directly writes to the underlying buffer. +template <class _OutIt, __fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> { public: - _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return __output_.__make_output_iterator(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it) + : __direct_iterator_buffer{__out_it, nullptr} {} - _LIBCPP_HIDE_FROM_ABI void __flush(const _CharT*, size_t __n) { __size_ += __n; } + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size) + : __output_buffer<_CharT>{std::__unwrap_iter(__out_it), __buffer_size, __prepare_write, __max_output_size}, + __out_it_(__out_it) {} - _LIBCPP_HIDE_FROM_ABI size_t __result() && { - __output_.__flush(); - return __size_; - } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _OutIt __out_it() && { return __out_it_ + this->__size(); } private: - __internal_storage<_CharT> __storage_; - __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this}; - size_t __size_{0}; -}; + // The function format_to expects a buffer large enough for the output. The + // function format_to_n has its own helper class that restricts the number of + // write options. So this function class can pretend to have an infinite + // buffer. + static constexpr size_t __buffer_size = -1; + + _OutIt __out_it_; -/// The base of a buffer that counts and limits the number of insertions. -template <class _OutIt, __fmt_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>; + _LIBCPP_HIDE_FROM_ABI static void + __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) { + std::__throw_length_error("__direct_iterator_buffer"); + } +}; +// A buffer that writes its output to the end of a container. +template <class _OutIt, __fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> { public: - _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) - : __writer_(std::move(__out_it)), __max_size_(std::max(_Size(0), __max_size)) {} + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it) + : __container_inserter_buffer{__out_it, nullptr} {} - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { - if (_Size(__size_) <= __max_size_) - __writer_.__flush(__ptr, std::min(_Size(__n), __max_size_ - __size_)); - __size_ += __n; + [[nodiscard]] + _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it, __max_output_size* __max_output_size) + : __output_buffer<_CharT>{__small_buffer_, __buffer_size, __prepare_write, __max_output_size}, + __container_{__out_it.__get_container()} {} + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && { + __container_->insert(__container_->end(), __small_buffer_, __small_buffer_ + this->__size()); + return std::back_inserter(*__container_); } -protected: - __internal_storage<_CharT> __storage_; - __output_buffer<_CharT> __output_{__storage_.__begin(), __storage_.__buffer_size, this}; - typename __writer_selector<_OutIt, _CharT>::type __writer_; +private: + typename __back_insert_iterator_container<_OutIt>::type* __container_; + + // This class uses a fixed size buffer and appends the elements in + // __buffer_size chunks. An alternative would be to use an allocating buffer + // and append the output in a single write operation. Benchmarking showed no + // performance difference. + static constexpr size_t __buffer_size = 256; + _CharT __small_buffer_[__buffer_size]; + + _LIBCPP_HIDE_FROM_ABI void __prepare_write() { + __container_->insert(__container_->end(), __small_buffer_, __small_buffer_ + this->__size()); + this->__buffer_flushed(); + } - _Size __max_size_; - _Size __size_{0}; + _LIBCPP_HIDE_FROM_ABI static void + __prepare_write(__output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) { + static_cast<__container_inserter_buffer<_OutIt, _CharT>&>(__buffer).__prepare_write(); + } }; -/// 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 to the direct writer so it will not -/// exceed the maximum number of code units. +// A buffer that writes to an iterator. +// +// Unlike the __container_inserter_buffer this class' performance does benefit +// from allocating and then inserting. template <class _OutIt, __fmt_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>; - +class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT> { public: - _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) - : __output_(std::__unwrap_iter(__out_it), __max_size, this), - __writer_(std::move(__out_it)), - __max_size_(__max_size) { - if (__max_size <= 0) [[unlikely]] - __output_.__reset(__storage_.__begin(), __storage_.__buffer_size); - } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it) + : __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {} - _LIBCPP_HIDE_FROM_ABI void __flush(_CharT* __ptr, size_t __n) { - // A __flush to the direct writer happens in the following 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. - // - Like above, but the next "mass write" operation would overflow the - // buffer. In that case the buffer is pre-emptively switched. The still - // valid code units will be written separately. - // - 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 __max_size <= 0 the constructor already switched the buffers. - if (__size_ == 0 && __ptr != __storage_.__begin()) { - __writer_.__flush(__ptr, __n); - __output_.__reset(__storage_.__begin(), __storage_.__buffer_size); - } else if (__size_ < __max_size_) { - // Copies a part of the internal buffer to the output up to n characters. - // See __output_buffer<_CharT>::__flush_on_overflow for more information. - _Size __s = std::min(_Size(__n), __max_size_ - __size_); - std::copy_n(__ptr, __s, __writer_.__out_it()); - __writer_.__flush(__ptr, __s); - } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it, __max_output_size* __max_output_size) + : __allocating_buffer<_CharT>{__max_output_size}, __out_it_{std::move(__out_it)} {} - __size_ += __n; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __out_it() && { + return std::ranges::copy(this->__view(), std::move(__out_it_)).out; } -protected: - __internal_storage<_CharT> __storage_; - __output_buffer<_CharT> __output_; - __writer_direct<_OutIt, _CharT> __writer_; +private: + _OutIt __out_it_; +}; + +// Selects the type of the buffer used for the output iterator. +template <class _OutIt, __fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __buffer_selector { + using _Container _LIBCPP_NODEBUG = __back_insert_iterator_container<_OutIt>::type; - _Size __max_size_; - _Size __size_{0}; +public: + using type _LIBCPP_NODEBUG = + conditional_t<!same_as<_Container, void>, + __container_inserter_buffer<_OutIt, _CharT>, + conditional_t<__enable_direct_output<_OutIt, _CharT>, + __direct_iterator_buffer<_OutIt, _CharT>, + __iterator_buffer<_OutIt, _CharT>>>; }; -/// The buffer that counts and limits the number of insertions. +// A buffer that counts and limits the number of insertions. template <class _OutIt, __fmt_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>; +class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type { +public: + using _Base _LIBCPP_NODEBUG = __buffer_selector<_OutIt, _CharT>::type; + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_to_n_buffer(_OutIt __out_it, iter_difference_t<_OutIt> __n) + : _Base{std::move(__out_it), std::addressof(__max_output_size_)}, + __max_output_size_{__n < 0 ? size_t{0} : static_cast<size_t>(__n)} {} + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && { + return {static_cast<_Base&&>(*this).__out_it(), + static_cast<iter_difference_t<_OutIt>>(__max_output_size_.__code_units_written())}; + } + +private: + __max_output_size __max_output_size_; +}; +// A buffer that counts the number of insertions. +// +// Since formatted_size only needs to know the size, the output itself is +// discarded. +template <__fmt_char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer : private __output_buffer<_CharT> { public: - _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size) - : _Base(std::move(__out_it), __max_size) {} - _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return this->__output_.__make_output_iterator(); } + using _Base _LIBCPP_NODEBUG = __output_buffer<_CharT>; + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __formatted_size_buffer() + : _Base{nullptr, 0, __prepare_write, std::addressof(__max_output_size_)} {} + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto __make_output_iterator() { return _Base::__make_output_iterator(); } + + // This function does not need to be r-value qualified, however this is + // consistent with similar objects. + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __result() && { return __max_output_size_.__code_units_written(); } + +private: + __max_output_size __max_output_size_{0}; - _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __result() && { - this->__output_.__flush(); - return {std::move(this->__writer_).__out_it(), this->__size_}; + _LIBCPP_HIDE_FROM_ABI static void + __prepare_write([[maybe_unused]] __output_buffer<_CharT>& __buffer, [[maybe_unused]] size_t __size_hint) { + // Note this function does not satisfy the requirement of giving a 1 code unit buffer. + _LIBCPP_ASSERT_INTERNAL( + false, "Since __max_output_size_.__max_size_ == 0 there should never be call to this function."); } }; @@ -524,14 +578,14 @@ public: // 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>; + using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; public: - using value_type = _CharT; + using value_type _LIBCPP_NODEBUG = _CharT; struct __iterator { - using difference_type = ptrdiff_t; - using value_type = _CharT; + using difference_type _LIBCPP_NODEBUG = ptrdiff_t; + using value_type _LIBCPP_NODEBUG = _CharT; _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer) : __buffer_(std::addressof(__buffer)) {} @@ -646,7 +700,7 @@ private: } // namespace __format -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/concepts.h b/lib/libcxx/include/__format/concepts.h index 13380e9b91..28297c612d 100644 --- a/lib/libcxx/include/__format/concepts.h +++ b/lib/libcxx/include/__format/concepts.h @@ -34,7 +34,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _CharT> concept __fmt_char_type = same_as<_CharT, char> -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS || same_as<_CharT, wchar_t> # endif ; @@ -44,7 +44,7 @@ concept __fmt_char_type = // (Note testing for (w)format_context would be a valid choice, but requires // selecting the proper one depending on the type of _CharT.) template <class _CharT> -using __fmt_iter_for = _CharT*; +using __fmt_iter_for _LIBCPP_NODEBUG = _CharT*; template <class _Tp, class _Context, class _Formatter = typename _Context::template formatter_type<remove_const_t<_Tp>>> concept __formattable_with = @@ -75,8 +75,8 @@ template <class _Tp> concept __fmt_pair_like = __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); -# endif //_LIBCPP_STD_VER >= 23 -#endif //_LIBCPP_STD_VER >= 20 +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/container_adaptor.h b/lib/libcxx/include/__format/container_adaptor.h index 9f49ca03bf..48d42ee7d9 100644 --- a/lib/libcxx/include/__format/container_adaptor.h +++ b/lib/libcxx/include/__format/container_adaptor.h @@ -37,8 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Adaptor, class _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor { private: - using __maybe_const_container = __fmt_maybe_const<typename _Adaptor::container_type, _CharT>; - using __maybe_const_adaptor = __maybe_const<is_const_v<__maybe_const_container>, _Adaptor>; + using __maybe_const_container _LIBCPP_NODEBUG = __fmt_maybe_const<typename _Adaptor::container_type, _CharT>; + using __maybe_const_adaptor _LIBCPP_NODEBUG = __maybe_const<is_const_v<__maybe_const_container>, _Adaptor>; formatter<ranges::ref_view<__maybe_const_container>, _CharT> __underlying_; public: @@ -66,7 +66,7 @@ template <class _CharT, class _Tp, formattable<_CharT> _Container> struct _LIBCPP_TEMPLATE_VIS formatter<stack<_Tp, _Container>, _CharT> : public __formatter_container_adaptor<stack<_Tp, _Container>, _CharT> {}; -#endif //_LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/enable_insertable.h b/lib/libcxx/include/__format/enable_insertable.h index 86ef94a325..29fe566ff0 100644 --- a/lib/libcxx/include/__format/enable_insertable.h +++ b/lib/libcxx/include/__format/enable_insertable.h @@ -28,7 +28,7 @@ inline constexpr bool __enable_insertable = false; } // namespace __format -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/escaped_output_table.h b/lib/libcxx/include/__format/escaped_output_table.h index f7be2dc61f..7a0b352398 100644 --- a/lib/libcxx/include/__format/escaped_output_table.h +++ b/lib/libcxx/include/__format/escaped_output_table.h @@ -63,7 +63,7 @@ #include <__algorithm/ranges_upper_bound.h> #include <__config> -#include <cstddef> +#include <__cstddef/ptrdiff_t.h> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -856,7 +856,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[711] = { // clang-format on } // namespace __escaped_output_table -#endif //_LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/extended_grapheme_cluster_table.h b/lib/libcxx/include/__format/extended_grapheme_cluster_table.h index 48581d8a5d..7653a9e03b 100644 --- a/lib/libcxx/include/__format/extended_grapheme_cluster_table.h +++ b/lib/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -63,8 +63,8 @@ #include <__algorithm/ranges_upper_bound.h> #include <__config> +#include <__cstddef/ptrdiff_t.h> #include <__iterator/access.h> -#include <cstddef> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -1656,7 +1656,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { } // namespace __extended_grapheme_custer_property_boundary -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_arg.h b/lib/libcxx/include/__format/format_arg.h index aa02f81dc4..10f0ba9928 100644 --- a/lib/libcxx/include/__format/format_arg.h +++ b/lib/libcxx/include/__format/format_arg.h @@ -13,6 +13,7 @@ #include <__assert> #include <__concepts/arithmetic.h> #include <__config> +#include <__cstddef/size_t.h> #include <__format/concepts.h> #include <__format/format_parse_context.h> #include <__functional/invoke.h> @@ -113,7 +114,7 @@ _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_ case __format::__arg_t::__long_long: return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_); case __format::__arg_t::__i128: -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__i128_); # else __libcpp_unreachable(); @@ -123,7 +124,7 @@ _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_ case __format::__arg_t::__unsigned_long_long: return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); case __format::__arg_t::__u128: -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__u128_); # else __libcpp_unreachable(); @@ -148,7 +149,7 @@ _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_ __libcpp_unreachable(); } -# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER template <class _Rp, class _Visitor, class _Context> _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { @@ -164,7 +165,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg< case __format::__arg_t::__long_long: return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_); case __format::__arg_t::__i128: -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__i128_); # else __libcpp_unreachable(); @@ -174,7 +175,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg< case __format::__arg_t::__unsigned_long_long: return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); case __format::__arg_t::__u128: -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__u128_); # else __libcpp_unreachable(); @@ -199,7 +200,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg< __libcpp_unreachable(); } -# endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER /// Contains the values used in basic_format_arg. /// @@ -207,7 +208,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg< /// separate arrays. template <class _Context> class __basic_format_arg_value { - using _CharT = typename _Context::char_type; + using _CharT _LIBCPP_NODEBUG = typename _Context::char_type; public: /// Contains the implementation for basic_format_arg::handle. @@ -237,7 +238,7 @@ public: unsigned __unsigned_; long long __long_long_; unsigned long long __unsigned_long_long_; -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 __int128_t __i128_; __uint128_t __u128_; # endif @@ -261,7 +262,7 @@ public: _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {} _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept : __unsigned_long_long_(__value) {} -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {} _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {} # endif @@ -276,7 +277,7 @@ public: }; template <class _Context> -class _LIBCPP_TEMPLATE_VIS basic_format_arg { +class _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS basic_format_arg { public: class _LIBCPP_TEMPLATE_VIS handle; @@ -284,14 +285,14 @@ public: _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; } -# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER // This function is user facing, so it must wrap the non-standard types of // the "variant" in a handle to stay conforming. See __arg_t for more details. template <class _Visitor> _LIBCPP_HIDE_FROM_ABI decltype(auto) visit(this basic_format_arg __arg, _Visitor&& __vis) { switch (__arg.__type_) { -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 case __format::__arg_t::__i128: { typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); @@ -312,7 +313,7 @@ public: template <class _Rp, class _Visitor> _LIBCPP_HIDE_FROM_ABI _Rp visit(this basic_format_arg __arg, _Visitor&& __vis) { switch (__arg.__type_) { -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 case __format::__arg_t::__i128: { typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); @@ -328,7 +329,7 @@ public: } } -# endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER private: using char_type = typename _Context::char_type; @@ -370,13 +371,13 @@ private: // This function is user facing, so it must wrap the non-standard types of // the "variant" in a handle to stay conforming. See __arg_t for more details. template <class _Visitor, class _Context> -# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER _LIBCPP_DEPRECATED_IN_CXX26 # endif _LIBCPP_HIDE_FROM_ABI decltype(auto) visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { switch (__arg.__type_) { -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 case __format::__arg_t::__i128: { typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); @@ -386,13 +387,13 @@ _LIBCPP_DEPRECATED_IN_CXX26 typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); } -# endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER default: return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg); } } -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_arg_store.h b/lib/libcxx/include/__format/format_arg_store.h index 23a599e995..4c5ee9e9e4 100644 --- a/lib/libcxx/include/__format/format_arg_store.h +++ b/lib/libcxx/include/__format/format_arg_store.h @@ -22,6 +22,7 @@ #include <__type_traits/conditional.h> #include <__type_traits/extent.h> #include <__type_traits/remove_const.h> +#include <cstdint> #include <string> #include <string_view> @@ -48,7 +49,7 @@ template <class _Context, same_as<typename _Context::char_type> _Tp> consteval __arg_t __determine_arg_t() { return __arg_t::__char_type; } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class _Context, class _CharT> requires(same_as<typename _Context::char_type, wchar_t> && same_as<_CharT, char>) consteval __arg_t __determine_arg_t() { @@ -63,7 +64,7 @@ consteval __arg_t __determine_arg_t() { return __arg_t::__int; else if constexpr (sizeof(_Tp) <= sizeof(long long)) return __arg_t::__long_long; -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 else if constexpr (sizeof(_Tp) == sizeof(__int128_t)) return __arg_t::__i128; # endif @@ -78,7 +79,7 @@ consteval __arg_t __determine_arg_t() { return __arg_t::__unsigned; else if constexpr (sizeof(_Tp) <= sizeof(unsigned long long)) return __arg_t::__unsigned_long_long; -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 else if constexpr (sizeof(_Tp) == sizeof(__uint128_t)) return __arg_t::__u128; # endif @@ -172,7 +173,7 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu // final else requires no adjustment. if constexpr (__arg == __arg_t::__char_type) -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS if constexpr (same_as<typename _Context::char_type, wchar_t> && same_as<_Dp, char>) return basic_format_arg<_Context>{__arg, static_cast<wchar_t>(static_cast<unsigned char>(__value))}; else @@ -233,6 +234,11 @@ struct __packed_format_arg_store { uint64_t __types_ = 0; }; +template <class _Context> +struct __packed_format_arg_store<_Context, 0> { + uint64_t __types_ = 0; +}; + template <class _Context, size_t _Np> struct __unpacked_format_arg_store { basic_format_arg<_Context> __args_[_Np]; @@ -251,7 +257,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_arg_store { } } - using _Storage = + using _Storage _LIBCPP_NODEBUG = conditional_t<__format::__use_packed_format_arg_store(sizeof...(_Args)), __format::__packed_format_arg_store<_Context, sizeof...(_Args)>, __format::__unpacked_format_arg_store<_Context, sizeof...(_Args)>>; @@ -259,7 +265,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_arg_store { _Storage __storage; }; -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_args.h b/lib/libcxx/include/__format/format_args.h index 07923570f3..b98663c06e 100644 --- a/lib/libcxx/include/__format/format_args.h +++ b/lib/libcxx/include/__format/format_args.h @@ -11,10 +11,10 @@ #define _LIBCPP___FORMAT_FORMAT_ARGS_H #include <__config> +#include <__cstddef/size_t.h> #include <__format/format_arg.h> #include <__format/format_arg_store.h> #include <__fwd/format.h> -#include <cstddef> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -71,7 +71,7 @@ private: template <class _Context, class... _Args> basic_format_args(__format_arg_store<_Context, _Args...>) -> basic_format_args<_Context>; -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_context.h b/lib/libcxx/include/__format/format_context.h index 20c07559ea..4dbfdbc02a 100644 --- a/lib/libcxx/include/__format/format_context.h +++ b/lib/libcxx/include/__format/format_context.h @@ -23,9 +23,8 @@ #include <__memory/addressof.h> #include <__utility/move.h> #include <__variant/monostate.h> -#include <cstddef> -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION # include <__locale> # include <optional> #endif @@ -45,7 +44,7 @@ template <class _OutIt, class _CharT> requires output_iterator<_OutIt, const _CharT&> class _LIBCPP_TEMPLATE_VIS basic_format_context; -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION /** * Helper to create a basic_format_context. * @@ -67,7 +66,7 @@ __format_context_create(_OutIt __out_it, basic_format_args<basic_format_context< # endif using format_context = basic_format_context<back_insert_iterator<__format::__output_buffer<char>>, char>; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS using wformat_context = basic_format_context< back_insert_iterator<__format::__output_buffer<wchar_t>>, wchar_t>; # endif @@ -89,7 +88,7 @@ public: _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept { return __args_.get(__id); } -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION _LIBCPP_HIDE_FROM_ABI std::locale locale() { if (!__loc_) __loc_ = std::locale{}; @@ -102,7 +101,7 @@ public: private: iterator __out_it_; basic_format_args<basic_format_context> __args_; -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION // The Standard doesn't specify how the locale is stored. // [format.context]/6 @@ -132,6 +131,7 @@ private: : __out_it_(std::move(__out_it)), __args_(__args) {} # endif +public: basic_format_context(const basic_format_context&) = delete; basic_format_context& operator=(const basic_format_context&) = delete; }; @@ -163,7 +163,7 @@ public: template <class _Context> _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(iterator __out_it, _Context& __ctx) : __out_it_(std::move(__out_it)), -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION __loc_([](void* __c) { return static_cast<_Context*>(__c)->locale(); }), # endif __ctx_(std::addressof(__ctx)), @@ -180,20 +180,20 @@ public: __format::__determine_arg_t<basic_format_context, decltype(__arg)>(), __basic_format_arg_value<basic_format_context>(__arg)}; }; -# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER return static_cast<_Context*>(__c)->arg(__id).visit(std::move(__visitor)); # else _LIBCPP_SUPPRESS_DEPRECATED_PUSH return std::visit_format_arg(std::move(__visitor), static_cast<_Context*>(__c)->arg(__id)); _LIBCPP_SUPPRESS_DEPRECATED_POP -# endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER) +# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER }) { } _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept { return __arg_(__ctx_, __id); } -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION _LIBCPP_HIDE_FROM_ABI std::locale locale() { return __loc_(__ctx_); } # endif _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); } @@ -202,7 +202,7 @@ public: private: iterator __out_it_; -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION std::locale (*__loc_)(void* __ctx); # endif @@ -211,7 +211,7 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context); -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_error.h b/lib/libcxx/include/__format/format_error.h index ed40e395d6..b92e6d1de0 100644 --- a/lib/libcxx/include/__format/format_error.h +++ b/lib/libcxx/include/__format/format_error.h @@ -35,15 +35,15 @@ public: }; _LIBCPP_DIAGNOSTIC_POP -_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_format_error(const char* __s) { -# ifndef _LIBCPP_HAS_NO_EXCEPTIONS +[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_format_error(const char* __s) { +# if _LIBCPP_HAS_EXCEPTIONS throw format_error(__s); # else _LIBCPP_VERBOSE_ABORT("format_error was thrown in -fno-exceptions mode with message \"%s\"", __s); # endif } -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_functions.h b/lib/libcxx/include/__format/format_functions.h index d14b49aff1..5feaf7e5a0 100644 --- a/lib/libcxx/include/__format/format_functions.h +++ b/lib/libcxx/include/__format/format_functions.h @@ -31,7 +31,6 @@ #include <__format/formatter_pointer.h> #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> -#include <__iterator/back_insert_iterator.h> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> // iter_value_t @@ -40,7 +39,7 @@ #include <string> #include <string_view> -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION # include <__locale> #endif @@ -61,7 +60,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // to do this optimization now. using format_args = basic_format_args<format_context>; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS using wformat_args = basic_format_args<wformat_context>; # endif @@ -70,7 +69,7 @@ template <class _Context = format_context, class... _Args> return std::__format_arg_store<_Context, _Args...>(__args...); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class... _Args> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&... __args) { return std::__format_arg_store<wformat_context, _Args...>(__args...); @@ -206,7 +205,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg( case __arg_t::__long_long: return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx); case __arg_t::__i128: -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx); # else std::__throw_format_error("Invalid argument"); @@ -217,7 +216,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg( case __arg_t::__unsigned_long_long: return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx); case __arg_t::__u128: -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx); # else std::__throw_format_error("Invalid argument"); @@ -355,12 +354,12 @@ public: }; _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept { return __fmt; } # endif -# endif //_LIBCPP_STD_VER >= 26 +# endif // _LIBCPP_STD_VER >= 26 template <class _CharT, class... _Args> struct _LIBCPP_TEMPLATE_VIS basic_format_string { @@ -379,7 +378,7 @@ struct _LIBCPP_TEMPLATE_VIS basic_format_string { private: basic_string_view<_CharT> __str_; - using _Context = __format::__compile_time_basic_format_context<_CharT>; + using _Context _LIBCPP_NODEBUG = __format::__compile_time_basic_format_context<_CharT>; static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; @@ -397,7 +396,7 @@ private: template <class... _Args> using format_string = basic_format_string<char, type_identity_t<_Args>...>; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class... _Args> using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>; # endif @@ -411,7 +410,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it, return std::__format::__vformat_to( basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args)); else { - __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)}; + typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)}; std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(__buffer.__make_output_iterator(), __args)); return std::move(__buffer).__out_it(); @@ -426,7 +425,7 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, s return std::__vformat_to(std::move(__out_it), __fmt, __args); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { @@ -440,7 +439,7 @@ format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...)); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -452,20 +451,20 @@ format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { // fires too eagerly, see http://llvm.org/PR61563. template <class = void> [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { - string __res; - std::vformat_to(std::back_inserter(__res), __fmt, __args); - return __res; + __format::__allocating_buffer<char> __buffer; + std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args); + return string{__buffer.__view()}; } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template <class = void> [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { - wstring __res; - std::vformat_to(std::back_inserter(__res), __fmt, __args); - return __res; + __format::__allocating_buffer<wchar_t> __buffer; + std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args); + return wstring{__buffer.__view()}; } # endif @@ -475,7 +474,7 @@ format(format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(__fmt.get(), std::make_format_args(__args...)); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class... _Args> [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -501,7 +500,7 @@ format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args. return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...)); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -523,7 +522,7 @@ formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)}); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class... _Args> [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -531,7 +530,7 @@ formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { } # endif -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION template <class _OutIt, class _CharT, class _FormatOutIt> requires(output_iterator<_OutIt, const _CharT&>) @@ -544,7 +543,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to( return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args, std::move(__loc))); else { - __format::__format_buffer<_OutIt, _CharT> __buffer{std::move(__out_it)}; + typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)}; std::__format::__vformat_to( basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc))); @@ -558,7 +557,7 @@ vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { @@ -572,7 +571,7 @@ format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&. return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...)); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -585,20 +584,20 @@ format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&& template <class = void> [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(locale __loc, string_view __fmt, format_args __args) { - string __res; - std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); - return __res; + __format::__allocating_buffer<char> __buffer; + std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args); + return string{__buffer.__view()}; } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup // fires too eagerly, see http://llvm.org/PR61563. template <class = void> [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(locale __loc, wstring_view __fmt, wformat_args __args) { - wstring __res; - std::vformat_to(std::back_inserter(__res), std::move(__loc), __fmt, __args); - return __res; + __format::__allocating_buffer<wchar_t> __buffer; + std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args); + return wstring{__buffer.__view()}; } # endif @@ -608,7 +607,7 @@ format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...)); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class... _Args> [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -637,7 +636,7 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...)); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n( _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -661,7 +660,7 @@ formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)}); } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <class... _Args> [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { @@ -669,9 +668,9 @@ formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) } # endif -# endif // _LIBCPP_HAS_NO_LOCALIZATION +# endif // _LIBCPP_HAS_LOCALIZATION -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_parse_context.h b/lib/libcxx/include/__format/format_parse_context.h index aefcd5497f..459db751c9 100644 --- a/lib/libcxx/include/__format/format_parse_context.h +++ b/lib/libcxx/include/__format/format_parse_context.h @@ -94,11 +94,11 @@ private: _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context); using format_parse_context = basic_format_parse_context<char>; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS using wformat_parse_context = basic_format_parse_context<wchar_t>; # endif -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_string.h b/lib/libcxx/include/__format/format_string.h index bdf3cff7f4..5db5973dd5 100644 --- a/lib/libcxx/include/__format/format_string.h +++ b/lib/libcxx/include/__format/format_string.h @@ -12,10 +12,10 @@ #include <__assert> #include <__config> +#include <__cstddef/size_t.h> #include <__format/format_error.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> // iter_value_t -#include <cstddef> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -153,7 +153,7 @@ __parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { } // namespace __format -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/format_to_n_result.h b/lib/libcxx/include/__format/format_to_n_result.h index 6f30546dec..344299e32f 100644 --- a/lib/libcxx/include/__format/format_to_n_result.h +++ b/lib/libcxx/include/__format/format_to_n_result.h @@ -28,7 +28,7 @@ struct _LIBCPP_TEMPLATE_VIS format_to_n_result { }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(format_to_n_result); -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter.h b/lib/libcxx/include/__format/formatter.h index e2f418f936..39c2670dd8 100644 --- a/lib/libcxx/include/__format/formatter.h +++ b/lib/libcxx/include/__format/formatter.h @@ -40,6 +40,9 @@ struct _LIBCPP_TEMPLATE_VIS formatter { # if _LIBCPP_STD_VER >= 23 template <class _Tp> +constexpr bool enable_nonlocking_formatter_optimization = false; + +template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { if constexpr (requires { __formatter.set_debug_format(); }) __formatter.set_debug_format(); diff --git a/lib/libcxx/include/__format/formatter_bool.h b/lib/libcxx/include/__format/formatter_bool.h index 17dc69541e..d08acd4744 100644 --- a/lib/libcxx/include/__format/formatter_bool.h +++ b/lib/libcxx/include/__format/formatter_bool.h @@ -20,7 +20,7 @@ #include <__format/parser_std_format_spec.h> #include <__utility/unreachable.h> -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION # include <__locale> #endif @@ -69,7 +69,11 @@ public: __format_spec::__parser<_CharT> __parser_; }; -#endif //_LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<bool> = true; +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_char.h b/lib/libcxx/include/__format/formatter_char.h index d33e84368a..8b8fd2d42c 100644 --- a/lib/libcxx/include/__format/formatter_char.h +++ b/lib/libcxx/include/__format/formatter_char.h @@ -77,16 +77,24 @@ public: template <> struct _LIBCPP_TEMPLATE_VIS formatter<char, char> : public __formatter_char<char> {}; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t> : public __formatter_char<wchar_t> {}; template <> struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> {}; +# endif // _LIBCPP_HAS_WIDE_CHARACTERS -# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_STD_VER >= 23 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<char> = true; +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t> = true; +# endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_STD_VER >= 23 -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_floating_point.h b/lib/libcxx/include/__format/formatter_floating_point.h index fa42ba203b..ac4be9b619 100644 --- a/lib/libcxx/include/__format/formatter_floating_point.h +++ b/lib/libcxx/include/__format/formatter_floating_point.h @@ -23,6 +23,7 @@ #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> +#include <__cstddef/ptrdiff_t.h> #include <__format/concepts.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> @@ -36,9 +37,8 @@ #include <__utility/move.h> #include <__utility/unreachable.h> #include <cmath> -#include <cstddef> -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION # include <__locale> #endif @@ -141,7 +141,7 @@ struct __traits<double> { /// on the stack or the heap. template <floating_point _Fp> class _LIBCPP_TEMPLATE_VIS __float_buffer { - using _Traits = __traits<_Fp>; + using _Traits _LIBCPP_NODEBUG = __traits<_Fp>; public: // TODO FMT Improve this constructor to do a better estimate. @@ -491,7 +491,7 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer( } } -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION template <class _OutIt, class _Fp, class _CharT> _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form( _OutIt __out_it, @@ -576,7 +576,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form( // alignment return __formatter::__fill(std::move(__out_it), __padding.__after_, __specs.__fill_); } -# endif // _LIBCPP_HAS_NO_LOCALIZATION +# endif // _LIBCPP_HAS_LOCALIZATION template <class _OutIt, class _CharT> _LIBCPP_HIDE_FROM_ABI _OutIt __format_floating_point_non_finite( @@ -705,7 +705,7 @@ __format_floating_point(_Tp __value, _FormatContext& __ctx, __format_spec::__par } } -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION if (__specs.__std_.__locale_specific_form_) return __formatter::__format_locale_specific_form(__ctx.out(), __buffer, __result, __ctx.locale(), __specs); # endif @@ -774,7 +774,15 @@ struct _LIBCPP_TEMPLATE_VIS formatter<double, _CharT> : public __formatter_float template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<long double, _CharT> : public __formatter_floating_point<_CharT> {}; -#endif //_LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<float> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<double> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<long double> = true; +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_integer.h b/lib/libcxx/include/__format/formatter_integer.h index 41400f0047..3f51b10d75 100644 --- a/lib/libcxx/include/__format/formatter_integer.h +++ b/lib/libcxx/include/__format/formatter_integer.h @@ -67,7 +67,7 @@ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<long, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<long long, _CharT> : public __formatter_integer<_CharT> {}; -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif @@ -83,12 +83,43 @@ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long long, _CharT> : public __formatter_integer<_CharT> {}; -# ifndef _LIBCPP_HAS_NO_INT128 +# if _LIBCPP_HAS_INT128 template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif -#endif //_LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<signed char> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<short> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<int> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<long> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<long long> = true; +# if _LIBCPP_HAS_INT128 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<__int128_t> = true; +# endif + +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<unsigned char> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<unsigned short> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<unsigned> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<unsigned long> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<unsigned long long> = true; +# if _LIBCPP_HAS_INT128 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<__uint128_t> = true; +# endif +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_integral.h b/lib/libcxx/include/__format/formatter_integral.h index eca966f888..996b7620b3 100644 --- a/lib/libcxx/include/__format/formatter_integral.h +++ b/lib/libcxx/include/__format/formatter_integral.h @@ -27,11 +27,12 @@ #include <__type_traits/make_unsigned.h> #include <__utility/unreachable.h> #include <array> +#include <cstdint> #include <limits> #include <string> #include <string_view> -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION # include <__locale> #endif @@ -297,7 +298,7 @@ _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_integer( _Iterator __last = __formatter::__to_buffer(__first, __end, __value, __base); -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION if (__specs.__std_.__locale_specific_form_) { const auto& __np = std::use_facet<numpunct<_CharT>>(__ctx.locale()); string __grouping = __np.grouping(); @@ -411,7 +412,7 @@ struct _LIBCPP_TEMPLATE_VIS __bool_strings<char> { static constexpr string_view __false{"false"}; }; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> struct _LIBCPP_TEMPLATE_VIS __bool_strings<wchar_t> { static constexpr wstring_view __true{L"true"}; @@ -422,7 +423,7 @@ struct _LIBCPP_TEMPLATE_VIS __bool_strings<wchar_t> { template <class _CharT, class _FormatContext> _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_bool(bool __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { -# ifndef _LIBCPP_HAS_NO_LOCALIZATION +# if _LIBCPP_HAS_LOCALIZATION if (__specs.__std_.__locale_specific_form_) { const auto& __np = std::use_facet<numpunct<_CharT>>(__ctx.locale()); basic_string<_CharT> __str = __value ? __np.truename() : __np.falsename(); @@ -436,7 +437,7 @@ __format_bool(bool __value, _FormatContext& __ctx, __format_spec::__parsed_speci } // namespace __formatter -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_output.h b/lib/libcxx/include/__format/formatter_output.h index 1498f64c4a..e1f1309cd2 100644 --- a/lib/libcxx/include/__format/formatter_output.h +++ b/lib/libcxx/include/__format/formatter_output.h @@ -16,6 +16,8 @@ #include <__bit/countl.h> #include <__concepts/same_as.h> #include <__config> +#include <__cstddef/ptrdiff_t.h> +#include <__cstddef/size_t.h> #include <__format/buffer.h> #include <__format/concepts.h> #include <__format/formatter.h> @@ -28,7 +30,6 @@ #include <__memory/pointer_traits.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include <cstddef> #include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -168,7 +169,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, _CharT __value) } } -# ifndef _LIBCPP_HAS_NO_UNICODE +# if _LIBCPP_HAS_UNICODE template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> requires(same_as<_CharT, char>) _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { @@ -182,7 +183,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec:: return __out_it; } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { @@ -200,13 +201,13 @@ template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); } -# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -# else // _LIBCPP_HAS_NO_UNICODE +# endif // _LIBCPP_HAS_WIDE_CHARACTERS +# else // _LIBCPP_HAS_UNICODE template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); } -# endif // _LIBCPP_HAS_NO_UNICODE +# endif // _LIBCPP_HAS_UNICODE /// Writes the input to the output with the required padding. /// @@ -294,8 +295,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed( /// /// \pre !__specs.__has_precision() /// -/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the -/// input is ASCII. +/// \note When \c _LIBCPP_HAS_UNICODE is false the function assumes the input is ASCII. template <class _CharT> _LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( basic_string_view<_CharT> __str, @@ -326,7 +326,7 @@ _LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __pre } // namespace __formatter -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_pointer.h b/lib/libcxx/include/__format/formatter_pointer.h index 6941343efd..4ef48c168d 100644 --- a/lib/libcxx/include/__format/formatter_pointer.h +++ b/lib/libcxx/include/__format/formatter_pointer.h @@ -11,13 +11,13 @@ #define _LIBCPP___FORMAT_FORMATTER_POINTER_H #include <__config> +#include <__cstddef/nullptr_t.h> #include <__format/concepts.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> -#include <cstddef> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -65,7 +65,15 @@ struct _LIBCPP_TEMPLATE_VIS formatter<void*, _CharT> : public __formatter_pointe template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<const void*, _CharT> : public __formatter_pointer<_CharT> {}; -#endif //_LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<nullptr_t> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<void*> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<const void*> = true; +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_string.h b/lib/libcxx/include/__format/formatter_string.h index 347439fc8d..30084e5822 100644 --- a/lib/libcxx/include/__format/formatter_string.h +++ b/lib/libcxx/include/__format/formatter_string.h @@ -59,44 +59,26 @@ public: // Formatter const char*. template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template <class _FormatContext> _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const { _LIBCPP_ASSERT_INTERNAL(__str, "The basic_format_arg constructor should have prevented an invalid pointer."); - - __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); -# if _LIBCPP_STD_VER >= 23 - if (_Base::__parser_.__type_ == __format_spec::__type::__debug) - return __formatter::__format_escaped_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); -# endif - - // When using a center or right alignment and the width option the length - // of __str must be known to add the padding upfront. This case is handled - // by the base class by converting the argument to a basic_string_view. + // Converting the input to a basic_string_view means the data is looped over twice; + // - once to determine the length, and + // - once to process the data. // - // When using left alignment and the width option the padding is added - // after outputting __str so the length can be determined while outputting - // __str. The same holds true for the precision, during outputting __str it - // can be validated whether the precision threshold has been reached. For - // now these optimizations aren't implemented. Instead the base class - // handles these options. - // TODO FMT Implement these improvements. - if (__specs.__has_width() || __specs.__has_precision()) - return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); - - // No formatting required, copy the string to the output. - auto __out_it = __ctx.out(); - while (*__str) - *__out_it++ = *__str++; - return __out_it; + // This sounds slower than writing the output directly. However internally + // the output algorithms have optimizations for "bulk" operations, which + // makes this faster than a single-pass character-by-character output. + return _Base::format(basic_string_view<_CharT>(__str), __ctx); } }; // Formatter char*. template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> { - using _Base = formatter<const _CharT*, _CharT>; + using _Base _LIBCPP_NODEBUG = formatter<const _CharT*, _CharT>; template <class _FormatContext> _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const { @@ -107,7 +89,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter<const // Formatter char[]. template <__fmt_char_type _CharT, size_t _Size> struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template <class _FormatContext> _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -120,7 +102,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatte template <__fmt_char_type _CharT, class _Traits, class _Allocator> struct _LIBCPP_TEMPLATE_VIS formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template <class _FormatContext> _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -133,7 +115,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<basic_string<_CharT, _Traits, _Allocator>, // Formatter std::string_view. template <__fmt_char_type _CharT, class _Traits> struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template <class _FormatContext> _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -143,7 +125,32 @@ struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT } }; -#endif //_LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<char*> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<const char*> = true; +template <size_t _Size> +inline constexpr bool enable_nonlocking_formatter_optimization<char[_Size]> = true; +template <class _Traits, class _Allocator> +inline constexpr bool enable_nonlocking_formatter_optimization<basic_string<char, _Traits, _Allocator>> = true; +template <class _Traits> +inline constexpr bool enable_nonlocking_formatter_optimization<basic_string_view<char, _Traits>> = true; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t*> = true; +template <> +inline constexpr bool enable_nonlocking_formatter_optimization<const wchar_t*> = true; +template <size_t _Size> +inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t[_Size]> = true; +template <class _Traits, class _Allocator> +inline constexpr bool enable_nonlocking_formatter_optimization<basic_string<wchar_t, _Traits, _Allocator>> = true; +template <class _Traits> +inline constexpr bool enable_nonlocking_formatter_optimization<basic_string_view<wchar_t, _Traits>> = true; +# endif // _LIBCPP_HAS_WIDE_CHARACTERS +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/formatter_tuple.h b/lib/libcxx/include/__format/formatter_tuple.h index 030097a879..bb841ef114 100644 --- a/lib/libcxx/include/__format/formatter_tuple.h +++ b/lib/libcxx/include/__format/formatter_tuple.h @@ -143,7 +143,7 @@ template <__fmt_char_type _CharT, formattable<_CharT>... _Args> struct _LIBCPP_TEMPLATE_VIS formatter<tuple<_Args...>, _CharT> : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; -#endif //_LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/indic_conjunct_break_table.h b/lib/libcxx/include/__format/indic_conjunct_break_table.h index 44521d2749..df6cfe6a02 100644 --- a/lib/libcxx/include/__format/indic_conjunct_break_table.h +++ b/lib/libcxx/include/__format/indic_conjunct_break_table.h @@ -63,8 +63,8 @@ #include <__algorithm/ranges_upper_bound.h> #include <__config> +#include <__cstddef/ptrdiff_t.h> #include <__iterator/access.h> -#include <cstddef> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -343,7 +343,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = { } // namespace __indic_conjunct_break -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/parser_std_format_spec.h b/lib/libcxx/include/__format/parser_std_format_spec.h index 150bdde89f..415261acf0 100644 --- a/lib/libcxx/include/__format/parser_std_format_spec.h +++ b/lib/libcxx/include/__format/parser_std_format_spec.h @@ -52,13 +52,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace __format_spec { -_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void +[[noreturn]] _LIBCPP_HIDE_FROM_ABI inline void __throw_invalid_option_format_error(const char* __id, const char* __option) { std::__throw_format_error( (string("The format specifier for ") + __id + " does not allow the " + __option + " option").c_str()); } -_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __throw_invalid_type_format_error(const char* __id) { +[[noreturn]] _LIBCPP_HIDE_FROM_ABI inline void __throw_invalid_type_format_error(const char* __id) { std::__throw_format_error( (string("The type option contains an invalid value for ") + __id + " formatting argument").c_str()); } @@ -268,7 +268,7 @@ struct __code_point<char> { char __data[4] = {' '}; }; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <> struct __code_point<wchar_t> { wchar_t __data[4 / sizeof(wchar_t)] = {L' '}; @@ -321,7 +321,7 @@ struct __parsed_specifications { // value in formatting functions. static_assert(sizeof(__parsed_specifications<char>) == 16); static_assert(is_trivially_copyable_v<__parsed_specifications<char>>); -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS static_assert(sizeof(__parsed_specifications<wchar_t>) == 16); static_assert(is_trivially_copyable_v<__parsed_specifications<wchar_t>>); # endif @@ -580,11 +580,11 @@ private: std::__throw_format_error("The fill option contains an invalid value"); } -# ifndef _LIBCPP_HAS_NO_UNICODE +# if _LIBCPP_HAS_UNICODE // range-fill and tuple-fill are identical template <contiguous_iterator _Iterator> requires same_as<_CharT, char> -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS || (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) # endif _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end) { @@ -617,7 +617,7 @@ private: return true; } -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS template <contiguous_iterator _Iterator> requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end) { @@ -643,9 +643,9 @@ private: return true; } -# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS -# else // _LIBCPP_HAS_NO_UNICODE +# else // _LIBCPP_HAS_UNICODE // range-fill and tuple-fill are identical template <contiguous_iterator _Iterator> _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end) { @@ -670,7 +670,7 @@ private: return true; } -# endif // _LIBCPP_HAS_NO_UNICODE +# endif // _LIBCPP_HAS_UNICODE template <contiguous_iterator _Iterator> _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(_Iterator& __begin) { @@ -874,7 +874,7 @@ private: // Validates whether the reserved bitfields don't change the size. static_assert(sizeof(__parser<char>) == 16); -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS static_assert(sizeof(__parser<wchar_t>) == 16); # endif @@ -1026,7 +1026,7 @@ __column_width_result(size_t, _Iterator) -> __column_width_result<_Iterator>; /// "rounded up". enum class __column_width_rounding { __down, __up }; -# ifndef _LIBCPP_HAS_NO_UNICODE +# if _LIBCPP_HAS_UNICODE namespace __detail { template <contiguous_iterator _Iterator> @@ -1148,7 +1148,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_colu __result.__width_ += __ascii_size; return __result; } -# else // !defined(_LIBCPP_HAS_NO_UNICODE) +# else // _LIBCPP_HAS_UNICODE template <class _CharT> _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<typename basic_string_view<_CharT>::const_iterator> __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding) noexcept { @@ -1159,11 +1159,11 @@ __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __col return {__width, __str.begin() + __width}; } -# endif // !defined(_LIBCPP_HAS_NO_UNICODE) +# endif // _LIBCPP_HAS_UNICODE } // namespace __format_spec -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/range_default_formatter.h b/lib/libcxx/include/__format/range_default_formatter.h index b35223ae93..bb4c520f5e 100644 --- a/lib/libcxx/include/__format/range_default_formatter.h +++ b/lib/libcxx/include/__format/range_default_formatter.h @@ -40,7 +40,7 @@ concept __const_formattable_range = ranges::input_range<const _Rp> && formattable<ranges::range_reference_t<const _Rp>, _CharT>; template <class _Rp, class _CharT> -using __fmt_maybe_const = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; +using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") @@ -95,7 +95,7 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; template <ranges::input_range _Rp, class _CharT> struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::sequence, _Rp, _CharT> { private: - using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; + using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>, _CharT> __underlying_; public: @@ -122,8 +122,8 @@ public: template <ranges::input_range _Rp, class _CharT> struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::map, _Rp, _CharT> { private: - using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; - using __element_type = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>; + using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; + using __element_type _LIBCPP_NODEBUG = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>; range_formatter<__element_type, _CharT> __underlying_; public: @@ -150,8 +150,8 @@ public: template <ranges::input_range _Rp, class _CharT> struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::set, _Rp, _CharT> { private: - using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; - using __element_type = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>; + using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; + using __element_type _LIBCPP_NODEBUG = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>; range_formatter<__element_type, _CharT> __underlying_; public: @@ -207,7 +207,7 @@ template <ranges::input_range _Rp, class _CharT> requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>) struct _LIBCPP_TEMPLATE_VIS formatter<_Rp, _CharT> : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {}; -#endif //_LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/range_formatter.h b/lib/libcxx/include/__format/range_formatter.h index 6915630743..def55c86ce 100644 --- a/lib/libcxx/include/__format/range_formatter.h +++ b/lib/libcxx/include/__format/range_formatter.h @@ -257,7 +257,7 @@ private: basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "]"); }; -#endif //_LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/unicode.h b/lib/libcxx/include/__format/unicode.h index de7d0fea1d..46096fda1e 100644 --- a/lib/libcxx/include/__format/unicode.h +++ b/lib/libcxx/include/__format/unicode.h @@ -54,7 +54,7 @@ struct __consume_result { }; static_assert(sizeof(__consume_result) == sizeof(char32_t)); -# ifndef _LIBCPP_HAS_NO_UNICODE +# if _LIBCPP_HAS_UNICODE /// Implements the grapheme cluster boundary rules /// @@ -123,7 +123,7 @@ class __code_point_view; /// UTF-8 specialization. template <> class __code_point_view<char> { - using _Iterator = basic_string_view<char>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = basic_string_view<char>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) @@ -235,7 +235,7 @@ private: _Iterator __last_; }; -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# if _LIBCPP_HAS_WIDE_CHARACTERS _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_high(wchar_t __value) { return __value >= 0xd800 && __value <= 0xdbff; } @@ -249,7 +249,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_low(wchar_t __value) { /// - 4 UTF-32 (for example Linux) template <> class __code_point_view<wchar_t> { - using _Iterator = typename basic_string_view<wchar_t>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<wchar_t>::const_iterator; public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); @@ -292,7 +292,7 @@ private: _Iterator __first_; _Iterator __last_; }; -# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# endif // _LIBCPP_HAS_WIDE_CHARACTERS // State machine to implement the Extended Grapheme Cluster Boundary // @@ -300,8 +300,8 @@ private: // This implements the extended rules see // https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries class __extended_grapheme_cluster_break { - using __EGC_property = __extended_grapheme_custer_property_boundary::__property; - using __inCB_property = __indic_conjunct_break::__property; + using __EGC_property _LIBCPP_NODEBUG = __extended_grapheme_custer_property_boundary::__property; + using __inCB_property _LIBCPP_NODEBUG = __indic_conjunct_break::__property; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_break(char32_t __first_code_point) @@ -527,7 +527,7 @@ private: /// Therefore only this code point is extracted. template <class _CharT> class __extended_grapheme_cluster_view { - using _Iterator = typename basic_string_view<_CharT>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<_CharT>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) @@ -566,13 +566,13 @@ private: template <contiguous_iterator _Iterator> __extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cluster_view<iter_value_t<_Iterator>>; -# else // _LIBCPP_HAS_NO_UNICODE +# else // _LIBCPP_HAS_UNICODE // For ASCII every character is a "code point". -// This makes it easier to write code agnostic of the _LIBCPP_HAS_NO_UNICODE define. +// This makes it easier to write code agnostic of the _LIBCPP_HAS_UNICODE define. template <class _CharT> class __code_point_view { - using _Iterator = typename basic_string_view<_CharT>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<_CharT>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) @@ -591,11 +591,11 @@ private: _Iterator __last_; }; -# endif // _LIBCPP_HAS_NO_UNICODE +# endif // _LIBCPP_HAS_UNICODE } // namespace __unicode -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/width_estimation_table.h b/lib/libcxx/include/__format/width_estimation_table.h index 11f61dea18..5b4b3950c6 100644 --- a/lib/libcxx/include/__format/width_estimation_table.h +++ b/lib/libcxx/include/__format/width_estimation_table.h @@ -63,7 +63,7 @@ #include <__algorithm/ranges_upper_bound.h> #include <__config> -#include <cstddef> +#include <__cstddef/ptrdiff_t.h> #include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -263,7 +263,7 @@ inline constexpr uint32_t __table_upper_bound = 0x0003fffd; } // namespace __width_estimation_table -#endif //_LIBCPP_STD_VER >= 20 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__format/write_escaped.h b/lib/libcxx/include/__format/write_escaped.h index 052ea98c3c..aa74940032 100644 --- a/lib/libcxx/include/__format/write_escaped.h +++ b/lib/libcxx/include/__format/write_escaped.h @@ -16,6 +16,7 @@ #include <__charconv/to_chars_result.h> #include <__chrono/statically_widen.h> #include <__format/escaped_output_table.h> +#include <__format/extended_grapheme_cluster_table.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> #include <__format/unicode.h> @@ -41,8 +42,7 @@ namespace __formatter { /// Writes a string using format's width estimation algorithm. /// -/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the -/// input is ASCII. +/// \note When \c _LIBCPP_HAS_UNICODE is false the function assumes the input is ASCII. template <class _CharT> _LIBCPP_HIDE_FROM_ABI auto __write_string(basic_string_view<_CharT> __str, @@ -103,7 +103,7 @@ _LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_Cha template <class _CharT> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, bool __last_escaped, char32_t __value) { -# ifdef _LIBCPP_HAS_NO_UNICODE +# if !_LIBCPP_HAS_UNICODE // For ASCII assume everything above 127 is printable. if (__value > 127) return false; |
