/src/boringssl/include/openssl/span.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2017 The BoringSSL Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #ifndef OPENSSL_HEADER_SSL_SPAN_H |
16 | | #define OPENSSL_HEADER_SSL_SPAN_H |
17 | | |
18 | | #include <openssl/base.h> // IWYU pragma: export |
19 | | |
20 | | #if !defined(BORINGSSL_NO_CXX) |
21 | | |
22 | | extern "C++" { |
23 | | |
24 | | #include <stdlib.h> |
25 | | |
26 | | #include <algorithm> |
27 | | #include <string_view> |
28 | | #include <type_traits> |
29 | | |
30 | | #if __has_include(<version>) |
31 | | #include <version> |
32 | | #endif |
33 | | |
34 | | #if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L |
35 | | #include <ranges> |
36 | | BSSL_NAMESPACE_BEGIN |
37 | | template <typename T> |
38 | | class Span; |
39 | | BSSL_NAMESPACE_END |
40 | | |
41 | | // Mark `Span` as satisfying the `view` and `borrowed_range` concepts. This |
42 | | // should be done before the definition of `Span`, so that any inlined calls to |
43 | | // range functionality use the correct specializations. |
44 | | template <typename T> |
45 | | inline constexpr bool std::ranges::enable_view<bssl::Span<T>> = true; |
46 | | template <typename T> |
47 | | inline constexpr bool std::ranges::enable_borrowed_range<bssl::Span<T>> = true; |
48 | | #endif |
49 | | |
50 | | BSSL_NAMESPACE_BEGIN |
51 | | |
52 | | template <typename T> |
53 | | class Span; |
54 | | |
55 | | namespace internal { |
56 | | template <typename T> |
57 | | class SpanBase { |
58 | | // Put comparison operator implementations into a base class with const T, so |
59 | | // they can be used with any type that implicitly converts into a Span. |
60 | | static_assert(std::is_const<T>::value, |
61 | | "Span<T> must be derived from SpanBase<const T>"); |
62 | | |
63 | 0 | friend bool operator==(Span<T> lhs, Span<T> rhs) { |
64 | 0 | return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); |
65 | 0 | } |
66 | | |
67 | 0 | friend bool operator!=(Span<T> lhs, Span<T> rhs) { return !(lhs == rhs); } |
68 | | }; |
69 | | |
70 | | // Heuristically test whether C is a container type that can be converted into |
71 | | // a Span<T> by checking for data() and size() member functions. |
72 | | template <typename C, typename T> |
73 | | using EnableIfContainer = std::enable_if_t< |
74 | | std::is_convertible_v<decltype(std::declval<C>().data()), T *> && |
75 | | std::is_integral_v<decltype(std::declval<C>().size())>>; |
76 | | |
77 | | } // namespace internal |
78 | | |
79 | | // A Span<T> is a non-owning reference to a contiguous array of objects of type |
80 | | // |T|. Conceptually, a Span is a simple a pointer to |T| and a count of |
81 | | // elements accessible via that pointer. The elements referenced by the Span can |
82 | | // be mutated if |T| is mutable. |
83 | | // |
84 | | // A Span can be constructed from container types implementing |data()| and |
85 | | // |size()| methods. If |T| is constant, construction from a container type is |
86 | | // implicit. This allows writing methods that accept data from some unspecified |
87 | | // container type: |
88 | | // |
89 | | // // Foo views data referenced by v. |
90 | | // void Foo(bssl::Span<const uint8_t> v) { ... } |
91 | | // |
92 | | // std::vector<uint8_t> vec; |
93 | | // Foo(vec); |
94 | | // |
95 | | // For mutable Spans, conversion is explicit: |
96 | | // |
97 | | // // FooMutate mutates data referenced by v. |
98 | | // void FooMutate(bssl::Span<uint8_t> v) { ... } |
99 | | // |
100 | | // FooMutate(bssl::Span<uint8_t>(vec)); |
101 | | // |
102 | | // You can also use C++17 class template argument deduction to construct Spans |
103 | | // in order to deduce the type of the Span automatically. |
104 | | // |
105 | | // FooMutate(bssl::Span(vec)); |
106 | | // |
107 | | // Note that Spans have value type sematics. They are cheap to construct and |
108 | | // copy, and should be passed by value whenever a method would otherwise accept |
109 | | // a reference or pointer to a container or array. |
110 | | template <typename T> |
111 | | class Span : private internal::SpanBase<const T> { |
112 | | public: |
113 | | static const size_t npos = static_cast<size_t>(-1); |
114 | | |
115 | | using element_type = T; |
116 | | using value_type = std::remove_cv_t<T>; |
117 | | using size_type = size_t; |
118 | | using difference_type = ptrdiff_t; |
119 | | using pointer = T *; |
120 | | using const_pointer = const T *; |
121 | | using reference = T &; |
122 | | using const_reference = const T &; |
123 | | using iterator = T *; |
124 | | using const_iterator = const T *; |
125 | | |
126 | 0 | constexpr Span() : Span(nullptr, 0) {} Unexecuted instantiation: bssl::Span<char const*>::Span() Unexecuted instantiation: bssl::Span<unsigned char const>::Span() Unexecuted instantiation: bssl::Span<unsigned short const>::Span() Unexecuted instantiation: bssl::Span<char const>::Span() Unexecuted instantiation: bssl::Span<unsigned char>::Span() |
127 | 28.1k | constexpr Span(T *ptr, size_t len) : data_(ptr), size_(len) {} bssl::Span<unsigned char const>::Span(unsigned char const*, unsigned long) Line | Count | Source | 127 | 28.1k | constexpr Span(T *ptr, size_t len) : data_(ptr), size_(len) {} |
Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::Span(ssl_cipher_st const*, unsigned long) Unexecuted instantiation: bssl::Span<bool const>::Span(bool const*, unsigned long) Unexecuted instantiation: bssl::Span<char const*>::Span(char const**, unsigned long) Unexecuted instantiation: bssl::Span<unsigned char>::Span(unsigned char*, unsigned long) Unexecuted instantiation: bssl::Span<unsigned short const>::Span(unsigned short const*, unsigned long) Unexecuted instantiation: bssl::Span<int const>::Span(int const*, unsigned long) Unexecuted instantiation: bssl::Span<char const* const>::Span(char const* const*, unsigned long) Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::Span(SignatureAlgorithmName const*, unsigned long) Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::Span(bssl::VersionInfo const*, unsigned long) Unexecuted instantiation: bssl::Span<char const>::Span(char const*, unsigned long) Unexecuted instantiation: bssl::Span<unsigned short>::Span(unsigned short*, unsigned long) Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::Span(bssl::NamedGroup const*, unsigned long) |
128 | | |
129 | | template <size_t N> |
130 | 0 | constexpr Span(T (&array)[N]) : Span(array, N) {} Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::Span<24ul>(ssl_cipher_st const (&) [24ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<32ul>(unsigned char const (&) [32ul]) Unexecuted instantiation: bssl::Span<char const* const>::Span<3ul>(char const* const (&) [3ul]) Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::Span<14ul>(SignatureAlgorithmName const (&) [14ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<4ul>(unsigned char const (&) [4ul]) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<3ul>(unsigned short const (&) [3ul]) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<4ul>(unsigned short const (&) [4ul]) Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::Span<7ul>(bssl::VersionInfo const (&) [7ul]) Unexecuted instantiation: bssl::Span<char const>::Span<34ul>(char const (&) [34ul]) Unexecuted instantiation: bssl::Span<char const>::Span<20ul>(char const (&) [20ul]) Unexecuted instantiation: bssl::Span<unsigned char>::Span<8ul>(unsigned char (&) [8ul]) Unexecuted instantiation: bssl::Span<unsigned char>::Span<80ul>(unsigned char (&) [80ul]) Unexecuted instantiation: bssl::Span<unsigned char>::Span<24ul>(unsigned char (&) [24ul]) Unexecuted instantiation: bssl::Span<unsigned char>::Span<32ul>(unsigned char (&) [32ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<1ul>(unsigned char const (&) [1ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<2ul>(unsigned char const (&) [2ul]) Unexecuted instantiation: bssl::Span<unsigned char>::Span<2ul>(unsigned char (&) [2ul]) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<9ul>(unsigned short const (&) [9ul]) Unexecuted instantiation: bssl::Span<unsigned char>::Span<65ul>(unsigned char (&) [65ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<16ul>(unsigned char const (&) [16ul]) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<2ul>(unsigned short const (&) [2ul]) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<12ul>(unsigned short const (&) [12ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<8ul>(unsigned char const (&) [8ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<6ul>(unsigned char const (&) [6ul]) Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::Span<6ul>(bssl::NamedGroup const (&) [6ul]) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<65ul>(unsigned char const (&) [65ul]) |
131 | | |
132 | | template <typename C, typename = internal::EnableIfContainer<C, T>, |
133 | | typename = std::enable_if_t<std::is_const<T>::value, C>> |
134 | | constexpr Span(const C &container) |
135 | 2 | : data_(container.data()), size_(container.size()) {} bssl::Span<bool const>::Span<bssl::Array<bool>, void, bssl::Array<bool> >(bssl::Array<bool> const&) Line | Count | Source | 135 | 2 | : data_(container.data()), size_(container.size()) {} |
Unexecuted instantiation: bssl::Span<char const* const>::Span<bssl::Span<char const*>, void, bssl::Span<char const*> >(bssl::Span<char const*> const&) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::InplaceVector<unsigned char, 48ul>, void, bssl::InplaceVector<unsigned char, 48ul> >(bssl::InplaceVector<unsigned char, 48ul> const&) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::InplaceVector<unsigned char, 32ul>, void, bssl::InplaceVector<unsigned char, 32ul> >(bssl::InplaceVector<unsigned char, 32ul> const&) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<bssl::Array<unsigned short>, void, bssl::Array<unsigned short> >(bssl::Array<unsigned short> const&) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::Array<unsigned char>, void, bssl::Array<unsigned char> >(bssl::Array<unsigned char> const&) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::InplaceVector<unsigned char, 12ul>, void, bssl::InplaceVector<unsigned char, 12ul> >(bssl::InplaceVector<unsigned char, 12ul> const&) Unexecuted instantiation: bssl::Span<unsigned char const>::Span<bssl::Span<unsigned char>, void, bssl::Span<unsigned char> >(bssl::Span<unsigned char> const&) Unexecuted instantiation: bssl::Span<unsigned short const>::Span<bssl::Span<unsigned short>, void, bssl::Span<unsigned short> >(bssl::Span<unsigned short> const&) |
136 | | |
137 | | template <typename C, typename = internal::EnableIfContainer<C, T>, |
138 | | typename = std::enable_if_t<!std::is_const<T>::value, C>> |
139 | | constexpr explicit Span(C &container) |
140 | 0 | : data_(container.data()), size_(container.size()) {} Unexecuted instantiation: bssl::Span<unsigned char>::Span<bssl::Array<unsigned char>, void, bssl::Array<unsigned char> >(bssl::Array<unsigned char>&) Unexecuted instantiation: bssl::Span<unsigned char>::Span<bssl::InplaceVector<unsigned char, 48ul>, void, bssl::InplaceVector<unsigned char, 48ul> >(bssl::InplaceVector<unsigned char, 48ul>&) |
141 | | |
142 | 0 | constexpr T *data() const { return data_; } Unexecuted instantiation: bssl::Span<unsigned char const>::data() const Unexecuted instantiation: bssl::Span<char const*>::data() const Unexecuted instantiation: bssl::Span<unsigned char>::data() const Unexecuted instantiation: bssl::Span<unsigned short const>::data() const Unexecuted instantiation: bssl::Span<char const>::data() const Unexecuted instantiation: bssl::Span<unsigned short>::data() const |
143 | 41.6k | constexpr size_t size() const { return size_; } bssl::Span<unsigned char const>::size() const Line | Count | Source | 143 | 41.6k | constexpr size_t size() const { return size_; } |
Unexecuted instantiation: bssl::Span<char const* const>::size() const Unexecuted instantiation: bssl::Span<char const*>::size() const bssl::Span<bool const>::size() const Line | Count | Source | 143 | 4 | constexpr size_t size() const { return size_; } |
Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::size() const Unexecuted instantiation: bssl::Span<unsigned char>::size() const Unexecuted instantiation: bssl::Span<int const>::size() const Unexecuted instantiation: bssl::Span<unsigned short const>::size() const Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::size() const Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::size() const Unexecuted instantiation: bssl::Span<char const>::size() const Unexecuted instantiation: bssl::Span<unsigned short>::size() const Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::size() const |
144 | 0 | constexpr bool empty() const { return size_ == 0; } Unexecuted instantiation: bssl::Span<char const*>::empty() const Unexecuted instantiation: bssl::Span<unsigned char>::empty() const Unexecuted instantiation: bssl::Span<unsigned char const>::empty() const Unexecuted instantiation: bssl::Span<unsigned short const>::empty() const |
145 | | |
146 | 28.1k | constexpr iterator begin() const { return data_; } bssl::Span<unsigned char const>::begin() const Line | Count | Source | 146 | 28.1k | constexpr iterator begin() const { return data_; } |
bssl::Span<bool const>::begin() const Line | Count | Source | 146 | 2 | constexpr iterator begin() const { return data_; } |
Unexecuted instantiation: bssl::Span<unsigned short const>::begin() const |
147 | | constexpr const_iterator cbegin() const { return data_; } |
148 | 28.1k | constexpr iterator end() const { return data_ + size_; } bssl::Span<unsigned char const>::end() const Line | Count | Source | 148 | 28.1k | constexpr iterator end() const { return data_ + size_; } |
bssl::Span<bool const>::end() const Line | Count | Source | 148 | 2 | constexpr iterator end() const { return data_ + size_; } |
Unexecuted instantiation: bssl::Span<unsigned short const>::end() const |
149 | | constexpr const_iterator cend() const { return end(); } |
150 | | |
151 | 0 | constexpr T &front() const { |
152 | 0 | if (size_ == 0) { |
153 | 0 | abort(); |
154 | 0 | } |
155 | 0 | return data_[0]; |
156 | 0 | } |
157 | 0 | constexpr T &back() const { |
158 | 0 | if (size_ == 0) { |
159 | 0 | abort(); |
160 | 0 | } |
161 | 0 | return data_[size_ - 1]; |
162 | 0 | } Unexecuted instantiation: bssl::Span<unsigned char>::back() const Unexecuted instantiation: bssl::Span<unsigned char const>::back() const |
163 | | |
164 | 0 | constexpr T &operator[](size_t i) const { |
165 | 0 | if (i >= size_) { |
166 | 0 | abort(); |
167 | 0 | } |
168 | 0 | return data_[i]; |
169 | 0 | } Unexecuted instantiation: bssl::Span<char const*>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<char const* const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<ssl_cipher_st const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<int const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<SignatureAlgorithmName const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<unsigned char const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<bssl::VersionInfo const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<unsigned char>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<unsigned short const>::operator[](unsigned long) const Unexecuted instantiation: bssl::Span<bssl::NamedGroup const>::operator[](unsigned long) const |
170 | | T &at(size_t i) const { return (*this)[i]; } |
171 | | |
172 | 0 | constexpr Span subspan(size_t pos = 0, size_t len = npos) const { |
173 | 0 | if (pos > size_) { |
174 | | // absl::Span throws an exception here. Note std::span and Chromium |
175 | | // base::span additionally forbid pos + len being out of range, with a |
176 | | // special case at npos/dynamic_extent, while absl::Span::subspan clips |
177 | | // the span. For now, we align with absl::Span in case we switch to it in |
178 | | // the future. |
179 | 0 | abort(); |
180 | 0 | } |
181 | 0 | return Span(data_ + pos, std::min(size_ - pos, len)); |
182 | 0 | } Unexecuted instantiation: bssl::Span<char const*>::subspan(unsigned long, unsigned long) const Unexecuted instantiation: bssl::Span<unsigned char>::subspan(unsigned long, unsigned long) const Unexecuted instantiation: bssl::Span<unsigned char const>::subspan(unsigned long, unsigned long) const |
183 | | |
184 | 0 | constexpr Span first(size_t len) const { |
185 | 0 | if (len > size_) { |
186 | 0 | abort(); |
187 | 0 | } |
188 | 0 | return Span(data_, len); |
189 | 0 | } Unexecuted instantiation: bssl::Span<unsigned char>::first(unsigned long) const Unexecuted instantiation: bssl::Span<unsigned char const>::first(unsigned long) const |
190 | | |
191 | 0 | constexpr Span last(size_t len) const { |
192 | 0 | if (len > size_) { |
193 | 0 | abort(); |
194 | 0 | } |
195 | 0 | return Span(data_ + size_ - len, len); |
196 | 0 | } Unexecuted instantiation: bssl::Span<unsigned char>::last(unsigned long) const Unexecuted instantiation: bssl::Span<unsigned char const>::last(unsigned long) const |
197 | | |
198 | | private: |
199 | | T *data_; |
200 | | size_t size_; |
201 | | }; |
202 | | |
203 | | template <typename T> |
204 | | const size_t Span<T>::npos; |
205 | | |
206 | | template <typename T> |
207 | | Span(T *, size_t) -> Span<T>; |
208 | | template <typename T, size_t size> |
209 | | Span(T (&array)[size]) -> Span<T>; |
210 | | template < |
211 | | typename C, |
212 | | typename T = std::remove_pointer_t<decltype(std::declval<C>().data())>, |
213 | | typename = internal::EnableIfContainer<C, T>> |
214 | | Span(C &) -> Span<T>; |
215 | | |
216 | | template <typename T> |
217 | | constexpr Span<T> MakeSpan(T *ptr, size_t size) { |
218 | | return Span<T>(ptr, size); |
219 | | } |
220 | | |
221 | | template <typename C> |
222 | | constexpr auto MakeSpan(C &c) -> decltype(MakeSpan(c.data(), c.size())) { |
223 | | return MakeSpan(c.data(), c.size()); |
224 | | } |
225 | | |
226 | | template <typename T, size_t N> |
227 | | constexpr Span<T> MakeSpan(T (&array)[N]) { |
228 | | return Span<T>(array, N); |
229 | | } |
230 | | |
231 | | template <typename T> |
232 | 0 | constexpr Span<const T> MakeConstSpan(T *ptr, size_t size) { |
233 | 0 | return Span<const T>(ptr, size); |
234 | 0 | } Unexecuted instantiation: bssl::Span<unsigned char const> bssl::MakeConstSpan<unsigned char const>(unsigned char const*, unsigned long) Unexecuted instantiation: bssl::Span<unsigned char const> bssl::MakeConstSpan<unsigned char>(unsigned char*, unsigned long) |
235 | | |
236 | | template <typename C> |
237 | | constexpr auto MakeConstSpan(const C &c) |
238 | | -> decltype(MakeConstSpan(c.data(), c.size())) { |
239 | | return MakeConstSpan(c.data(), c.size()); |
240 | | } |
241 | | |
242 | | template <typename T, size_t size> |
243 | | constexpr Span<const T> MakeConstSpan(T (&array)[size]) { |
244 | | return array; |
245 | | } |
246 | | |
247 | 0 | inline Span<const uint8_t> StringAsBytes(std::string_view s) { |
248 | 0 | return MakeConstSpan(reinterpret_cast<const uint8_t *>(s.data()), s.size()); |
249 | 0 | } |
250 | | |
251 | 0 | inline std::string_view BytesAsStringView(bssl::Span<const uint8_t> b) { |
252 | 0 | return std::string_view(reinterpret_cast<const char *>(b.data()), b.size()); |
253 | 0 | } |
254 | | |
255 | | BSSL_NAMESPACE_END |
256 | | |
257 | | } // extern C++ |
258 | | |
259 | | #endif // !defined(BORINGSSL_NO_CXX) |
260 | | |
261 | | #endif // OPENSSL_HEADER_SSL_SPAN_H |