Loading...
Searching...
No Matches
v8-memory-span.h
Go to the documentation of this file.
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef INCLUDE_V8_MEMORY_SPAN_H_
6#define INCLUDE_V8_MEMORY_SPAN_H_
7
8#include <stddef.h>
9
10#include <array>
11#include <iterator>
12#include <type_traits>
13
14#include "v8config.h" // NOLINT(build/include_directory)
15
16// TODO(pkasting): Use <compare>/spaceship unconditionally after dropping
17// support for old libstdc++ versions.
18#if __has_include(<version>)
19#include <version>
20#endif
21#if defined(__cpp_lib_three_way_comparison) && \
22 __cpp_lib_three_way_comparison >= 201711L
23#define V8_HAVE_SPACESHIP_OPERATOR 1
24#else
25#define V8_HAVE_SPACESHIP_OPERATOR 0
26#endif
27
28// TODO(pkasting): Make this block unconditional after dropping support for old
29// libstdc++ versions.
30#if __has_include(<ranges>)
31#include <ranges>
32
33namespace v8 {
34
35template <typename T>
36class V8_EXPORT MemorySpan;
37
38} // namespace v8
39
40// Mark `MemorySpan` as satisfying the `view` and `borrowed_range` concepts.
41// This should be done before the definition of `MemorySpan`, so that any
42// inlined calls to range functionality use the correct specializations.
43template <typename T>
44inline constexpr bool std::ranges::enable_view<v8::MemorySpan<T>> = true;
45template <typename T>
46inline constexpr bool std::ranges::enable_borrowed_range<v8::MemorySpan<T>> =
47 true;
48#endif
49
50namespace v8 {
51
62template <typename T>
64 private:
66 template <typename From, typename To>
67 using is_array_convertible = std::is_convertible<From (*)[], To (*)[]>;
68 template <typename From, typename To>
69 static constexpr bool is_array_convertible_v =
70 is_array_convertible<From, To>::value;
71
72 template <typename It>
73 using iter_reference_t = decltype(*std::declval<It&>());
74
75 template <typename It, typename = void>
76 struct is_compatible_iterator : std::false_type {};
77 template <typename It>
78 struct is_compatible_iterator<
79 It,
80 std::void_t<
81 std::is_base_of<std::random_access_iterator_tag,
82 typename std::iterator_traits<It>::iterator_category>,
83 is_array_convertible<std::remove_reference_t<iter_reference_t<It>>,
84 T>>> : std::true_type {};
85 template <typename It>
86 static constexpr bool is_compatible_iterator_v =
87 is_compatible_iterator<It>::value;
88
89 template <typename U>
90 [[nodiscard]] static constexpr U* to_address(U* p) noexcept {
91 return p;
92 }
93
94 template <typename It,
95 typename = std::void_t<decltype(std::declval<It&>().operator->())>>
96 [[nodiscard]] static constexpr auto to_address(It it) noexcept {
97 return it.operator->();
98 }
99
100 public:
102 constexpr MemorySpan() = default;
103
107 constexpr MemorySpan(std::nullptr_t, size_t) {}
108
110 template <typename Iterator,
111 std::enable_if_t<is_compatible_iterator_v<Iterator>, bool> = true>
112 constexpr MemorySpan(Iterator first,
113 size_t count) // NOLINT(runtime/explicit)
114 : data_(to_address(first)), size_(count) {}
115
117 template <typename Iterator,
118 std::enable_if_t<is_compatible_iterator_v<Iterator> &&
119 !std::is_convertible_v<Iterator, size_t>,
120 bool> = true>
121 constexpr MemorySpan(Iterator first,
122 Iterator last) // NOLINT(runtime/explicit)
123 : data_(to_address(first)), size_(last - first) {}
124
126 template <size_t N>
127 constexpr MemorySpan(T (&a)[N]) noexcept // NOLINT(runtime/explicit)
128 : data_(a), size_(N) {}
129
131 template <typename U, size_t N,
132 std::enable_if_t<is_array_convertible_v<U, T>, bool> = true>
133 constexpr MemorySpan(
134 std::array<U, N>& a) noexcept // NOLINT(runtime/explicit)
135 : data_(a.data()), size_{N} {}
136
138 template <typename U, size_t N,
139 std::enable_if_t<is_array_convertible_v<const U, T>, bool> = true>
140 constexpr MemorySpan(
141 const std::array<U, N>& a) noexcept // NOLINT(runtime/explicit)
142 : data_(a.data()), size_{N} {}
143
145 [[nodiscard]] constexpr T* data() const { return data_; }
147 [[nodiscard]] constexpr size_t size() const { return size_; }
148
149 [[nodiscard]] constexpr T& operator[](size_t i) const { return data_[i]; }
150
152 [[nodiscard]] constexpr bool empty() const { return size() == 0; }
153
154 class Iterator {
155 public:
156 using difference_type = std::ptrdiff_t;
157 using value_type = T;
160 using iterator_category = std::random_access_iterator_tag;
161 // There seems to be no feature-test macro covering this, so use the
162 // presence of `<ranges>` as a crude proxy, since it was added to the
163 // standard as part of the Ranges papers.
164 // TODO(pkasting): Add this unconditionally after dropping support for old
165 // libstdc++ versions.
166#if __has_include(<ranges>)
167 using iterator_concept = std::contiguous_iterator_tag;
168#endif
169
170 // Required to satisfy `std::semiregular<>`.
171 constexpr Iterator() = default;
172
173 [[nodiscard]] friend constexpr bool operator==(const Iterator& a,
174 const Iterator& b) {
175 // TODO(pkasting): Replace this body with `= default` after dropping
176 // support for old gcc versions.
177 return a.ptr_ == b.ptr_;
178 }
179#if V8_HAVE_SPACESHIP_OPERATOR
180 [[nodiscard]] friend constexpr auto operator<=>(const Iterator&,
181 const Iterator&) = default;
182#else
183 // Assume that if spaceship isn't present, operator rewriting might not be
184 // either.
185 [[nodiscard]] friend constexpr bool operator!=(const Iterator& a,
186 const Iterator& b) {
187 return a.ptr_ != b.ptr_;
188 }
189
190 [[nodiscard]] friend constexpr bool operator<(const Iterator& a,
191 const Iterator& b) {
192 return a.ptr_ < b.ptr_;
193 }
194 [[nodiscard]] friend constexpr bool operator<=(const Iterator& a,
195 const Iterator& b) {
196 return a.ptr_ <= b.ptr_;
197 }
198 [[nodiscard]] friend constexpr bool operator>(const Iterator& a,
199 const Iterator& b) {
200 return a.ptr_ > b.ptr_;
201 }
202 [[nodiscard]] friend constexpr bool operator>=(const Iterator& a,
203 const Iterator& b) {
204 return a.ptr_ >= b.ptr_;
205 }
206#endif
207
208 constexpr Iterator& operator++() {
209 ++ptr_;
210 return *this;
211 }
212
213 constexpr Iterator operator++(int) {
214 Iterator temp = *this;
215 ++*this;
216 return temp;
217 }
218
219 constexpr Iterator& operator--() {
220 --ptr_;
221 return *this;
222 }
223
224 constexpr Iterator operator--(int) {
225 Iterator temp = *this;
226 --*this;
227 return temp;
228 }
229
231 ptr_ += rhs;
232 return this;
233 }
234
235 [[nodiscard]] friend constexpr Iterator operator+(Iterator lhs,
236 difference_type rhs) {
237 lhs += rhs;
238 return lhs;
239 }
240
241 [[nodiscard]] friend constexpr Iterator operator+(difference_type lhs,
242 const Iterator& rhs) {
243 return rhs + lhs;
244 }
245
247 ptr_ -= rhs;
248 return this;
249 }
250
251 [[nodiscard]] friend constexpr Iterator operator-(Iterator lhs,
252 difference_type rhs) {
253 lhs -= rhs;
254 return lhs;
255 }
256
257 [[nodiscard]] friend constexpr difference_type operator-(
258 const Iterator& lhs, const Iterator& rhs) {
259 return lhs.ptr_ - rhs.ptr_;
260 }
261
262 [[nodiscard]] constexpr reference operator*() const { return *ptr_; }
263 [[nodiscard]] constexpr pointer operator->() const { return ptr_; }
264 [[nodiscard]] constexpr reference operator[](size_t offset) const {
265 return ptr_[offset];
266 }
267
268 private:
269 friend class MemorySpan<T>;
270
271 constexpr explicit Iterator(T* ptr) : ptr_(ptr) {}
272
273 T* ptr_ = nullptr;
274 };
275
276 [[nodiscard]] Iterator begin() const { return Iterator(data_); }
277 [[nodiscard]] Iterator end() const { return Iterator(data_ + size_); }
278
279 private:
280 T* data_ = nullptr;
281 size_t size_ = 0;
282};
283
295namespace detail {
296template <class T, std::size_t N, std::size_t... I>
297[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array_lvalue_impl(
298 T (&a)[N], std::index_sequence<I...>) {
299 return {{a[I]...}};
300}
301
302template <class T, std::size_t N, std::size_t... I>
303[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array_rvalue_impl(
304 T (&&a)[N], std::index_sequence<I...>) {
305 return {{std::move(a[I])...}};
306}
307} // namespace detail
308
309template <class T, std::size_t N>
310[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N]) {
311 return detail::to_array_lvalue_impl(a, std::make_index_sequence<N>{});
312}
313
314template <class T, std::size_t N>
315[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array(
316 T (&&a)[N]) {
317 return detail::to_array_rvalue_impl(std::move(a),
318 std::make_index_sequence<N>{});
319}
320
321} // namespace v8
322#endif // INCLUDE_V8_MEMORY_SPAN_H_
Definition: v8-memory-span.h:154
std::ptrdiff_t difference_type
Definition: v8-memory-span.h:156
friend constexpr bool operator>(const Iterator &a, const Iterator &b)
Definition: v8-memory-span.h:198
friend constexpr difference_type operator-(const Iterator &lhs, const Iterator &rhs)
Definition: v8-memory-span.h:257
constexpr Iterator & operator+=(difference_type rhs)
Definition: v8-memory-span.h:230
friend constexpr Iterator operator+(Iterator lhs, difference_type rhs)
Definition: v8-memory-span.h:235
constexpr Iterator & operator++()
Definition: v8-memory-span.h:208
friend constexpr bool operator>=(const Iterator &a, const Iterator &b)
Definition: v8-memory-span.h:202
friend constexpr bool operator==(const Iterator &a, const Iterator &b)
Definition: v8-memory-span.h:173
std::random_access_iterator_tag iterator_category
Definition: v8-memory-span.h:160
T value_type
Definition: v8-memory-span.h:157
constexpr Iterator()=default
friend constexpr bool operator!=(const Iterator &a, const Iterator &b)
Definition: v8-memory-span.h:185
value_type & reference
Definition: v8-memory-span.h:159
constexpr reference operator*() const
Definition: v8-memory-span.h:262
friend constexpr Iterator operator+(difference_type lhs, const Iterator &rhs)
Definition: v8-memory-span.h:241
constexpr Iterator operator--(int)
Definition: v8-memory-span.h:224
constexpr Iterator operator++(int)
Definition: v8-memory-span.h:213
value_type * pointer
Definition: v8-memory-span.h:158
friend constexpr bool operator<(const Iterator &a, const Iterator &b)
Definition: v8-memory-span.h:190
constexpr Iterator & operator-=(difference_type rhs)
Definition: v8-memory-span.h:246
friend constexpr Iterator operator-(Iterator lhs, difference_type rhs)
Definition: v8-memory-span.h:251
friend constexpr bool operator<=(const Iterator &a, const Iterator &b)
Definition: v8-memory-span.h:194
constexpr Iterator & operator--()
Definition: v8-memory-span.h:219
constexpr pointer operator->() const
Definition: v8-memory-span.h:263
Definition: v8-memory-span.h:63
constexpr MemorySpan(std::nullptr_t, size_t)
Definition: v8-memory-span.h:107
Iterator end() const
Definition: v8-memory-span.h:277
constexpr MemorySpan(std::array< U, N > &a) noexcept
Definition: v8-memory-span.h:133
constexpr MemorySpan()=default
constexpr T & operator[](size_t i) const
Definition: v8-memory-span.h:149
constexpr MemorySpan(const std::array< U, N > &a) noexcept
Definition: v8-memory-span.h:140
constexpr MemorySpan(Iterator first, size_t count)
Definition: v8-memory-span.h:112
constexpr MemorySpan(T(&a)[N]) noexcept
Definition: v8-memory-span.h:127
constexpr T * data() const
Definition: v8-memory-span.h:145
constexpr MemorySpan(Iterator first, Iterator last)
Definition: v8-memory-span.h:121
constexpr bool empty() const
Definition: v8-memory-span.h:152
Iterator begin() const
Definition: v8-memory-span.h:276
constexpr size_t size() const
Definition: v8-memory-span.h:147
constexpr std::array< std::remove_cv_t< T >, N > to_array_rvalue_impl(T(&&a)[N], std::index_sequence< I... >)
Definition: v8-memory-span.h:303
constexpr std::array< std::remove_cv_t< T >, N > to_array_lvalue_impl(T(&a)[N], std::index_sequence< I... >)
Definition: v8-memory-span.h:297
Definition: libplatform.h:15
constexpr std::array< std::remove_cv_t< T >, N > to_array(T(&a)[N])
Definition: v8-memory-span.h:310
#define V8_EXPORT
Definition: v8config.h:793