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 <compare>
12#include <cstddef>
13#include <iterator>
14#include <ranges>
15#include <type_traits>
16
17#include "v8config.h" // NOLINT(build/include_directory)
18
19namespace v8 {
20
21template <typename T>
22class V8_EXPORT MemorySpan;
23
24} // namespace v8
25
26// Mark `MemorySpan` as satisfying the `view` and `borrowed_range` concepts.
27// This should be done before the definition of `MemorySpan`, so that any
28// inlined calls to range functionality use the correct specializations.
29template <typename T>
30inline constexpr bool std::ranges::enable_view<v8::MemorySpan<T>> = true;
31template <typename T>
32inline constexpr bool std::ranges::enable_borrowed_range<v8::MemorySpan<T>> =
33 true;
34
35namespace v8 {
36
47template <typename T>
49 private:
51 template <typename From, typename To>
52 using is_array_convertible = std::is_convertible<From (*)[], To (*)[]>;
53 template <typename From, typename To>
54 static constexpr bool is_array_convertible_v =
55 is_array_convertible<From, To>::value;
56
57 template <typename It>
58 using iter_reference_t = decltype(*std::declval<It&>());
59
60 template <typename It, typename = void>
61 struct is_compatible_iterator : std::false_type {};
62 template <typename It>
63 struct is_compatible_iterator<
64 It,
65 std::void_t<
66 std::is_base_of<std::random_access_iterator_tag,
67 typename std::iterator_traits<It>::iterator_category>,
68 is_array_convertible<std::remove_reference_t<iter_reference_t<It>>,
69 T>>> : std::true_type {};
70 template <typename It>
71 static constexpr bool is_compatible_iterator_v =
72 is_compatible_iterator<It>::value;
73
74 // SFINAE-compatible wrapper for `std::to_address()`.
75 // Adapted from "base/types/to_address.h" in chromium.
76 template <typename U>
77 requires(!std::is_function_v<U>)
78 [[nodiscard]] static constexpr U* to_address(U* p) noexcept {
79 return p;
80 }
81
82 template <typename It>
83 requires(
84 requires(const It& it) { std::pointer_traits<It>::to_address(it); } ||
85 requires(const It& it) { it.operator->(); })
86 [[nodiscard]] static constexpr auto to_address(const It& it) noexcept {
87 return std::to_address(it);
88 }
89
90 public:
92 constexpr MemorySpan() = default;
93
97 constexpr MemorySpan(std::nullptr_t, size_t) {}
98
100 template <typename Iterator,
101 std::enable_if_t<is_compatible_iterator_v<Iterator>, bool> = true>
102 constexpr MemorySpan(Iterator first,
103 size_t count) // NOLINT(runtime/explicit)
104 : data_(to_address(first)), size_(count) {}
105
107 template <typename Iterator,
108 std::enable_if_t<is_compatible_iterator_v<Iterator> &&
109 !std::is_convertible_v<Iterator, size_t>,
110 bool> = true>
111 constexpr MemorySpan(Iterator first,
112 Iterator last) // NOLINT(runtime/explicit)
113 : data_(to_address(first)), size_(last - first) {}
114
116 template <size_t N>
117 constexpr MemorySpan(T (&a)[N]) noexcept // NOLINT(runtime/explicit)
118 : data_(a), size_(N) {}
119
121 template <typename U, size_t N,
122 std::enable_if_t<is_array_convertible_v<U, T>, bool> = true>
123 constexpr MemorySpan(
124 std::array<U, N>& a) noexcept // NOLINT(runtime/explicit)
125 : data_(a.data()), size_{N} {}
126
128 template <typename U, size_t N,
129 std::enable_if_t<is_array_convertible_v<const U, T>, bool> = true>
130 constexpr MemorySpan(
131 const std::array<U, N>& a) noexcept // NOLINT(runtime/explicit)
132 : data_(a.data()), size_{N} {}
133
135 [[nodiscard]] constexpr T* data() const { return data_; }
137 [[nodiscard]] constexpr size_t size() const { return size_; }
138
139 [[nodiscard]] constexpr T& operator[](size_t i) const { return data_[i]; }
140
142 [[nodiscard]] constexpr bool empty() const { return size() == 0; }
143
144 class Iterator {
145 public:
146 using difference_type = std::ptrdiff_t;
147 using value_type = T;
150 using iterator_category = std::random_access_iterator_tag;
151 using iterator_concept = std::contiguous_iterator_tag;
152
153 // Required to satisfy `std::semiregular<>`.
154 constexpr Iterator() = default;
155
156 [[nodiscard]] constexpr bool operator==(const Iterator&) const = default;
157 [[nodiscard]] constexpr auto operator<=>(const Iterator&) const = default;
158
159 constexpr Iterator& operator++() {
160 ++ptr_;
161 return *this;
162 }
163
164 constexpr Iterator operator++(int) {
165 Iterator temp = *this;
166 ++*this;
167 return temp;
168 }
169
170 constexpr Iterator& operator--() {
171 --ptr_;
172 return *this;
173 }
174
175 constexpr Iterator operator--(int) {
176 Iterator temp = *this;
177 --*this;
178 return temp;
179 }
180
182 ptr_ += rhs;
183 return *this;
184 }
185
186 [[nodiscard]] friend constexpr Iterator operator+(Iterator lhs,
187 difference_type rhs) {
188 lhs += rhs;
189 return lhs;
190 }
191
192 [[nodiscard]] friend constexpr Iterator operator+(difference_type lhs,
193 const Iterator& rhs) {
194 return rhs + lhs;
195 }
196
198 ptr_ -= rhs;
199 return *this;
200 }
201
202 [[nodiscard]] friend constexpr Iterator operator-(Iterator lhs,
203 difference_type rhs) {
204 lhs -= rhs;
205 return lhs;
206 }
207
208 [[nodiscard]] friend constexpr difference_type operator-(
209 const Iterator& lhs, const Iterator& rhs) {
210 return lhs.ptr_ - rhs.ptr_;
211 }
212
213 [[nodiscard]] constexpr reference operator*() const { return *ptr_; }
214 [[nodiscard]] constexpr pointer operator->() const { return ptr_; }
215 [[nodiscard]] constexpr reference operator[](size_t offset) const {
216 return ptr_[offset];
217 }
218
219 private:
220 friend class MemorySpan<T>;
221
222 constexpr explicit Iterator(T* ptr) : ptr_(ptr) {}
223
224 T* ptr_ = nullptr;
225 };
226
227 [[nodiscard]] Iterator begin() const { return Iterator(data_); }
228 [[nodiscard]] Iterator end() const { return Iterator(data_ + size_); }
229
230 private:
231 T* data_ = nullptr;
232 size_t size_ = 0;
233};
234
246namespace detail {
247template <class T, std::size_t N, std::size_t... I>
248[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array_lvalue_impl(
249 T (&a)[N], std::index_sequence<I...>) {
250 return {{a[I]...}};
251}
252
253template <class T, std::size_t N, std::size_t... I>
254[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array_rvalue_impl(
255 T (&&a)[N], std::index_sequence<I...>) {
256 return {{std::move(a[I])...}};
257}
258} // namespace detail
259
260template <class T, std::size_t N>
261[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N]) {
262 return detail::to_array_lvalue_impl(a, std::make_index_sequence<N>{});
263}
264
265template <class T, std::size_t N>
266[[nodiscard]] constexpr std::array<std::remove_cv_t<T>, N> to_array(
267 T (&&a)[N]) {
268 return detail::to_array_rvalue_impl(std::move(a),
269 std::make_index_sequence<N>{});
270}
271
272} // namespace v8
273#endif // INCLUDE_V8_MEMORY_SPAN_H_
Definition: v8-memory-span.h:144
std::ptrdiff_t difference_type
Definition: v8-memory-span.h:146
friend constexpr difference_type operator-(const Iterator &lhs, const Iterator &rhs)
Definition: v8-memory-span.h:208
constexpr Iterator & operator+=(difference_type rhs)
Definition: v8-memory-span.h:181
friend constexpr Iterator operator+(Iterator lhs, difference_type rhs)
Definition: v8-memory-span.h:186
constexpr Iterator & operator++()
Definition: v8-memory-span.h:159
std::random_access_iterator_tag iterator_category
Definition: v8-memory-span.h:150
T value_type
Definition: v8-memory-span.h:147
constexpr Iterator()=default
value_type & reference
Definition: v8-memory-span.h:149
constexpr reference operator*() const
Definition: v8-memory-span.h:213
std::contiguous_iterator_tag iterator_concept
Definition: v8-memory-span.h:151
friend constexpr Iterator operator+(difference_type lhs, const Iterator &rhs)
Definition: v8-memory-span.h:192
constexpr bool operator==(const Iterator &) const =default
constexpr auto operator<=>(const Iterator &) const =default
constexpr Iterator operator--(int)
Definition: v8-memory-span.h:175
constexpr Iterator operator++(int)
Definition: v8-memory-span.h:164
value_type * pointer
Definition: v8-memory-span.h:148
constexpr Iterator & operator-=(difference_type rhs)
Definition: v8-memory-span.h:197
friend constexpr Iterator operator-(Iterator lhs, difference_type rhs)
Definition: v8-memory-span.h:202
constexpr Iterator & operator--()
Definition: v8-memory-span.h:170
constexpr pointer operator->() const
Definition: v8-memory-span.h:214
Definition: v8-memory-span.h:48
constexpr MemorySpan(std::nullptr_t, size_t)
Definition: v8-memory-span.h:97
Iterator end() const
Definition: v8-memory-span.h:228
constexpr MemorySpan(std::array< U, N > &a) noexcept
Definition: v8-memory-span.h:123
constexpr MemorySpan()=default
constexpr T & operator[](size_t i) const
Definition: v8-memory-span.h:139
constexpr MemorySpan(const std::array< U, N > &a) noexcept
Definition: v8-memory-span.h:130
constexpr MemorySpan(Iterator first, size_t count)
Definition: v8-memory-span.h:102
constexpr MemorySpan(T(&a)[N]) noexcept
Definition: v8-memory-span.h:117
constexpr T * data() const
Definition: v8-memory-span.h:135
constexpr MemorySpan(Iterator first, Iterator last)
Definition: v8-memory-span.h:111
constexpr bool empty() const
Definition: v8-memory-span.h:142
Iterator begin() const
Definition: v8-memory-span.h:227
constexpr size_t size() const
Definition: v8-memory-span.h:137
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:254
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:248
Definition: libplatform.h:15
constexpr std::array< std::remove_cv_t< T >, N > to_array(T(&a)[N])
Definition: v8-memory-span.h:261
#define V8_EXPORT
Definition: v8config.h:855