| 789 | } |
| 790 | |
| 791 | static FMT_CONSTEXPR20 void grow(detail::buffer<T>& buf, size_t size) { |
| 792 | detail::abort_fuzzing_if(size > 5000); |
| 793 | auto& self = static_cast<basic_memory_buffer&>(buf); |
| 794 | const size_t max_size = |
| 795 | std::allocator_traits<Allocator>::max_size(self.alloc_); |
| 796 | size_t old_capacity = buf.capacity(); |
| 797 | size_t new_capacity = old_capacity + old_capacity / 2; |
| 798 | if (size > new_capacity) |
| 799 | new_capacity = size; |
| 800 | else if (new_capacity > max_size) |
| 801 | new_capacity = max_of(size, max_size); |
| 802 | T* old_data = buf.data(); |
| 803 | T* new_data = self.alloc_.allocate(new_capacity); |
| 804 | // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). |
| 805 | detail::assume(buf.size() <= new_capacity); |
| 806 | // The following code doesn't throw, so the raw pointer above doesn't leak. |
| 807 | memcpy(new_data, old_data, buf.size() * sizeof(T)); |
| 808 | self.set(new_data, new_capacity); |
| 809 | // deallocate must not throw according to the standard, but even if it does, |
| 810 | // the buffer already uses the new storage and will deallocate it in |
| 811 | // destructor. |
| 812 | if (old_data != self.store_) self.alloc_.deallocate(old_data, old_capacity); |
| 813 | } |
| 814 | |
| 815 | public: |
| 816 | using value_type = T; |
nothing calls this directly
no test coverage detected