File indexing completed on 2025-08-28 08:27:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #pragma once
0019
0020 #include <cstddef>
0021 #include <cstdint>
0022 #include <cstring>
0023 #include <iterator>
0024 #include <type_traits>
0025
0026 namespace arrow::util {
0027
0028 template <class T>
0029 class span;
0030
0031
0032
0033
0034 template <typename T>
0035 class span {
0036 static_assert(sizeof(T),
0037 R"(
0038 std::span allows contiguous_iterators instead of just pointers, the enforcement
0039 of which requires T to be a complete type. arrow::util::span does not support
0040 contiguous_iterators, but T is still required to be a complete type to prevent
0041 writing code which would break when it is replaced by std::span.)");
0042
0043 public:
0044 using element_type = T;
0045 using value_type = std::remove_cv_t<T>;
0046 using iterator = T*;
0047 using const_iterator = T const*;
0048
0049 span() = default;
0050 span(const span&) = default;
0051 span& operator=(const span&) = default;
0052
0053 template <typename M, typename = std::enable_if_t<std::is_same_v<T, M const>>>
0054
0055 constexpr span(span<M> mut) : span{mut.data(), mut.size()} {}
0056
0057 constexpr span(T* data, size_t count) : data_{data}, size_{count} {}
0058
0059 constexpr span(T* begin, T* end)
0060 : data_{begin}, size_{static_cast<size_t>(end - begin)} {}
0061
0062 template <typename R, typename RD = decltype(std::data(std::declval<R>())),
0063 typename RS = decltype(std::size(std::declval<R>())),
0064 typename E = std::enable_if_t<std::is_constructible_v<T*, RD> &&
0065 std::is_constructible_v<size_t, RS>>>
0066
0067 constexpr span(R&& range) : data_{std::data(range)}, size_{std::size(range)} {}
0068
0069 constexpr T* begin() const { return data_; }
0070 constexpr T* end() const { return data_ + size_; }
0071 constexpr T* data() const { return data_; }
0072
0073 constexpr size_t size() const { return size_; }
0074 constexpr size_t size_bytes() const { return size_ * sizeof(T); }
0075 constexpr bool empty() const { return size_ == 0; }
0076
0077 constexpr T& operator[](size_t i) { return data_[i]; }
0078 constexpr const T& operator[](size_t i) const { return data_[i]; }
0079
0080 constexpr span subspan(size_t offset) const {
0081 if (offset > size_) return {data_, data_};
0082 return {data_ + offset, size_ - offset};
0083 }
0084
0085 constexpr span subspan(size_t offset, size_t count) const {
0086 auto out = subspan(offset);
0087 if (count < out.size_) {
0088 out.size_ = count;
0089 }
0090 return out;
0091 }
0092
0093 constexpr bool operator==(span const& other) const {
0094 if (size_ != other.size_) return false;
0095
0096 if constexpr (std::is_integral_v<T>) {
0097 if (size_ == 0) {
0098 return true;
0099 }
0100 return std::memcmp(data_, other.data_, size_bytes()) == 0;
0101 } else {
0102 T* ptr = data_;
0103 for (T const& e : other) {
0104 if (*ptr++ != e) return false;
0105 }
0106 return true;
0107 }
0108 }
0109 constexpr bool operator!=(span const& other) const { return !(*this == other); }
0110
0111 private:
0112 T* data_{};
0113 size_t size_{};
0114 };
0115
0116 template <typename R>
0117 span(R& range) -> span<std::remove_pointer_t<decltype(std::data(range))>>;
0118
0119 template <typename T>
0120 span(T*, size_t) -> span<T>;
0121
0122 template <typename T>
0123 constexpr span<std::byte const> as_bytes(span<T> s) {
0124 return {reinterpret_cast<std::byte const*>(s.data()), s.size_bytes()};
0125 }
0126
0127 template <typename T>
0128 constexpr span<std::byte> as_writable_bytes(span<T> s) {
0129 return {reinterpret_cast<std::byte*>(s.data()), s.size_bytes()};
0130 }
0131
0132 }