Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/span.h
Line
Count
Source
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
103k
{
77
103k
    size_t size = span.size();
78
103k
    T& back = span.back();
79
103k
    span = span.first(size - 1);
80
103k
    return back;
81
103k
}
Unexecuted instantiation: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const& SpanPopBack<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const>(std::span<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, 18446744073709551615ul>&)
std::vector<unsigned char, std::allocator<unsigned char> > const& SpanPopBack<std::vector<unsigned char, std::allocator<unsigned char> > const>(std::span<std::vector<unsigned char, std::allocator<unsigned char> > const, 18446744073709551615ul>&)
Line
Count
Source
76
103k
{
77
103k
    size_t size = span.size();
78
103k
    T& back = span.back();
79
103k
    span = span.first(size - 1);
80
103k
    return back;
81
103k
}
Unexecuted instantiation: unsigned char const& SpanPopBack<unsigned char const>(std::span<unsigned char const, 18446744073709551615ul>&)
82
83
template <typename V>
84
auto MakeByteSpan(const V& v) noexcept
85
128M
{
86
128M
    return std::as_bytes(std::span{v});
87
128M
}
auto MakeByteSpan<std::vector<unsigned char, std::allocator<unsigned char> > >(std::vector<unsigned char, std::allocator<unsigned char> > const&)
Line
Count
Source
85
22.5M
{
86
22.5M
    return std::as_bytes(std::span{v});
87
22.5M
}
auto MakeByteSpan<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
Line
Count
Source
85
1.51M
{
86
1.51M
    return std::as_bytes(std::span{v});
87
1.51M
}
auto MakeByteSpan<prevector<28u, unsigned char, unsigned int, int> >(prevector<28u, unsigned char, unsigned int, int> const&)
Line
Count
Source
85
60.4M
{
86
60.4M
    return std::as_bytes(std::span{v});
87
60.4M
}
auto MakeByteSpan<uint256>(uint256 const&)
Line
Count
Source
85
44.3k
{
86
44.3k
    return std::as_bytes(std::span{v});
87
44.3k
}
auto MakeByteSpan<std::array<unsigned char, 4ul> >(std::array<unsigned char, 4ul> const&)
Line
Count
Source
85
17.4M
{
86
17.4M
    return std::as_bytes(std::span{v});
87
17.4M
}
auto MakeByteSpan<char [12]>(char const (&) [12])
Line
Count
Source
85
12.9M
{
86
12.9M
    return std::as_bytes(std::span{v});
87
12.9M
}
auto MakeByteSpan<unsigned char [4]>(unsigned char const (&) [4])
Line
Count
Source
85
12.9M
{
86
12.9M
    return std::as_bytes(std::span{v});
87
12.9M
}
auto MakeByteSpan<prevector<16u, unsigned char, unsigned int, int> >(prevector<16u, unsigned char, unsigned int, int> const&)
Line
Count
Source
85
8.38k
{
86
8.38k
    return std::as_bytes(std::span{v});
87
8.38k
}
auto MakeByteSpan<unsigned char [16]>(unsigned char const (&) [16])
Line
Count
Source
85
177k
{
86
177k
    return std::as_bytes(std::span{v});
87
177k
}
Unexecuted instantiation: auto MakeByteSpan<std::array<std::byte, 168ul> >(std::array<std::byte, 168ul> const&)
auto MakeByteSpan<std::array<std::byte, 8ul> >(std::array<std::byte, 8ul> const&)
Line
Count
Source
85
11.0k
{
86
11.0k
    return std::as_bytes(std::span{v});
87
11.0k
}
auto MakeByteSpan<std::vector<std::byte, std::allocator<std::byte> > >(std::vector<std::byte, std::allocator<std::byte> > const&)
Line
Count
Source
85
11.0k
{
86
11.0k
    return std::as_bytes(std::span{v});
87
11.0k
}
Unexecuted instantiation: auto MakeByteSpan<std::array<unsigned char, 5ul> >(std::array<unsigned char, 5ul> const&)
Unexecuted instantiation: auto MakeByteSpan<unsigned char [5]>(unsigned char const (&) [5])
Unexecuted instantiation: auto MakeByteSpan<unsigned char [78]>(unsigned char const (&) [78])
auto MakeByteSpan<leveldb::Slice>(leveldb::Slice const&)
Line
Count
Source
85
13.0k
{
86
13.0k
    return std::as_bytes(std::span{v});
87
13.0k
}
auto MakeByteSpan<std::vector<unsigned char, secure_allocator<unsigned char> > >(std::vector<unsigned char, secure_allocator<unsigned char> > const&)
Line
Count
Source
85
88.7k
{
86
88.7k
    return std::as_bytes(std::span{v});
87
88.7k
}
Unexecuted instantiation: auto MakeByteSpan<unsigned char [384]>(unsigned char const (&) [384])
88
template <typename V>
89
auto MakeWritableByteSpan(V&& v) noexcept
90
34.3M
{
91
34.3M
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
34.3M
}
auto MakeWritableByteSpan<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)
Line
Count
Source
90
88.7k
{
91
88.7k
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
88.7k
}
auto MakeWritableByteSpan<uint256&>(uint256&)
Line
Count
Source
90
22.1k
{
91
22.1k
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
22.1k
}
auto MakeWritableByteSpan<DataStream&>(DataStream&)
Line
Count
Source
90
6.90M
{
91
6.90M
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
6.90M
}
auto MakeWritableByteSpan<std::vector<unsigned char, std::allocator<unsigned char> >&>(std::vector<unsigned char, std::allocator<unsigned char> >&)
Line
Count
Source
90
70.0k
{
91
70.0k
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
70.0k
}
auto MakeWritableByteSpan<unsigned char (&) [16]>(unsigned char (&) [16])
Line
Count
Source
90
95.2k
{
91
95.2k
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
95.2k
}
auto MakeWritableByteSpan<std::array<unsigned char, 4ul>&>(std::array<unsigned char, 4ul>&)
Line
Count
Source
90
5.54M
{
91
5.54M
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
5.54M
}
auto MakeWritableByteSpan<char (&) [12]>(char (&) [12])
Line
Count
Source
90
5.52M
{
91
5.52M
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
5.52M
}
auto MakeWritableByteSpan<unsigned char (&) [4]>(unsigned char (&) [4])
Line
Count
Source
90
5.52M
{
91
5.52M
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
5.52M
}
auto MakeWritableByteSpan<std::array<unsigned char, 32ul>&>(std::array<unsigned char, 32ul>&)
Line
Count
Source
90
10.5M
{
91
10.5M
    return std::as_writable_bytes(std::span{std::forward<V>(v)});
92
10.5M
}
Unexecuted instantiation: auto MakeWritableByteSpan<std::array<std::byte, 8ul>&>(std::array<std::byte, 8ul>&)
Unexecuted instantiation: auto MakeWritableByteSpan<std::array<unsigned char, 5ul>&>(std::array<unsigned char, 5ul>&)
Unexecuted instantiation: auto MakeWritableByteSpan<std::array<unsigned char, 20ul>&>(std::array<unsigned char, 20ul>&)
Unexecuted instantiation: auto MakeWritableByteSpan<std::array<std::byte, 20ul>&>(std::array<std::byte, 20ul>&)
Unexecuted instantiation: auto MakeWritableByteSpan<char (&) [368]>(char (&) [368])
Unexecuted instantiation: auto MakeWritableByteSpan<unsigned char (&) [20]>(unsigned char (&) [20])
Unexecuted instantiation: auto MakeWritableByteSpan<unsigned char (&) [5]>(unsigned char (&) [5])
Unexecuted instantiation: auto MakeWritableByteSpan<unsigned char (&) [384]>(unsigned char (&) [384])
93
94
// Helper functions to safely cast basic byte pointers to unsigned char pointers.
95
22.1k
inline unsigned char* UCharCast(char* c) { return reinterpret_cast<unsigned char*>(c); }
96
188k
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
44.3k
inline unsigned char* UCharCast(std::byte* c) { return reinterpret_cast<unsigned char*>(c); }
99
4.73M
inline const unsigned char* UCharCast(const char* c) { return reinterpret_cast<const unsigned char*>(c); }
100
28.0M
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
541M
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
28.1M
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()}; }
auto UCharSpanCast<char const, 18446744073709551615ul>(std::span<char const, 18446744073709551615ul>)
Line
Count
Source
108
22.1k
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()}; }
auto UCharSpanCast<std::byte const, 18446744073709551615ul>(std::span<std::byte const, 18446744073709551615ul>)
Line
Count
Source
108
11.5k
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()}; }
auto UCharSpanCast<unsigned char const, 18446744073709551615ul>(std::span<unsigned char const, 18446744073709551615ul>)
Line
Count
Source
108
27.9M
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()}; }
auto UCharSpanCast<unsigned char, 18446744073709551615ul>(std::span<unsigned char, 18446744073709551615ul>)
Line
Count
Source
108
177k
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()}; }
auto UCharSpanCast<unsigned char const, 8ul>(std::span<unsigned char const, 8ul>)
Line
Count
Source
108
22.1k
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()}; }
109
110
/** Like the std::span constructor, but for (const) unsigned char member types only. Only works for (un)signed char containers. */
111
28.1M
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
Unexecuted instantiation: decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::span<char const, 18446744073709551615ul> >(std::span<char const, 18446744073709551615ul> const&)
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::span<std::byte const, 18446744073709551615ul> >(std::span<std::byte const, 18446744073709551615ul> const&)
Line
Count
Source
111
11.0k
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
Unexecuted instantiation: decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::basic_string_view<char, std::char_traits<char> > >(std::basic_string_view<char, std::char_traits<char> > const&)
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::span<unsigned char const, 18446744073709551615ul> >(std::span<unsigned char const, 18446744073709551615ul> const&)
Line
Count
Source
111
5.01M
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::vector<unsigned char, std::allocator<unsigned char> > >(std::vector<unsigned char, std::allocator<unsigned char> > const&)
Line
Count
Source
111
17.9M
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<DataStream>(DataStream const&)
Line
Count
Source
111
449
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<uint256>(uint256 const&)
Line
Count
Source
111
4.47M
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<CScript>(CScript const&)
Line
Count
Source
111
443k
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::span<unsigned char, 18446744073709551615ul> >(std::span<unsigned char, 18446744073709551615ul> const&)
Line
Count
Source
111
177k
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
Line
Count
Source
111
22.1k
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<unsigned char [8]>(unsigned char const (&) [8])
Line
Count
Source
111
22.1k
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
Unexecuted instantiation: decltype (UCharSpanCast(std::span{{parm#1}})) MakeUCharSpan<XOnlyPubKey>(XOnlyPubKey const&)
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