Warning: This file is not a C or C++ file. It does not have highlighting.
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 | |
55 | LIBC_INLINE constexpr span() : span_data(nullptr), span_size(0) {} |
56 | |
57 | LIBC_INLINE constexpr span(const span &) = default; |
58 | |
59 | LIBC_INLINE constexpr span(pointer first, size_type count) |
60 | : span_data(first), span_size(count) {} |
61 | |
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> |
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> |
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> |
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 | |
91 | LIBC_INLINE constexpr iterator begin() const { return data(); } |
92 | LIBC_INLINE constexpr iterator end() const { return data() + size(); } |
93 | LIBC_INLINE constexpr reference front() const { return (*this)[0]; } |
94 | LIBC_INLINE constexpr reference back() const { return (*this)[size() - 1]; } |
95 | LIBC_INLINE constexpr pointer data() const { return span_data; } |
96 | LIBC_INLINE constexpr size_type size() const { return span_size; } |
97 | LIBC_INLINE constexpr size_type size_bytes() const { |
98 | return sizeof(T) * size(); |
99 | } |
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 | |
107 | LIBC_INLINE constexpr span<element_type> first(size_type count) const { |
108 | return subspan(0, count); |
109 | } |
110 | |
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: |
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 |
Warning: This file is not a C or C++ file. It does not have highlighting.