diff --git a/Release/include/cpprest/containerstream.h b/Release/include/cpprest/containerstream.h index 6e949a75e0..f76b5219d4 100644 --- a/Release/include/cpprest/containerstream.h +++ b/Release/include/cpprest/containerstream.h @@ -14,10 +14,10 @@ #pragma once #include "cpprest/astreambuf.h" +#include "cpprest/details/checked_array_iterator.h" #include "cpprest/streams.h" #include "pplx/pplxtasks.h" #include -#include #include #include @@ -401,7 +401,7 @@ class basic_container_buffer : public streams::details::streambuf_state_manager< #if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0 // Avoid warning C4996: Use checked iterators under SECURE_SCL - std::copy(readBegin, readEnd, stdext::checked_array_iterator<_CharType*>(ptr, count)); + std::copy(readBegin, readEnd, ext::checked_array_iterator<_CharType*>(ptr, count)); #else std::copy(readBegin, readEnd, ptr); #endif // _WIN32 diff --git a/Release/include/cpprest/details/checked_array_iterator.h b/Release/include/cpprest/details/checked_array_iterator.h new file mode 100644 index 0000000000..3e707689bb --- /dev/null +++ b/Release/include/cpprest/details/checked_array_iterator.h @@ -0,0 +1,246 @@ +/*** + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * This file defines the checked iterator iterator template that originated from MSVC STL's + * stdext::checked_iterator_iterator, which is now deprecated. + * + * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ +#pragma once + +#ifndef CHECKED_ARRAY_ITERATOR_H +#define CHECKED_ARRAY_ITERATOR_H + +#include + +#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0 +namespace Concurrency +{ +namespace streams +{ +namespace details +{ +namespace ext +{ +template +class checked_array_iterator +{ // wrap a pointer with checking +private: + using pointee_type_ = std::remove_pointer_t; + static_assert(std::is_pointer_v && std::is_object_v, + "checked_array_iterator requires pointers to objects"); + +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = std::remove_cv_t; + using difference_type = std::ptrdiff_t; + using pointer = Ptr; + using reference = pointee_type_&; +#ifdef __cpp_lib_concepts + using iterator_concept = std::contiguous_iterator_tag; +#endif // defined(__cpp_lib_concepts) + + constexpr checked_array_iterator() = default; + + constexpr checked_array_iterator(const Ptr arr, const size_t size, const size_t ind = 0) noexcept + : m_data(arr), m_size(size), m_index(ind) + { + _STL_VERIFY(ind <= size, "checked_array_iterator construction index out of range"); + } + + template, int> = 0> + constexpr operator checked_array_iterator() const noexcept + { + return checked_array_iterator {m_data, m_size, m_index}; + } + + _NODISCARD constexpr Ptr base() const noexcept { return m_data + m_index; } + + _NODISCARD constexpr reference operator*() const noexcept { return *operator->(); } + + _NODISCARD constexpr pointer operator->() const noexcept + { + _STL_VERIFY(m_data, "cannot dereference value-initialized or null checked_array_iterator"); + _STL_VERIFY(m_index < m_size, "cannot dereference end checked_array_iterator"); + return m_data + m_index; + } + + constexpr checked_array_iterator& operator++() noexcept + { + _STL_VERIFY(m_data, "cannot increment value-initialized or null checked_array_iterator"); + _STL_VERIFY(m_index < m_size, "cannot increment checked_array_iterator past end"); + ++m_index; + return *this; + } + + constexpr checked_array_iterator operator++(int) noexcept + { + auto tmp = *this; + ++*this; + return tmp; + } + + constexpr checked_array_iterator& operator--() noexcept + { + _STL_VERIFY(m_data, "cannot decrement value-initialized or null checked_array_iterator"); + _STL_VERIFY(m_index != 0, "cannot decrement checked_array_iterator before begin"); + --m_index; + return *this; + } + + constexpr checked_array_iterator operator--(int) noexcept + { + auto tmp = *this; + --*this; + return tmp; + } + + constexpr checked_array_iterator& operator+=(const difference_type off) noexcept + { + if (off != 0) + { + _STL_VERIFY(m_data, "cannot seek value-initialized or null checked_array_iterator"); + } + + if (off < 0) + { + _STL_VERIFY(m_index >= size_t {0} - static_cast(off), + "cannot seek checked_array_iterator before begin"); + } + + if (off > 0) + { + _STL_VERIFY(m_size - m_index >= static_cast(off), "cannot seek checked_array_iterator after end"); + } + + m_index += off; + return *this; + } + + _NODISCARD constexpr checked_array_iterator operator+(const difference_type off) const noexcept + { + auto tmp = *this; + tmp += off; + return tmp; + } + + _NODISCARD_FRIEND constexpr checked_array_iterator operator+(const difference_type off, + const checked_array_iterator& next_iter) noexcept + { + return next_iter + off; + } + + constexpr checked_array_iterator& operator-=(const difference_type off) noexcept + { + if (off != 0) + { + _STL_VERIFY(m_data, "cannot seek value-initialized or null checked_array_iterator"); + } + + if (off > 0) + { + _STL_VERIFY(m_index >= static_cast(off), "cannot seek checked_array_iterator before begin"); + } + + if (off < 0) + { + _STL_VERIFY(m_size - m_index >= size_t {0} - static_cast(off), + "cannot seek checked_array_iterator after end"); + } + + m_index -= off; + return *this; + } + + _NODISCARD constexpr checked_array_iterator operator-(const difference_type off) const noexcept + { + auto tmp = *this; + tmp -= off; + return tmp; + } + + _NODISCARD constexpr difference_type operator-(const checked_array_iterator& rhs) const noexcept + { + _STL_VERIFY(m_data == rhs.m_data && m_size == rhs.m_size, + "cannot subtract incompatible checked_array_iterators"); + return static_cast(m_index - rhs.m_index); + } + + _NODISCARD constexpr reference operator[](const difference_type off) const noexcept { return *(*this + off); } + + _NODISCARD constexpr bool operator==(const checked_array_iterator& rhs) const noexcept + { + _STL_VERIFY(m_data == rhs.m_data && m_size == rhs.m_size, + "cannot compare incompatible checked_array_iterators for equality"); + return m_index == rhs.m_index; + } + +#if _HAS_CXX20 + _NODISCARD constexpr _STD strong_ordering operator<=>(const checked_array_iterator& rhs) const noexcept + { + _STL_VERIFY(m_data == rhs.m_data && m_size == rhs.m_size, + "cannot compare incompatible checked_array_iterators"); + return m_index <=> rhs.m_index; + } +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + _NODISCARD constexpr bool operator!=(const checked_array_iterator& rhs) const noexcept { return !(*this == rhs); } + + _NODISCARD constexpr bool operator<(const checked_array_iterator& rhs) const noexcept + { + _STL_VERIFY(m_data == rhs.m_data && m_size == rhs.m_size, + "cannot compare incompatible checked_array_iterators"); + return m_index < rhs.m_index; + } + + _NODISCARD constexpr bool operator>(const checked_array_iterator& rhs) const noexcept { return rhs < *this; } + + _NODISCARD constexpr bool operator<=(const checked_array_iterator& rhs) const noexcept { return !(rhs < *this); } + + _NODISCARD constexpr bool operator>=(const checked_array_iterator& rhs) const noexcept { return !(*this < rhs); } +#endif // !_HAS_CXX20 + + friend constexpr void _Verify_range(const checked_array_iterator& first, + const checked_array_iterator& last) noexcept + { + _STL_VERIFY(last.m_data == last.m_data && first.m_size == last.m_size, "mismatching checked_array_iterators"); + _STL_VERIFY(last.m_index <= last.m_index, "transposed checked_array_iterator range"); + } + + constexpr void _Verify_offset(const difference_type off) const noexcept + { + if (off < 0) + { + _STL_VERIFY(m_index >= size_t {0} - static_cast(off), + "cannot seek checked_array_iterator iterator before begin"); + } + + if (off > 0) + { + _STL_VERIFY(m_size - m_index >= static_cast(off), + "cannot seek checked_array_iterator iterator after end"); + } + } + + using _Prevent_inheriting_unwrap = checked_array_iterator; + + _NODISCARD constexpr Ptr _Unwrapped() const noexcept { return m_data + m_index; } + + constexpr void _Seek_to(Ptr it) noexcept { m_index = static_cast(it - m_data); } + +private: + Ptr m_data = nullptr; // beginning of array + size_t m_size = 0; // size of array + size_t m_index = 0; // offset into array +}; +} // namespace ext +} // namespace details +} // namespace streams +} // namespace Concurrency +#endif + +#endif diff --git a/Release/include/cpprest/producerconsumerstream.h b/Release/include/cpprest/producerconsumerstream.h index 3487c4606f..d933c70a28 100644 --- a/Release/include/cpprest/producerconsumerstream.h +++ b/Release/include/cpprest/producerconsumerstream.h @@ -17,9 +17,9 @@ #define CASA_PRODUCER_CONSUMER_STREAMS_H #include "cpprest/astreambuf.h" +#include "cpprest/details/checked_array_iterator.h" #include "pplx/pplxtasks.h" #include -#include #include #include @@ -441,7 +441,7 @@ class basic_producer_consumer_buffer : public streams::details::streambuf_state_ #if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0 // Avoid warning C4996: Use checked iterators under SECURE_SCL - std::copy(beg, end, stdext::checked_array_iterator<_CharType*>(dest, count)); + std::copy(beg, end, ext::checked_array_iterator<_CharType*>(dest, count)); #else std::copy(beg, end, dest); #endif // _WIN32 @@ -464,7 +464,7 @@ class basic_producer_consumer_buffer : public streams::details::streambuf_state_ #if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0 // Avoid warning C4996: Use checked iterators under SECURE_SCL - std::copy(src, srcEnd, stdext::checked_array_iterator<_CharType*>(wbegin(), static_cast(avail))); + std::copy(src, srcEnd, ext::checked_array_iterator<_CharType*>(wbegin(), static_cast(avail))); #else std::copy(src, srcEnd, wbegin()); #endif // _WIN32 diff --git a/Release/include/cpprest/rawptrstream.h b/Release/include/cpprest/rawptrstream.h index 1f15ecbe77..3b2d6b8c20 100644 --- a/Release/include/cpprest/rawptrstream.h +++ b/Release/include/cpprest/rawptrstream.h @@ -17,10 +17,10 @@ #define CASA_RAWPTR_STREAMS_H #include "cpprest/astreambuf.h" +#include "cpprest/details/checked_array_iterator.h" #include "cpprest/streams.h" #include "pplx/pplxtasks.h" #include -#include #include #include @@ -441,7 +441,7 @@ class basic_rawptr_buffer : public streams::details::streambuf_state_manager<_Ch #if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0 // Avoid warning C4996: Use checked iterators under SECURE_SCL - std::copy(readBegin, readEnd, stdext::checked_array_iterator<_CharType*>(ptr, count)); + std::copy(readBegin, readEnd, ext::checked_array_iterator<_CharType*>(ptr, count)); #else std::copy(readBegin, readEnd, ptr); #endif // _WIN32