• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
span()51   LIBC_INLINE constexpr span() : span_data(nullptr), span_size(0) {}
52 
span(pointer first,size_type count)53   LIBC_INLINE constexpr span(pointer first, size_type count)
54       : span_data(first), span_size(count) {}
55 
span(pointer first,pointer end)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>
span(U (& arr)[N])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>
span(array<U,N> & arr)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>
span(span<U> & s)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 
begin()85   LIBC_INLINE constexpr iterator begin() const { return data(); }
end()86   LIBC_INLINE constexpr iterator end() const { return data() + size(); }
front()87   LIBC_INLINE constexpr reference front() const { return (*this)[0]; }
back()88   LIBC_INLINE constexpr reference back() const { return (*this)[size() - 1]; }
data()89   LIBC_INLINE constexpr pointer data() const { return span_data; }
size()90   LIBC_INLINE constexpr size_type size() const { return span_size; }
size_bytes()91   LIBC_INLINE constexpr size_type size_bytes() const {
92     return sizeof(T) * size();
93   }
empty()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 
first(size_type count)101   LIBC_INLINE constexpr span<element_type> first(size_type count) const {
102     return subspan(0, count);
103   }
104 
last(size_type count)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:
count_to_size(size_type offset,size_type count)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