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