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