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