/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 | 0 | { |
77 | 0 | size_t size = span.size(); |
78 | 0 | T& back = span.back(); |
79 | 0 | span = span.first(size - 1); |
80 | 0 | return back; |
81 | 0 | } Unexecuted instantiation: _Z11SpanPopBackIKNSt3__16vectorIhNS0_9allocatorIhEEEEERT_RNS0_4spanIS6_Lm18446744073709551615EEE Unexecuted instantiation: _Z11SpanPopBackIKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEERT_RNS0_4spanIS8_Lm18446744073709551615EEE Unexecuted instantiation: _Z11SpanPopBackIKhERT_RNSt3__14spanIS1_Lm18446744073709551615EEE |
82 | | |
83 | | template <typename V> |
84 | | auto MakeByteSpan(const V& v) noexcept |
85 | 746M | { |
86 | 746M | return std::as_bytes(std::span{v}); |
87 | 746M | } _Z12MakeByteSpanINSt3__16vectorIhNS0_9allocatorIhEEEEEDaRKT_ Line | Count | Source | 85 | 64.5M | { | 86 | 64.5M | return std::as_bytes(std::span{v}); | 87 | 64.5M | } |
_Z12MakeByteSpanINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEEDaRKT_ Line | Count | Source | 85 | 199k | { | 86 | 199k | return std::as_bytes(std::span{v}); | 87 | 199k | } |
_Z12MakeByteSpanI9prevectorILj28EhjiEEDaRKT_ Line | Count | Source | 85 | 536M | { | 86 | 536M | return std::as_bytes(std::span{v}); | 87 | 536M | } |
_Z12MakeByteSpanIA4_hEDaRKT_ Line | Count | Source | 85 | 1.14M | { | 86 | 1.14M | return std::as_bytes(std::span{v}); | 87 | 1.14M | } |
Unexecuted instantiation: _Z12MakeByteSpanIA5_hEDaRKT_ Unexecuted instantiation: _Z12MakeByteSpanIA78_hEDaRKT_ Unexecuted instantiation: _Z12MakeByteSpanI9prevectorILj16EhjiEEDaRKT_ _Z12MakeByteSpanIA16_hEDaRKT_ Line | Count | Source | 85 | 598k | { | 86 | 598k | return std::as_bytes(std::span{v}); | 87 | 598k | } |
_Z12MakeByteSpanINSt3__15arrayIhLm4EEEEDaRKT_ Line | Count | Source | 85 | 21.1M | { | 86 | 21.1M | return std::as_bytes(std::span{v}); | 87 | 21.1M | } |
_Z12MakeByteSpanIA12_cEDaRKT_ Line | Count | Source | 85 | 1.14M | { | 86 | 1.14M | return std::as_bytes(std::span{v}); | 87 | 1.14M | } |
Unexecuted instantiation: _Z12MakeByteSpanINSt3__15arrayIhLm5EEEEDaRKT_ _Z12MakeByteSpanI7uint256EDaRKT_ Line | Count | Source | 85 | 121M | { | 86 | 121M | return std::as_bytes(std::span{v}); | 87 | 121M | } |
Unexecuted instantiation: _Z12MakeByteSpanINSt3__16vectorIh16secure_allocatorIhEEEEDaRKT_ Unexecuted instantiation: _Z12MakeByteSpanIN7leveldb5SliceEEDaRKT_ _Z12MakeByteSpanINSt3__15arrayISt4byteLm168EEEEDaRKT_ Line | Count | Source | 85 | 15.3k | { | 86 | 15.3k | return std::as_bytes(std::span{v}); | 87 | 15.3k | } |
_Z12MakeByteSpanINSt3__15arrayISt4byteLm8EEEEDaRKT_ Line | Count | Source | 85 | 49.9k | { | 86 | 49.9k | return std::as_bytes(std::span{v}); | 87 | 49.9k | } |
Unexecuted instantiation: _Z12MakeByteSpanINSt3__16vectorISt4byteNS0_9allocatorIS2_EEEEEDaRKT_ Unexecuted instantiation: _Z12MakeByteSpanIA384_hEDaRKT_ |
88 | | template <typename V> |
89 | | auto MakeWritableByteSpan(V&& v) noexcept |
90 | 4.47M | { |
91 | 4.47M | return std::as_writable_bytes(std::span{std::forward<V>(v)}); |
92 | 4.47M | } Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEEDaOT_ _Z20MakeWritableByteSpanIR10DataStreamEDaOT_ Line | Count | Source | 90 | 261k | { | 91 | 261k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 261k | } |
_Z20MakeWritableByteSpanIR7uint256EDaOT_ Line | Count | Source | 90 | 49.9k | { | 91 | 49.9k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 49.9k | } |
Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__16vectorISt4byteNS0_9allocatorIS2_EEEEEDaOT_ _Z20MakeWritableByteSpanIRNSt3__15arrayIhLm32EEEEDaOT_ Line | Count | Source | 90 | 1.74M | { | 91 | 1.74M | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 1.74M | } |
_Z20MakeWritableByteSpanIRNSt3__16vectorIhNS0_9allocatorIhEEEEEDaOT_ Line | Count | Source | 90 | 100k | { | 91 | 100k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 100k | } |
_Z20MakeWritableByteSpanIRA16_hEDaOT_ Line | Count | Source | 90 | 141k | { | 91 | 141k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 141k | } |
_Z20MakeWritableByteSpanIRA4_hEDaOT_ Line | Count | Source | 90 | 711k | { | 91 | 711k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 711k | } |
Unexecuted instantiation: _Z20MakeWritableByteSpanIRA5_hEDaOT_ _Z20MakeWritableByteSpanIRNSt3__15arrayIhLm4EEEEDaOT_ Line | Count | Source | 90 | 762k | { | 91 | 762k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 762k | } |
_Z20MakeWritableByteSpanIRA12_cEDaOT_ Line | Count | Source | 90 | 711k | { | 91 | 711k | return std::as_writable_bytes(std::span{std::forward<V>(v)}); | 92 | 711k | } |
Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayIhLm5EEEEDaOT_ Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayIhLm20EEEEDaOT_ Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayISt4byteLm20EEEEDaOT_ Unexecuted instantiation: _Z20MakeWritableByteSpanIRA368_cEDaOT_ Unexecuted instantiation: _Z20MakeWritableByteSpanIRA20_hEDaOT_ Unexecuted instantiation: _Z20MakeWritableByteSpanIRNSt3__15arrayISt4byteLm8EEEEDaOT_ 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 | 1.14M | 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 | 1.47G | 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 | 1.19M | 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 | 49.9k | 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 | 1.14M | 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_EEE Unexecuted 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 | 1.19M | 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 | 49.9k | 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 | 1.14M | template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); } |
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_ Unexecuted instantiation: _Z13MakeUCharSpanI7uint256EDTcl13UCharSpanCasttlNSt3__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 |