|
|
|
@ -485,20 +485,6 @@ inline auto get_data(Container& c) -> typename Container::value_type* {
|
|
|
|
|
return c.data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(_SECURE_SCL) && _SECURE_SCL
|
|
|
|
|
// Make a checked iterator to avoid MSVC warnings.
|
|
|
|
|
template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
|
|
|
|
|
template <typename T>
|
|
|
|
|
constexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> {
|
|
|
|
|
return {p, size};
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
template <typename T> using checked_ptr = T*;
|
|
|
|
|
template <typename T> constexpr auto make_checked(T* p, size_t) -> T* {
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Attempts to reserve space for n extra characters in the output range.
|
|
|
|
|
// Returns a pointer to the reserved range or a reference to it.
|
|
|
|
|
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
|
|
|
@ -507,11 +493,11 @@ __attribute__((no_sanitize("undefined")))
|
|
|
|
|
#endif
|
|
|
|
|
inline auto
|
|
|
|
|
reserve(std::back_insert_iterator<Container> it, size_t n)
|
|
|
|
|
-> checked_ptr<typename Container::value_type> {
|
|
|
|
|
-> typename Container::value_type* {
|
|
|
|
|
Container& c = get_container(it);
|
|
|
|
|
size_t size = c.size();
|
|
|
|
|
c.resize(size + n);
|
|
|
|
|
return make_checked(get_data(c) + size, n);
|
|
|
|
|
return get_data(c) + size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
@ -544,7 +530,7 @@ template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
|
|
|
|
|
|
|
|
|
|
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
|
|
|
|
inline auto base_iterator(std::back_insert_iterator<Container>& it,
|
|
|
|
|
checked_ptr<typename Container::value_type>)
|
|
|
|
|
typename Container::value_type*)
|
|
|
|
|
-> std::back_insert_iterator<Container> {
|
|
|
|
|
return it;
|
|
|
|
|
}
|
|
|
|
@ -775,7 +761,7 @@ void buffer<T>::append(const U* begin, const U* end) {
|
|
|
|
|
try_reserve(size_ + count);
|
|
|
|
|
auto free_cap = capacity_ - size_;
|
|
|
|
|
if (free_cap < count) count = free_cap;
|
|
|
|
|
std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));
|
|
|
|
|
std::uninitialized_copy_n(begin, count, ptr_ + size_);
|
|
|
|
|
size_ += count;
|
|
|
|
|
begin += count;
|
|
|
|
|
}
|
|
|
|
@ -853,7 +839,7 @@ class basic_memory_buffer final : public detail::buffer<T> {
|
|
|
|
|
if (data == other.store_) {
|
|
|
|
|
this->set(store_, capacity);
|
|
|
|
|
detail::copy_str<T>(other.store_, other.store_ + size,
|
|
|
|
|
detail::make_checked(store_, capacity));
|
|
|
|
|
store_);
|
|
|
|
|
} else {
|
|
|
|
|
this->set(data, capacity);
|
|
|
|
|
// Set pointer to the inline array so that delete is not called
|
|
|
|
@ -923,7 +909,7 @@ FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow(
|
|
|
|
|
std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
|
|
|
|
|
// The following code doesn't throw, so the raw pointer above doesn't leak.
|
|
|
|
|
std::uninitialized_copy(old_data, old_data + this->size(),
|
|
|
|
|
detail::make_checked(new_data, new_capacity));
|
|
|
|
|
new_data);
|
|
|
|
|
this->set(new_data, new_capacity);
|
|
|
|
|
// deallocate must not throw according to the standard, but even if it does,
|
|
|
|
|
// the buffer already uses the new storage and will deallocate it in
|
|
|
|
@ -2804,7 +2790,7 @@ class bigint {
|
|
|
|
|
auto size = other.bigits_.size();
|
|
|
|
|
bigits_.resize(size);
|
|
|
|
|
auto data = other.bigits_.data();
|
|
|
|
|
std::copy(data, data + size, make_checked(bigits_.data(), size));
|
|
|
|
|
std::copy(data, data + size, bigits_.data());
|
|
|
|
|
exp_ = other.exp_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|