From cb7bbc62245e372e206c1a776ac1c79be76dbe13 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sat, 7 Apr 2018 14:54:17 -0700 Subject: [PATCH] Improve checked iterator support --- include/fmt/format.h | 53 ++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 7f4b5504..865f132c 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -341,14 +341,26 @@ FMT_CONSTEXPR typename std::make_unsigned::type to_unsigned(Int value) { } #if FMT_SECURE_SCL -// Use checked iterator to avoid warnings on MSVC. template -inline stdext::checked_array_iterator make_ptr(T *ptr, std::size_t size) { - return stdext::checked_array_iterator(ptr, size); +struct checked { typedef stdext::checked_array_iterator type; }; + +// Make a checked iterator to avoid warnings on MSVC. +template +inline stdext::checked_array_iterator make_checked(T *p, std::size_t size) { + return {p, size}; } + +// Extracts the pointer from a checked iterator. +template +static T *from_checked(stdext::checked_array_iterator p) { return p.base(); } + #else template -inline T *make_ptr(T *ptr, std::size_t) { return ptr; } +struct checked { typedef T *type; }; +template +inline T *make_checked(T *p, std::size_t) { return p; } +template +inline T *from_checked(T *p) { return p; } #endif template @@ -357,7 +369,7 @@ void basic_buffer::append(const U *begin, const U *end) { std::size_t new_size = size_ + internal::to_unsigned(end - begin); reserve(new_size); std::uninitialized_copy(begin, end, - internal::make_ptr(ptr_, capacity_) + size_); + internal::make_checked(ptr_, capacity_) + size_); size_ = new_size; } } // namespace internal @@ -437,7 +449,7 @@ class basic_memory_buffer: private Allocator, public internal::basic_buffer { if (data == other.store_) { this->set(store_, capacity); std::uninitialized_copy(other.store_, other.store_ + size, - internal::make_ptr(store_, capacity)); + internal::make_checked(store_, capacity)); } else { this->set(data, capacity); // Set pointer to the inline array so that delete is not called @@ -484,7 +496,7 @@ void basic_memory_buffer::grow(std::size_t size) { T *new_data = internal::allocate(*this, 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(), - internal::make_ptr(new_data, new_capacity)); + internal::make_checked(new_data, new_capacity)); 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 @@ -586,34 +598,15 @@ extern template int char_traits::format_float( int precision, long double value); #endif -#if FMT_SECURE_SCL -template -struct pointer { typedef stdext::checked_array_iterator type; }; -// Returns pointer value. -template -static T *get(typename pointer::type p) { return p.base(); } -template -static typename pointer::type make_pointer(T* p, std::size_t n) { - return {p, n}; -} -#else -template -struct pointer { typedef T *type; }; -template -static T *get(T *p) { return p; } -template -static T *make_pointer(T *p, std::size_t) { return p; } -#endif - template inline typename std::enable_if< is_contiguous::value, - typename pointer::type>::type + typename checked::type>::type reserve(std::back_insert_iterator &it, std::size_t n) { Container &c = internal::get_container(it); std::size_t size = c.size(); c.resize(size + n); - return make_pointer(&c[size], n); + return make_checked(&c[size], n); } template @@ -731,6 +724,7 @@ class counting_iterator { typedef std::ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; + typedef counting_iterator _Unchecked_type; // Mark iterator as checked. counting_iterator(): count_(0) {} @@ -764,6 +758,7 @@ class truncating_iterator { typedef typename traits::difference_type difference_type; typedef typename traits::pointer pointer; typedef typename traits::reference reference; + typedef truncating_iterator _Unchecked_type; // Mark iterator as checked. truncating_iterator(OutputIt out, std::size_t limit) : out_(out), limit_(limit), count_(0) {} @@ -956,7 +951,7 @@ class add_thousands_sep { return; buffer -= sep_.size(); std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(), - internal::make_ptr(buffer, sep_.size())); + internal::make_checked(buffer, sep_.size())); } };