-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathchecked_array_iterator.h
More file actions
246 lines (205 loc) · 8.38 KB
/
checked_array_iterator.h
File metadata and controls
246 lines (205 loc) · 8.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
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 <iterator>
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
namespace Concurrency
{
namespace streams
{
namespace details
{
namespace ext
{
template<class Ptr>
class checked_array_iterator
{ // wrap a pointer with checking
private:
using pointee_type_ = std::remove_pointer_t<Ptr>;
static_assert(std::is_pointer_v<Ptr> && std::is_object_v<pointee_type_>,
"checked_array_iterator requires pointers to objects");
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = std::remove_cv_t<pointee_type_>;
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<class T = pointee_type_, std::enable_if_t<!std::is_const_v<T>, int> = 0>
constexpr operator checked_array_iterator<const T*>() const noexcept
{
return checked_array_iterator<const T*> {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<size_t>(off),
"cannot seek checked_array_iterator before begin");
}
if (off > 0)
{
_STL_VERIFY(m_size - m_index >= static_cast<size_t>(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<Ptr>& 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<size_t>(off), "cannot seek checked_array_iterator before begin");
}
if (off < 0)
{
_STL_VERIFY(m_size - m_index >= size_t {0} - static_cast<size_t>(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<difference_type>(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<size_t>(off),
"cannot seek checked_array_iterator iterator before begin");
}
if (off > 0)
{
_STL_VERIFY(m_size - m_index >= static_cast<size_t>(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<size_t>(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