1*bb722a7dSDimitry Andric //===-- Standalone implementation std::span ---------------------*- C++ -*-===// 2*bb722a7dSDimitry Andric // 3*bb722a7dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bb722a7dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bb722a7dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bb722a7dSDimitry Andric // 7*bb722a7dSDimitry Andric //===----------------------------------------------------------------------===// 8*bb722a7dSDimitry Andric #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H 9*bb722a7dSDimitry Andric #define LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H 10*bb722a7dSDimitry Andric 11*bb722a7dSDimitry Andric #include <stddef.h> // For size_t 12*bb722a7dSDimitry Andric 13*bb722a7dSDimitry Andric #include "array.h" // For array 14*bb722a7dSDimitry Andric #include "limits.h" 15*bb722a7dSDimitry Andric #include "src/__support/macros/config.h" 16*bb722a7dSDimitry Andric #include "type_traits.h" // For remove_cv_t, enable_if_t, is_same_v, is_const_v 17*bb722a7dSDimitry Andric 18*bb722a7dSDimitry Andric #include "src/__support/macros/attributes.h" 19*bb722a7dSDimitry Andric 20*bb722a7dSDimitry Andric namespace LIBC_NAMESPACE_DECL { 21*bb722a7dSDimitry Andric namespace cpp { 22*bb722a7dSDimitry Andric 23*bb722a7dSDimitry Andric // A trimmed down implementation of std::span. 24*bb722a7dSDimitry Andric // Missing features: 25*bb722a7dSDimitry Andric // - No constant size spans (e.g. Span<int, 4>), 26*bb722a7dSDimitry Andric // - Only handle pointer like types, no fancy interators nor object overriding 27*bb722a7dSDimitry Andric // the & operator, 28*bb722a7dSDimitry Andric // - No implicit type conversion (e.g. Span<B>, initialized with As where A 29*bb722a7dSDimitry Andric // inherits from B), 30*bb722a7dSDimitry Andric // - No reverse iterators 31*bb722a7dSDimitry Andric template <typename T> class span { 32*bb722a7dSDimitry Andric template <typename U> 33*bb722a7dSDimitry Andric LIBC_INLINE_VAR static constexpr bool is_const_view_v = 34*bb722a7dSDimitry Andric !cpp::is_const_v<U> && cpp::is_const_v<T> && 35*bb722a7dSDimitry Andric cpp::is_same_v<U, remove_cv_t<T>>; 36*bb722a7dSDimitry Andric 37*bb722a7dSDimitry Andric template <typename U> 38*bb722a7dSDimitry Andric LIBC_INLINE_VAR static constexpr bool is_compatible_v = 39*bb722a7dSDimitry Andric cpp::is_same_v<U, T> || is_const_view_v<U>; 40*bb722a7dSDimitry Andric 41*bb722a7dSDimitry Andric public: 42*bb722a7dSDimitry Andric using element_type = T; 43*bb722a7dSDimitry Andric using value_type = remove_cv_t<T>; 44*bb722a7dSDimitry Andric using size_type = size_t; 45*bb722a7dSDimitry Andric using difference_type = ptrdiff_t; 46*bb722a7dSDimitry Andric using pointer = T *; 47*bb722a7dSDimitry Andric using const_pointer = const T *; 48*bb722a7dSDimitry Andric using reference = T &; 49*bb722a7dSDimitry Andric using const_reference = const T &; 50*bb722a7dSDimitry Andric using iterator = T *; 51*bb722a7dSDimitry Andric 52*bb722a7dSDimitry Andric LIBC_INLINE_VAR static constexpr size_type dynamic_extent = 53*bb722a7dSDimitry Andric cpp::numeric_limits<size_type>::max(); 54*bb722a7dSDimitry Andric span()55*bb722a7dSDimitry Andric LIBC_INLINE constexpr span() : span_data(nullptr), span_size(0) {} 56*bb722a7dSDimitry Andric 57*bb722a7dSDimitry Andric LIBC_INLINE constexpr span(const span &) = default; 58*bb722a7dSDimitry Andric span(pointer first,size_type count)59*bb722a7dSDimitry Andric LIBC_INLINE constexpr span(pointer first, size_type count) 60*bb722a7dSDimitry Andric : span_data(first), span_size(count) {} 61*bb722a7dSDimitry Andric span(pointer first,pointer end)62*bb722a7dSDimitry Andric LIBC_INLINE constexpr span(pointer first, pointer end) 63*bb722a7dSDimitry Andric : span_data(first), span_size(static_cast<size_t>(end - first)) {} 64*bb722a7dSDimitry Andric 65*bb722a7dSDimitry Andric template <typename U, size_t N, 66*bb722a7dSDimitry Andric cpp::enable_if_t<is_compatible_v<U>, bool> = true> span(U (& arr)[N])67*bb722a7dSDimitry Andric LIBC_INLINE constexpr span(U (&arr)[N]) : span_data(arr), span_size(N) {} 68*bb722a7dSDimitry Andric 69*bb722a7dSDimitry Andric template <typename U, size_t N, 70*bb722a7dSDimitry Andric cpp::enable_if_t<is_compatible_v<U>, bool> = true> span(array<U,N> & arr)71*bb722a7dSDimitry Andric LIBC_INLINE constexpr span(array<U, N> &arr) 72*bb722a7dSDimitry Andric : span_data(arr.data()), span_size(arr.size()) {} 73*bb722a7dSDimitry Andric 74*bb722a7dSDimitry Andric template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true> span(span<U> & s)75*bb722a7dSDimitry Andric LIBC_INLINE constexpr span(span<U> &s) 76*bb722a7dSDimitry Andric : span_data(s.data()), span_size(s.size()) {} 77*bb722a7dSDimitry Andric 78*bb722a7dSDimitry Andric template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true> 79*bb722a7dSDimitry Andric LIBC_INLINE constexpr span &operator=(span<U> &s) { 80*bb722a7dSDimitry Andric span_data = s.data(); 81*bb722a7dSDimitry Andric span_size = s.size(); 82*bb722a7dSDimitry Andric return *this; 83*bb722a7dSDimitry Andric } 84*bb722a7dSDimitry Andric 85*bb722a7dSDimitry Andric LIBC_INLINE ~span() = default; 86*bb722a7dSDimitry Andric 87*bb722a7dSDimitry Andric LIBC_INLINE constexpr reference operator[](size_type index) const { 88*bb722a7dSDimitry Andric return data()[index]; 89*bb722a7dSDimitry Andric } 90*bb722a7dSDimitry Andric begin()91*bb722a7dSDimitry Andric LIBC_INLINE constexpr iterator begin() const { return data(); } end()92*bb722a7dSDimitry Andric LIBC_INLINE constexpr iterator end() const { return data() + size(); } front()93*bb722a7dSDimitry Andric LIBC_INLINE constexpr reference front() const { return (*this)[0]; } back()94*bb722a7dSDimitry Andric LIBC_INLINE constexpr reference back() const { return (*this)[size() - 1]; } data()95*bb722a7dSDimitry Andric LIBC_INLINE constexpr pointer data() const { return span_data; } size()96*bb722a7dSDimitry Andric LIBC_INLINE constexpr size_type size() const { return span_size; } size_bytes()97*bb722a7dSDimitry Andric LIBC_INLINE constexpr size_type size_bytes() const { 98*bb722a7dSDimitry Andric return sizeof(T) * size(); 99*bb722a7dSDimitry Andric } empty()100*bb722a7dSDimitry Andric LIBC_INLINE constexpr bool empty() const { return size() == 0; } 101*bb722a7dSDimitry Andric 102*bb722a7dSDimitry Andric LIBC_INLINE constexpr span<element_type> 103*bb722a7dSDimitry Andric subspan(size_type offset, size_type count = dynamic_extent) const { 104*bb722a7dSDimitry Andric return span<element_type>(data() + offset, count_to_size(offset, count)); 105*bb722a7dSDimitry Andric } 106*bb722a7dSDimitry Andric first(size_type count)107*bb722a7dSDimitry Andric LIBC_INLINE constexpr span<element_type> first(size_type count) const { 108*bb722a7dSDimitry Andric return subspan(0, count); 109*bb722a7dSDimitry Andric } 110*bb722a7dSDimitry Andric last(size_type count)111*bb722a7dSDimitry Andric LIBC_INLINE constexpr span<element_type> last(size_type count) const { 112*bb722a7dSDimitry Andric return span<element_type>(data() + (size() - count), count); 113*bb722a7dSDimitry Andric } 114*bb722a7dSDimitry Andric 115*bb722a7dSDimitry Andric private: count_to_size(size_type offset,size_type count)116*bb722a7dSDimitry Andric LIBC_INLINE constexpr size_type count_to_size(size_type offset, 117*bb722a7dSDimitry Andric size_type count) const { 118*bb722a7dSDimitry Andric if (count == dynamic_extent) { 119*bb722a7dSDimitry Andric return size() - offset; 120*bb722a7dSDimitry Andric } 121*bb722a7dSDimitry Andric return count; 122*bb722a7dSDimitry Andric } 123*bb722a7dSDimitry Andric 124*bb722a7dSDimitry Andric T *span_data; 125*bb722a7dSDimitry Andric size_t span_size; 126*bb722a7dSDimitry Andric }; 127*bb722a7dSDimitry Andric 128*bb722a7dSDimitry Andric } // namespace cpp 129*bb722a7dSDimitry Andric } // namespace LIBC_NAMESPACE_DECL 130*bb722a7dSDimitry Andric 131*bb722a7dSDimitry Andric #endif // LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H 132