File indexing completed on 2025-02-21 10:05:25
0001
0002
0003
0004
0005 #ifndef INCLUDE_V8_MEMORY_SPAN_H_
0006 #define INCLUDE_V8_MEMORY_SPAN_H_
0007
0008 #include <stddef.h>
0009
0010 #include <array>
0011 #include <iterator>
0012 #include <type_traits>
0013
0014 #include "v8config.h" // NOLINT(build/include_directory)
0015
0016 namespace v8 {
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 template <typename T>
0029 class V8_EXPORT MemorySpan {
0030 private:
0031
0032 template <typename From, typename To>
0033 using is_array_convertible = std::is_convertible<From (*)[], To (*)[]>;
0034 template <typename From, typename To>
0035 static constexpr bool is_array_convertible_v =
0036 is_array_convertible<From, To>::value;
0037
0038 template <typename It>
0039 using iter_reference_t = decltype(*std::declval<It&>());
0040
0041 template <typename It, typename = void>
0042 struct is_compatible_iterator : std::false_type {};
0043 template <typename It>
0044 struct is_compatible_iterator<
0045 It,
0046 std::void_t<
0047 std::is_base_of<std::random_access_iterator_tag,
0048 typename std::iterator_traits<It>::iterator_category>,
0049 is_array_convertible<std::remove_reference_t<iter_reference_t<It>>,
0050 T>>> : std::true_type {};
0051 template <typename It>
0052 static constexpr bool is_compatible_iterator_v =
0053 is_compatible_iterator<It>::value;
0054
0055 template <typename U>
0056 static constexpr U* to_address(U* p) noexcept {
0057 return p;
0058 }
0059
0060 template <typename It,
0061 typename = std::void_t<decltype(std::declval<It&>().operator->())>>
0062 static constexpr auto to_address(It it) noexcept {
0063 return it.operator->();
0064 }
0065
0066 public:
0067
0068 constexpr MemorySpan() = default;
0069
0070
0071
0072
0073 constexpr MemorySpan(std::nullptr_t, size_t) {}
0074
0075
0076 template <typename Iterator,
0077 std::enable_if_t<is_compatible_iterator_v<Iterator>, bool> = true>
0078 constexpr MemorySpan(Iterator first,
0079 size_t count)
0080 : data_(to_address(first)), size_(count) {}
0081
0082
0083 template <typename Iterator,
0084 std::enable_if_t<is_compatible_iterator_v<Iterator> &&
0085 !std::is_convertible_v<Iterator, size_t>,
0086 bool> = true>
0087 constexpr MemorySpan(Iterator first,
0088 Iterator last)
0089 : data_(to_address(first)), size_(last - first) {}
0090
0091
0092 template <size_t N>
0093 constexpr MemorySpan(T (&a)[N]) noexcept
0094 : data_(a), size_(N) {}
0095
0096
0097 template <typename U, size_t N,
0098 std::enable_if_t<is_array_convertible_v<U, T>, bool> = true>
0099 constexpr MemorySpan(
0100 std::array<U, N>& a) noexcept
0101 : data_(a.data()), size_{N} {}
0102
0103
0104 template <typename U, size_t N,
0105 std::enable_if_t<is_array_convertible_v<const U, T>, bool> = true>
0106 constexpr MemorySpan(
0107 const std::array<U, N>& a) noexcept
0108 : data_(a.data()), size_{N} {}
0109
0110
0111 constexpr T* data() const { return data_; }
0112
0113 constexpr size_t size() const { return size_; }
0114
0115 constexpr T& operator[](size_t i) const { return data_[i]; }
0116
0117
0118 constexpr bool empty() const { return size() == 0; }
0119
0120 class Iterator {
0121 public:
0122 using iterator_category = std::forward_iterator_tag;
0123 using value_type = T;
0124 using difference_type = std::ptrdiff_t;
0125 using pointer = value_type*;
0126 using reference = value_type&;
0127
0128 T& operator*() const { return *ptr_; }
0129 T* operator->() const { return ptr_; }
0130
0131 bool operator==(Iterator other) const { return ptr_ == other.ptr_; }
0132 bool operator!=(Iterator other) const { return !(*this == other); }
0133
0134 Iterator& operator++() {
0135 ++ptr_;
0136 return *this;
0137 }
0138
0139 Iterator operator++(int) {
0140 Iterator temp(*this);
0141 ++(*this);
0142 return temp;
0143 }
0144
0145 private:
0146 friend class MemorySpan<T>;
0147
0148 explicit Iterator(T* ptr) : ptr_(ptr) {}
0149
0150 T* ptr_ = nullptr;
0151 };
0152
0153 Iterator begin() const { return Iterator(data_); }
0154 Iterator end() const { return Iterator(data_ + size_); }
0155
0156 private:
0157 T* data_ = nullptr;
0158 size_t size_ = 0;
0159 };
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 namespace detail {
0173 template <class T, std::size_t N, std::size_t... I>
0174 constexpr std::array<std::remove_cv_t<T>, N> to_array_lvalue_impl(
0175 T (&a)[N], std::index_sequence<I...>) {
0176 return {{a[I]...}};
0177 }
0178
0179 template <class T, std::size_t N, std::size_t... I>
0180 constexpr std::array<std::remove_cv_t<T>, N> to_array_rvalue_impl(
0181 T (&&a)[N], std::index_sequence<I...>) {
0182 return {{std::move(a[I])...}};
0183 }
0184 }
0185
0186 template <class T, std::size_t N>
0187 constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N]) {
0188 return detail::to_array_lvalue_impl(a, std::make_index_sequence<N>{});
0189 }
0190
0191 template <class T, std::size_t N>
0192 constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&&a)[N]) {
0193 return detail::to_array_rvalue_impl(std::move(a),
0194 std::make_index_sequence<N>{});
0195 }
0196
0197 }
0198 #endif