/Users/eugenesiegel/btc/bitcoin/src/span.h
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2018-present The Bitcoin Core developers | 
| 2 |  | // Distributed under the MIT software license, see the accompanying | 
| 3 |  | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | 
| 4 |  |  | 
| 5 |  | #ifndef BITCOIN_SPAN_H | 
| 6 |  | #define BITCOIN_SPAN_H | 
| 7 |  |  | 
| 8 |  | #include <cassert> | 
| 9 |  | #include <cstddef> | 
| 10 |  | #include <span> | 
| 11 |  | #include <type_traits> | 
| 12 |  | #include <utility> | 
| 13 |  |  | 
| 14 |  | /** A span is an object that can refer to a contiguous sequence of objects. | 
| 15 |  |  * | 
| 16 |  |  * Things to be aware of when writing code that deals with spans: | 
| 17 |  |  * | 
| 18 |  |  * - Similar to references themselves, spans are subject to reference lifetime | 
| 19 |  |  *   issues. The user is responsible for making sure the objects pointed to by | 
| 20 |  |  *   a span live as long as the span is used. For example: | 
| 21 |  |  * | 
| 22 |  |  *       std::vector<int> vec{1,2,3,4}; | 
| 23 |  |  *       std::span<int> sp(vec); | 
| 24 |  |  *       vec.push_back(5); | 
| 25 |  |  *       printf("%i\n", sp.front()); // UB! | 
| 26 |  |  * | 
| 27 |  |  *   may exhibit undefined behavior, as increasing the size of a vector may | 
| 28 |  |  *   invalidate references. | 
| 29 |  |  * | 
| 30 |  |  * - One particular pitfall is that spans can be constructed from temporaries, | 
| 31 |  |  *   but this is unsafe when the span is stored in a variable, outliving the | 
| 32 |  |  *   temporary. For example, this will compile, but exhibits undefined behavior: | 
| 33 |  |  * | 
| 34 |  |  *       std::span<const int> sp(std::vector<int>{1, 2, 3}); | 
| 35 |  |  *       printf("%i\n", sp.front()); // UB! | 
| 36 |  |  * | 
| 37 |  |  *   The lifetime of the vector ends when the statement it is created in ends. | 
| 38 |  |  *   Thus the span is left with a dangling reference, and using it is undefined. | 
| 39 |  |  * | 
| 40 |  |  * - Due to spans automatic creation from range-like objects (arrays, and data | 
| 41 |  |  *   types that expose a data() and size() member function), functions that | 
| 42 |  |  *   accept a span as input parameter can be called with any compatible | 
| 43 |  |  *   range-like object. For example, this works: | 
| 44 |  |  * | 
| 45 |  |  *       void Foo(std::span<const int> arg); | 
| 46 |  |  * | 
| 47 |  |  *       Foo(std::vector<int>{1, 2, 3}); // Works | 
| 48 |  |  * | 
| 49 |  |  *   This is very useful in cases where a function truly does not care about the | 
| 50 |  |  *   container, and only about having exactly a range of elements. However it | 
| 51 |  |  *   may also be surprising to see automatic conversions in this case. | 
| 52 |  |  * | 
| 53 |  |  *   When a function accepts a span with a mutable element type, it will not | 
| 54 |  |  *   accept temporaries; only variables or other references. For example: | 
| 55 |  |  * | 
| 56 |  |  *       void FooMut(std::span<int> arg); | 
| 57 |  |  * | 
| 58 |  |  *       FooMut(std::vector<int>{1, 2, 3}); // Does not compile | 
| 59 |  |  *       std::vector<int> baz{1, 2, 3}; | 
| 60 |  |  *       FooMut(baz); // Works | 
| 61 |  |  * | 
| 62 |  |  *   This is similar to how functions that take (non-const) lvalue references | 
| 63 |  |  *   as input cannot accept temporaries. This does not work either: | 
| 64 |  |  * | 
| 65 |  |  *       void FooVec(std::vector<int>& arg); | 
| 66 |  |  *       FooVec(std::vector<int>{1, 2, 3}); // Does not compile | 
| 67 |  |  * | 
| 68 |  |  *   The idea is that if a function accepts a mutable reference, a meaningful | 
| 69 |  |  *   result will be present in that variable after the call. Passing a temporary | 
| 70 |  |  *   is useless in that context. | 
| 71 |  |  */ | 
| 72 |  |  | 
| 73 |  | /** Pop the last element off a span, and return a reference to that element. */ | 
| 74 |  | template <typename T> | 
| 75 |  | T& SpanPopBack(std::span<T>& span) | 
| 76 | 998k | { | 
| 77 | 998k |     size_t size = span.size(); | 
| 78 | 998k |     T& back = span.back(); | 
| 79 | 998k |     span = span.first(size - 1); | 
| 80 | 998k |     return back; | 
| 81 | 998k | } _Z11SpanPopBackIKNSt3__16vectorIhNS0_9allocatorIhEEEEERT_RNS0_4spanIS6_Lm18446744073709551615EEE| Line | Count | Source |  | 76 | 998k | { |  | 77 | 998k |     size_t size = span.size(); |  | 78 | 998k |     T& back = span.back(); |  | 79 | 998k |     span = span.first(size - 1); |  | 80 | 998k |     return back; |  | 81 | 998k | } | 
Unexecuted instantiation: _Z11SpanPopBackIKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEERT_RNS0_4spanIS8_Lm18446744073709551615EEEUnexecuted instantiation: _Z11SpanPopBackIKhERT_RNSt3__14spanIS1_Lm18446744073709551615EEE | 
| 82 |  |  | 
| 83 |  | template <typename V> | 
| 84 |  | auto MakeByteSpan(const V& v) noexcept | 
| 85 | 151M | { | 
| 86 | 151M |     return std::as_bytes(std::span{v}); | 
| 87 | 151M | } _Z12MakeByteSpanINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEEDaRKT_| Line | Count | Source |  | 85 | 1.75M | { |  | 86 | 1.75M |     return std::as_bytes(std::span{v}); |  | 87 | 1.75M | } | 
_Z12MakeByteSpanI9prevectorILj36EhjiEEDaRKT_| Line | Count | Source |  | 85 | 70.1M | { |  | 86 | 70.1M |     return std::as_bytes(std::span{v}); |  | 87 | 70.1M | } | 
_Z12MakeByteSpanINSt3__16vectorIhNS0_9allocatorIhEEEEEDaRKT_| Line | Count | Source |  | 85 | 20.9M | { |  | 86 | 20.9M |     return std::as_bytes(std::span{v}); |  | 87 | 20.9M | } | 
_Z12MakeByteSpanIA4_hEDaRKT_| Line | Count | Source |  | 85 | 8.05M | { |  | 86 | 8.05M |     return std::as_bytes(std::span{v}); |  | 87 | 8.05M | } | 
Unexecuted instantiation: _Z12MakeByteSpanIA5_hEDaRKT_Unexecuted instantiation: _Z12MakeByteSpanIA78_hEDaRKT_Unexecuted instantiation: _Z12MakeByteSpanI9prevectorILj16EhjiEEDaRKT__Z12MakeByteSpanIA16_hEDaRKT_| Line | Count | Source |  | 85 | 769k | { |  | 86 | 769k |     return std::as_bytes(std::span{v}); |  | 87 | 769k | } | 
_Z12MakeByteSpanINSt3__15arrayIhLm4EEEEDaRKT_| Line | Count | Source |  | 85 | 8.10M | { |  | 86 | 8.10M |     return std::as_bytes(std::span{v}); |  | 87 | 8.10M | } | 
_Z12MakeByteSpanIA12_cEDaRKT_| Line | Count | Source |  | 85 | 8.05M | { |  | 86 | 8.05M |     return std::as_bytes(std::span{v}); |  | 87 | 8.05M | } | 
Unexecuted instantiation: _Z12MakeByteSpanINSt3__15arrayIhLm5EEEEDaRKT__Z12MakeByteSpanI7uint256EDaRKT_| Line | Count | Source |  | 85 | 12.5M | { |  | 86 | 12.5M |     return std::as_bytes(std::span{v}); |  | 87 | 12.5M | } | 
Unexecuted instantiation: _Z12MakeByteSpanINSt3__16vectorIh16secure_allocatorIhEEEEDaRKT__Z12MakeByteSpanIN7leveldb5SliceEEDaRKT_| Line | Count | Source |  | 85 | 20.6M | { |  | 86 | 20.6M |     return std::as_bytes(std::span{v}); |  | 87 | 20.6M | } | 
Unexecuted instantiation: _Z12MakeByteSpanINSt3__16vectorISt4byteNS0_9allocatorIS2_EEEEEDaRKT__Z12MakeByteSpanINSt3__15arrayISt4byteLm168EEEEDaRKT_| Line | Count | Source |  | 85 | 5.66k | { |  | 86 | 5.66k |     return std::as_bytes(std::span{v}); |  | 87 | 5.66k | } | 
Unexecuted instantiation: _Z12MakeByteSpanINSt3__15arrayISt4byteLm8EEEEDaRKT_Unexecuted instantiation: _Z12MakeByteSpanIA384_hEDaRKT_ | 
| 88 |  | template <typename V> | 
| 89 |  | auto MakeWritableByteSpan(V&& v) noexcept | 
| 90 | 63.0M | { | 
| 91 | 63.0M |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 
| 92 | 63.0M | } Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEEDaOT__Z20MakeWritableByteSpanIR7uint256EDaOT_| Line | Count | Source |  | 90 | 51.2k | { |  | 91 | 51.2k |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 51.2k | } | 
Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__16vectorISt4byteNS0_9allocatorIS2_EEEEEDaOT__Z20MakeWritableByteSpanIRNSt3__15arrayIhLm32EEEEDaOT_| Line | Count | Source |  | 90 | 41.9M | { |  | 91 | 41.9M |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 41.9M | } | 
Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__16vectorIhNS0_9allocatorIhEEEEEDaOT__Z20MakeWritableByteSpanIRA16_hEDaOT_| Line | Count | Source |  | 90 | 191k | { |  | 91 | 191k |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 191k | } | 
_Z20MakeWritableByteSpanIRA4_hEDaOT_| Line | Count | Source |  | 90 | 6.84M | { |  | 91 | 6.84M |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 6.84M | } | 
Unexecuted instantiation: _Z20MakeWritableByteSpanIRA5_hEDaOT__Z20MakeWritableByteSpanIRNSt3__15arrayIhLm4EEEEDaOT_| Line | Count | Source |  | 90 | 7.15M | { |  | 91 | 7.15M |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 7.15M | } | 
_Z20MakeWritableByteSpanIRA12_cEDaOT_| Line | Count | Source |  | 90 | 6.84M | { |  | 91 | 6.84M |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 6.84M | } | 
Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayIhLm5EEEEDaOT_Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayIhLm20EEEEDaOT_Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayISt4byteLm20EEEEDaOT_Unexecuted instantiation: _Z20MakeWritableByteSpanIRA368_cEDaOT_Unexecuted instantiation: _Z20MakeWritableByteSpanIRA20_hEDaOT__Z20MakeWritableByteSpanIRNSt3__15arrayISt4byteLm8EEEEDaOT_| Line | Count | Source |  | 90 | 51.2k | { |  | 91 | 51.2k |     return std::as_writable_bytes(std::span{std::forward<V>(v)}); |  | 92 | 51.2k | } | 
Unexecuted instantiation: _Z20MakeWritableByteSpanIRA384_hEDaOT_ | 
| 93 |  |  | 
| 94 |  | // Helper functions to safely cast basic byte pointers to unsigned char pointers. | 
| 95 | 0 | inline unsigned char* UCharCast(char* c) { return reinterpret_cast<unsigned char*>(c); } | 
| 96 | 0 | inline unsigned char* UCharCast(unsigned char* c) { return c; } | 
| 97 | 0 | inline unsigned char* UCharCast(signed char* c) { return reinterpret_cast<unsigned char*>(c); } | 
| 98 | 0 | inline unsigned char* UCharCast(std::byte* c) { return reinterpret_cast<unsigned char*>(c); } | 
| 99 | 0 | inline const unsigned char* UCharCast(const char* c) { return reinterpret_cast<const unsigned char*>(c); } | 
| 100 | 8.05M | inline const unsigned char* UCharCast(const unsigned char* c) { return c; } | 
| 101 | 0 | inline const unsigned char* UCharCast(const signed char* c) { return reinterpret_cast<const unsigned char*>(c); } | 
| 102 | 937M | inline const unsigned char* UCharCast(const std::byte* c) { return reinterpret_cast<const unsigned char*>(c); } | 
| 103 |  | // Helper concept for the basic byte types. | 
| 104 |  | template <typename B> | 
| 105 |  | concept BasicByte = requires { UCharCast(std::span<B>{}.data()); }; | 
| 106 |  |  | 
| 107 |  | // Helper function to safely convert a span to a span<[const] unsigned char>. | 
| 108 | 8.21M | template <typename T, size_t N> constexpr auto UCharSpanCast(std::span<T, N> s) { return std::span<std::remove_pointer_t<decltype(UCharCast(s.data()))>, N>{UCharCast(s.data()), s.size()}; }Unexecuted instantiation: _Z13UCharSpanCastIKcLm18446744073709551615EEDaNSt3__14spanIT_XT0_EEE_Z13UCharSpanCastIKSt4byteLm18446744073709551615EEDaNSt3__14spanIT_XT0_EEE| Line | Count | Source |  | 108 | 153k | template <typename T, size_t N> constexpr auto UCharSpanCast(std::span<T, N> s) { return std::span<std::remove_pointer_t<decltype(UCharCast(s.data()))>, N>{UCharCast(s.data()), s.size()}; } | 
_Z13UCharSpanCastIKhLm18446744073709551615EEDaNSt3__14spanIT_XT0_EEE| Line | Count | Source |  | 108 | 8.05M | template <typename T, size_t N> constexpr auto UCharSpanCast(std::span<T, N> s) { return std::span<std::remove_pointer_t<decltype(UCharCast(s.data()))>, N>{UCharCast(s.data()), s.size()}; } | 
Unexecuted instantiation: _Z13UCharSpanCastIhLm18446744073709551615EEDaNSt3__14spanIT_XT0_EEEUnexecuted instantiation: _Z13UCharSpanCastIKhLm8EEDaNSt3__14spanIT_XT0_EEE | 
| 109 |  |  | 
| 110 |  | /** Like the std::span constructor, but for (const) unsigned char member types only. Only works for (un)signed char containers. */ | 
| 111 | 8.21M | template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }Unexecuted instantiation: _Z13MakeUCharSpanINSt3__14spanIKcLm18446744073709551615EEEEDTcl13UCharSpanCasttlS1_fp_EEERKT__Z13MakeUCharSpanINSt3__14spanIKSt4byteLm18446744073709551615EEEEDTcl13UCharSpanCasttlS1_fp_EEERKT_| Line | Count | Source |  | 111 | 153k | template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); } | 
Unexecuted instantiation: _Z13MakeUCharSpanINSt3__117basic_string_viewIcNS0_11char_traitsIcEEEEEDTcl13UCharSpanCasttlNS0_4spanEfp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanINSt3__14spanIKhLm18446744073709551615EEEEDTcl13UCharSpanCasttlS1_fp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEEDTcl13UCharSpanCasttlNS0_4spanEfp_EEERKT__Z13MakeUCharSpanINSt3__16vectorIhNS0_9allocatorIhEEEEEDTcl13UCharSpanCasttlNS0_4spanEfp_EEERKT_| Line | Count | Source |  | 111 | 8.05M | template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); } | 
Unexecuted instantiation: _Z13MakeUCharSpanI7uint256EDTcl13UCharSpanCasttlNSt3__14spanEfp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanI11XOnlyPubKeyEDTcl13UCharSpanCasttlNSt3__14spanEfp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanI7CPubKeyEDTcl13UCharSpanCasttlNSt3__14spanEfp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanI7CScriptEDTcl13UCharSpanCasttlNSt3__14spanEfp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanINSt3__14spanIhLm18446744073709551615EEEEDTcl13UCharSpanCasttlS1_fp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanI10DataStreamEDTcl13UCharSpanCasttlNSt3__14spanEfp_EEERKT_Unexecuted instantiation: _Z13MakeUCharSpanIA8_hEDTcl13UCharSpanCasttlNSt3__14spanEfp_EEERKT_ | 
| 112 |  | template <typename V> constexpr auto MakeWritableUCharSpan(V&& v) -> decltype(UCharSpanCast(std::span{std::forward<V>(v)})) { return UCharSpanCast(std::span{std::forward<V>(v)}); } | 
| 113 |  |  | 
| 114 |  | #endif // BITCOIN_SPAN_H |