xref: /aosp_15_r20/external/boringssl/src/include/openssl/span.h (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (c) 2017, Google Inc.
2*8fb009dcSAndroid Build Coastguard Worker  *
3*8fb009dcSAndroid Build Coastguard Worker  * Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker  * purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker  * copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker  *
7*8fb009dcSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14*8fb009dcSAndroid Build Coastguard Worker 
15*8fb009dcSAndroid Build Coastguard Worker #ifndef OPENSSL_HEADER_SSL_SPAN_H
16*8fb009dcSAndroid Build Coastguard Worker #define OPENSSL_HEADER_SSL_SPAN_H
17*8fb009dcSAndroid Build Coastguard Worker 
18*8fb009dcSAndroid Build Coastguard Worker #include <openssl/base.h>
19*8fb009dcSAndroid Build Coastguard Worker 
20*8fb009dcSAndroid Build Coastguard Worker #if !defined(BORINGSSL_NO_CXX)
21*8fb009dcSAndroid Build Coastguard Worker 
22*8fb009dcSAndroid Build Coastguard Worker extern "C++" {
23*8fb009dcSAndroid Build Coastguard Worker 
24*8fb009dcSAndroid Build Coastguard Worker #include <stdlib.h>
25*8fb009dcSAndroid Build Coastguard Worker 
26*8fb009dcSAndroid Build Coastguard Worker #include <algorithm>
27*8fb009dcSAndroid Build Coastguard Worker #include <type_traits>
28*8fb009dcSAndroid Build Coastguard Worker 
29*8fb009dcSAndroid Build Coastguard Worker #if __cplusplus >= 201703L
30*8fb009dcSAndroid Build Coastguard Worker #include <string_view>
31*8fb009dcSAndroid Build Coastguard Worker #endif
32*8fb009dcSAndroid Build Coastguard Worker 
33*8fb009dcSAndroid Build Coastguard Worker BSSL_NAMESPACE_BEGIN
34*8fb009dcSAndroid Build Coastguard Worker 
35*8fb009dcSAndroid Build Coastguard Worker template <typename T>
36*8fb009dcSAndroid Build Coastguard Worker class Span;
37*8fb009dcSAndroid Build Coastguard Worker 
38*8fb009dcSAndroid Build Coastguard Worker namespace internal {
39*8fb009dcSAndroid Build Coastguard Worker template <typename T>
40*8fb009dcSAndroid Build Coastguard Worker class SpanBase {
41*8fb009dcSAndroid Build Coastguard Worker   // Put comparison operator implementations into a base class with const T, so
42*8fb009dcSAndroid Build Coastguard Worker   // they can be used with any type that implicitly converts into a Span.
43*8fb009dcSAndroid Build Coastguard Worker   static_assert(std::is_const<T>::value,
44*8fb009dcSAndroid Build Coastguard Worker                 "Span<T> must be derived from SpanBase<const T>");
45*8fb009dcSAndroid Build Coastguard Worker 
46*8fb009dcSAndroid Build Coastguard Worker   friend bool operator==(Span<T> lhs, Span<T> rhs) {
47*8fb009dcSAndroid Build Coastguard Worker     return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
48*8fb009dcSAndroid Build Coastguard Worker   }
49*8fb009dcSAndroid Build Coastguard Worker 
50*8fb009dcSAndroid Build Coastguard Worker   friend bool operator!=(Span<T> lhs, Span<T> rhs) { return !(lhs == rhs); }
51*8fb009dcSAndroid Build Coastguard Worker };
52*8fb009dcSAndroid Build Coastguard Worker 
53*8fb009dcSAndroid Build Coastguard Worker // Heuristically test whether C is a container type that can be converted into
54*8fb009dcSAndroid Build Coastguard Worker // a Span<T> by checking for data() and size() member functions.
55*8fb009dcSAndroid Build Coastguard Worker //
56*8fb009dcSAndroid Build Coastguard Worker // TODO(davidben): Require C++17 support for std::is_convertible_v, etc.
57*8fb009dcSAndroid Build Coastguard Worker template <typename C, typename T>
58*8fb009dcSAndroid Build Coastguard Worker using EnableIfContainer = std::enable_if_t<
59*8fb009dcSAndroid Build Coastguard Worker     std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
60*8fb009dcSAndroid Build Coastguard Worker     std::is_integral<decltype(std::declval<C>().size())>::value>;
61*8fb009dcSAndroid Build Coastguard Worker 
62*8fb009dcSAndroid Build Coastguard Worker }  // namespace internal
63*8fb009dcSAndroid Build Coastguard Worker 
64*8fb009dcSAndroid Build Coastguard Worker // A Span<T> is a non-owning reference to a contiguous array of objects of type
65*8fb009dcSAndroid Build Coastguard Worker // |T|. Conceptually, a Span is a simple a pointer to |T| and a count of
66*8fb009dcSAndroid Build Coastguard Worker // elements accessible via that pointer. The elements referenced by the Span can
67*8fb009dcSAndroid Build Coastguard Worker // be mutated if |T| is mutable.
68*8fb009dcSAndroid Build Coastguard Worker //
69*8fb009dcSAndroid Build Coastguard Worker // A Span can be constructed from container types implementing |data()| and
70*8fb009dcSAndroid Build Coastguard Worker // |size()| methods. If |T| is constant, construction from a container type is
71*8fb009dcSAndroid Build Coastguard Worker // implicit. This allows writing methods that accept data from some unspecified
72*8fb009dcSAndroid Build Coastguard Worker // container type:
73*8fb009dcSAndroid Build Coastguard Worker //
74*8fb009dcSAndroid Build Coastguard Worker // // Foo views data referenced by v.
75*8fb009dcSAndroid Build Coastguard Worker // void Foo(bssl::Span<const uint8_t> v) { ... }
76*8fb009dcSAndroid Build Coastguard Worker //
77*8fb009dcSAndroid Build Coastguard Worker // std::vector<uint8_t> vec;
78*8fb009dcSAndroid Build Coastguard Worker // Foo(vec);
79*8fb009dcSAndroid Build Coastguard Worker //
80*8fb009dcSAndroid Build Coastguard Worker // For mutable Spans, conversion is explicit:
81*8fb009dcSAndroid Build Coastguard Worker //
82*8fb009dcSAndroid Build Coastguard Worker // // FooMutate mutates data referenced by v.
83*8fb009dcSAndroid Build Coastguard Worker // void FooMutate(bssl::Span<uint8_t> v) { ... }
84*8fb009dcSAndroid Build Coastguard Worker //
85*8fb009dcSAndroid Build Coastguard Worker // FooMutate(bssl::Span<uint8_t>(vec));
86*8fb009dcSAndroid Build Coastguard Worker //
87*8fb009dcSAndroid Build Coastguard Worker // You can also use the |MakeSpan| and |MakeConstSpan| factory methods to
88*8fb009dcSAndroid Build Coastguard Worker // construct Spans in order to deduce the type of the Span automatically.
89*8fb009dcSAndroid Build Coastguard Worker //
90*8fb009dcSAndroid Build Coastguard Worker // FooMutate(bssl::MakeSpan(vec));
91*8fb009dcSAndroid Build Coastguard Worker //
92*8fb009dcSAndroid Build Coastguard Worker // Note that Spans have value type sematics. They are cheap to construct and
93*8fb009dcSAndroid Build Coastguard Worker // copy, and should be passed by value whenever a method would otherwise accept
94*8fb009dcSAndroid Build Coastguard Worker // a reference or pointer to a container or array.
95*8fb009dcSAndroid Build Coastguard Worker template <typename T>
96*8fb009dcSAndroid Build Coastguard Worker class Span : private internal::SpanBase<const T> {
97*8fb009dcSAndroid Build Coastguard Worker  public:
98*8fb009dcSAndroid Build Coastguard Worker   static const size_t npos = static_cast<size_t>(-1);
99*8fb009dcSAndroid Build Coastguard Worker 
100*8fb009dcSAndroid Build Coastguard Worker   using element_type = T;
101*8fb009dcSAndroid Build Coastguard Worker   using value_type = std::remove_cv_t<T>;
102*8fb009dcSAndroid Build Coastguard Worker   using size_type = size_t;
103*8fb009dcSAndroid Build Coastguard Worker   using difference_type = ptrdiff_t;
104*8fb009dcSAndroid Build Coastguard Worker   using pointer = T *;
105*8fb009dcSAndroid Build Coastguard Worker   using const_pointer = const T *;
106*8fb009dcSAndroid Build Coastguard Worker   using reference = T &;
107*8fb009dcSAndroid Build Coastguard Worker   using const_reference = const T &;
108*8fb009dcSAndroid Build Coastguard Worker   using iterator = T *;
109*8fb009dcSAndroid Build Coastguard Worker   using const_iterator = const T *;
110*8fb009dcSAndroid Build Coastguard Worker 
Span()111*8fb009dcSAndroid Build Coastguard Worker   constexpr Span() : Span(nullptr, 0) {}
Span(T * ptr,size_t len)112*8fb009dcSAndroid Build Coastguard Worker   constexpr Span(T *ptr, size_t len) : data_(ptr), size_(len) {}
113*8fb009dcSAndroid Build Coastguard Worker 
114*8fb009dcSAndroid Build Coastguard Worker   template <size_t N>
Span(T (& array)[N])115*8fb009dcSAndroid Build Coastguard Worker   constexpr Span(T (&array)[N]) : Span(array, N) {}
116*8fb009dcSAndroid Build Coastguard Worker 
117*8fb009dcSAndroid Build Coastguard Worker   template <typename C, typename = internal::EnableIfContainer<C, T>,
118*8fb009dcSAndroid Build Coastguard Worker             typename = std::enable_if_t<std::is_const<T>::value, C>>
Span(const C & container)119*8fb009dcSAndroid Build Coastguard Worker   constexpr Span(const C &container)
120*8fb009dcSAndroid Build Coastguard Worker       : data_(container.data()), size_(container.size()) {}
121*8fb009dcSAndroid Build Coastguard Worker 
122*8fb009dcSAndroid Build Coastguard Worker   template <typename C, typename = internal::EnableIfContainer<C, T>,
123*8fb009dcSAndroid Build Coastguard Worker             typename = std::enable_if_t<!std::is_const<T>::value, C>>
Span(C & container)124*8fb009dcSAndroid Build Coastguard Worker   constexpr explicit Span(C &container)
125*8fb009dcSAndroid Build Coastguard Worker       : data_(container.data()), size_(container.size()) {}
126*8fb009dcSAndroid Build Coastguard Worker 
data()127*8fb009dcSAndroid Build Coastguard Worker   constexpr T *data() const { return data_; }
size()128*8fb009dcSAndroid Build Coastguard Worker   constexpr size_t size() const { return size_; }
empty()129*8fb009dcSAndroid Build Coastguard Worker   constexpr bool empty() const { return size_ == 0; }
130*8fb009dcSAndroid Build Coastguard Worker 
begin()131*8fb009dcSAndroid Build Coastguard Worker   constexpr iterator begin() const { return data_; }
cbegin()132*8fb009dcSAndroid Build Coastguard Worker   constexpr const_iterator cbegin() const { return data_; }
end()133*8fb009dcSAndroid Build Coastguard Worker   constexpr iterator end() const { return data_ + size_; }
cend()134*8fb009dcSAndroid Build Coastguard Worker   constexpr const_iterator cend() const { return end(); }
135*8fb009dcSAndroid Build Coastguard Worker 
front()136*8fb009dcSAndroid Build Coastguard Worker   constexpr T &front() const {
137*8fb009dcSAndroid Build Coastguard Worker     if (size_ == 0) {
138*8fb009dcSAndroid Build Coastguard Worker       abort();
139*8fb009dcSAndroid Build Coastguard Worker     }
140*8fb009dcSAndroid Build Coastguard Worker     return data_[0];
141*8fb009dcSAndroid Build Coastguard Worker   }
back()142*8fb009dcSAndroid Build Coastguard Worker   constexpr T &back() const {
143*8fb009dcSAndroid Build Coastguard Worker     if (size_ == 0) {
144*8fb009dcSAndroid Build Coastguard Worker       abort();
145*8fb009dcSAndroid Build Coastguard Worker     }
146*8fb009dcSAndroid Build Coastguard Worker     return data_[size_ - 1];
147*8fb009dcSAndroid Build Coastguard Worker   }
148*8fb009dcSAndroid Build Coastguard Worker 
149*8fb009dcSAndroid Build Coastguard Worker   constexpr T &operator[](size_t i) const {
150*8fb009dcSAndroid Build Coastguard Worker     if (i >= size_) {
151*8fb009dcSAndroid Build Coastguard Worker       abort();
152*8fb009dcSAndroid Build Coastguard Worker     }
153*8fb009dcSAndroid Build Coastguard Worker     return data_[i];
154*8fb009dcSAndroid Build Coastguard Worker   }
at(size_t i)155*8fb009dcSAndroid Build Coastguard Worker   T &at(size_t i) const { return (*this)[i]; }
156*8fb009dcSAndroid Build Coastguard Worker 
157*8fb009dcSAndroid Build Coastguard Worker   constexpr Span subspan(size_t pos = 0, size_t len = npos) const {
158*8fb009dcSAndroid Build Coastguard Worker     if (pos > size_) {
159*8fb009dcSAndroid Build Coastguard Worker       // absl::Span throws an exception here. Note std::span and Chromium
160*8fb009dcSAndroid Build Coastguard Worker       // base::span additionally forbid pos + len being out of range, with a
161*8fb009dcSAndroid Build Coastguard Worker       // special case at npos/dynamic_extent, while absl::Span::subspan clips
162*8fb009dcSAndroid Build Coastguard Worker       // the span. For now, we align with absl::Span in case we switch to it in
163*8fb009dcSAndroid Build Coastguard Worker       // the future.
164*8fb009dcSAndroid Build Coastguard Worker       abort();
165*8fb009dcSAndroid Build Coastguard Worker     }
166*8fb009dcSAndroid Build Coastguard Worker     return Span(data_ + pos, std::min(size_ - pos, len));
167*8fb009dcSAndroid Build Coastguard Worker   }
168*8fb009dcSAndroid Build Coastguard Worker 
first(size_t len)169*8fb009dcSAndroid Build Coastguard Worker   constexpr Span first(size_t len) const {
170*8fb009dcSAndroid Build Coastguard Worker     if (len > size_) {
171*8fb009dcSAndroid Build Coastguard Worker       abort();
172*8fb009dcSAndroid Build Coastguard Worker     }
173*8fb009dcSAndroid Build Coastguard Worker     return Span(data_, len);
174*8fb009dcSAndroid Build Coastguard Worker   }
175*8fb009dcSAndroid Build Coastguard Worker 
last(size_t len)176*8fb009dcSAndroid Build Coastguard Worker   constexpr Span last(size_t len) const {
177*8fb009dcSAndroid Build Coastguard Worker     if (len > size_) {
178*8fb009dcSAndroid Build Coastguard Worker       abort();
179*8fb009dcSAndroid Build Coastguard Worker     }
180*8fb009dcSAndroid Build Coastguard Worker     return Span(data_ + size_ - len, len);
181*8fb009dcSAndroid Build Coastguard Worker   }
182*8fb009dcSAndroid Build Coastguard Worker 
183*8fb009dcSAndroid Build Coastguard Worker  private:
184*8fb009dcSAndroid Build Coastguard Worker   T *data_;
185*8fb009dcSAndroid Build Coastguard Worker   size_t size_;
186*8fb009dcSAndroid Build Coastguard Worker };
187*8fb009dcSAndroid Build Coastguard Worker 
188*8fb009dcSAndroid Build Coastguard Worker template <typename T>
189*8fb009dcSAndroid Build Coastguard Worker const size_t Span<T>::npos;
190*8fb009dcSAndroid Build Coastguard Worker 
191*8fb009dcSAndroid Build Coastguard Worker #if __cplusplus >= 201703L
192*8fb009dcSAndroid Build Coastguard Worker template <typename T>
193*8fb009dcSAndroid Build Coastguard Worker Span(T *, size_t) -> Span<T>;
194*8fb009dcSAndroid Build Coastguard Worker template <typename T, size_t size>
195*8fb009dcSAndroid Build Coastguard Worker Span(T (&array)[size]) -> Span<T>;
196*8fb009dcSAndroid Build Coastguard Worker template <
197*8fb009dcSAndroid Build Coastguard Worker     typename C,
198*8fb009dcSAndroid Build Coastguard Worker     typename T = std::remove_pointer_t<decltype(std::declval<C>().data())>,
199*8fb009dcSAndroid Build Coastguard Worker     typename = internal::EnableIfContainer<C, T>>
200*8fb009dcSAndroid Build Coastguard Worker Span(C &) -> Span<T>;
201*8fb009dcSAndroid Build Coastguard Worker #endif
202*8fb009dcSAndroid Build Coastguard Worker 
203*8fb009dcSAndroid Build Coastguard Worker // C++17 callers can instead rely on CTAD and the deduction guides defined
204*8fb009dcSAndroid Build Coastguard Worker // above.
205*8fb009dcSAndroid Build Coastguard Worker template <typename T>
MakeSpan(T * ptr,size_t size)206*8fb009dcSAndroid Build Coastguard Worker constexpr Span<T> MakeSpan(T *ptr, size_t size) {
207*8fb009dcSAndroid Build Coastguard Worker   return Span<T>(ptr, size);
208*8fb009dcSAndroid Build Coastguard Worker }
209*8fb009dcSAndroid Build Coastguard Worker 
210*8fb009dcSAndroid Build Coastguard Worker template <typename C>
211*8fb009dcSAndroid Build Coastguard Worker constexpr auto MakeSpan(C &c) -> decltype(MakeSpan(c.data(), c.size())) {
212*8fb009dcSAndroid Build Coastguard Worker   return MakeSpan(c.data(), c.size());
213*8fb009dcSAndroid Build Coastguard Worker }
214*8fb009dcSAndroid Build Coastguard Worker 
215*8fb009dcSAndroid Build Coastguard Worker template <typename T>
MakeConstSpan(T * ptr,size_t size)216*8fb009dcSAndroid Build Coastguard Worker constexpr Span<const T> MakeConstSpan(T *ptr, size_t size) {
217*8fb009dcSAndroid Build Coastguard Worker   return Span<const T>(ptr, size);
218*8fb009dcSAndroid Build Coastguard Worker }
219*8fb009dcSAndroid Build Coastguard Worker 
220*8fb009dcSAndroid Build Coastguard Worker template <typename C>
221*8fb009dcSAndroid Build Coastguard Worker constexpr auto MakeConstSpan(const C &c)
222*8fb009dcSAndroid Build Coastguard Worker     -> decltype(MakeConstSpan(c.data(), c.size())) {
223*8fb009dcSAndroid Build Coastguard Worker   return MakeConstSpan(c.data(), c.size());
224*8fb009dcSAndroid Build Coastguard Worker }
225*8fb009dcSAndroid Build Coastguard Worker 
226*8fb009dcSAndroid Build Coastguard Worker template <typename T, size_t size>
MakeConstSpan(T (& array)[size])227*8fb009dcSAndroid Build Coastguard Worker constexpr Span<const T> MakeConstSpan(T (&array)[size]) {
228*8fb009dcSAndroid Build Coastguard Worker   return array;
229*8fb009dcSAndroid Build Coastguard Worker }
230*8fb009dcSAndroid Build Coastguard Worker 
231*8fb009dcSAndroid Build Coastguard Worker #if __cplusplus >= 201703L
StringAsBytes(std::string_view s)232*8fb009dcSAndroid Build Coastguard Worker inline Span<const uint8_t> StringAsBytes(std::string_view s) {
233*8fb009dcSAndroid Build Coastguard Worker   return MakeConstSpan(reinterpret_cast<const uint8_t *>(s.data()), s.size());
234*8fb009dcSAndroid Build Coastguard Worker }
235*8fb009dcSAndroid Build Coastguard Worker 
BytesAsStringView(bssl::Span<const uint8_t> b)236*8fb009dcSAndroid Build Coastguard Worker inline std::string_view BytesAsStringView(bssl::Span<const uint8_t> b) {
237*8fb009dcSAndroid Build Coastguard Worker   return std::string_view(reinterpret_cast<const char *>(b.data()), b.size());
238*8fb009dcSAndroid Build Coastguard Worker }
239*8fb009dcSAndroid Build Coastguard Worker #endif
240*8fb009dcSAndroid Build Coastguard Worker 
241*8fb009dcSAndroid Build Coastguard Worker BSSL_NAMESPACE_END
242*8fb009dcSAndroid Build Coastguard Worker 
243*8fb009dcSAndroid Build Coastguard Worker }  // extern C++
244*8fb009dcSAndroid Build Coastguard Worker 
245*8fb009dcSAndroid Build Coastguard Worker #endif  // !defined(BORINGSSL_NO_CXX)
246*8fb009dcSAndroid Build Coastguard Worker 
247*8fb009dcSAndroid Build Coastguard Worker #endif  // OPENSSL_HEADER_SSL_SPAN_H
248