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