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
18namespace 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
28template <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
38public:
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
109private:
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

source code of libc/src/__support/CPP/span.h