• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ska-sa / spead2 / 5991859444

27 Aug 2023 02:11PM UTC coverage: 75.031% (+0.03%) from 75.0%
5991859444

Pull #239

github

bmerry
Remove an unneeded lambda capture

It was giving a warning on Clang and hence failing CI.
Pull Request #239: Update to require at least C++17

152 of 152 new or added lines in 39 files covered. (100.0%)

5427 of 7233 relevant lines covered (75.03%)

52706.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.24
/src/send_heap.cpp
1
/* Copyright 2015, 2023 National Research Foundation (SARAO)
2
 *
3
 * This program is free software: you can redistribute it and/or modify it under
4
 * the terms of the GNU Lesser General Public License as published by the Free
5
 * Software Foundation, either version 3 of the License, or (at your option) any
6
 * later version.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
11
 * details.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public License
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 */
16

17
/**
18
 * @file
19
 */
20

21
#include <cstdint>
22
#include <vector>
23
#include <memory>
24
#include <stdexcept>
25
#include <cassert>
26
#include <cstring>
27
#include <boost/asio/buffer.hpp>
28
#include <spead2/send_heap.h>
29
#include <spead2/send_packet.h>
30
#include <spead2/send_utils.h>
31
#include <spead2/common_defines.h>
32
#include <spead2/common_logging.h>
33
#include <spead2/common_endian.h>
34
#include "common_unique.h"
35

36
namespace spead2::send
37
{
38

39
/**
40
 * Encode @a value as an unsigned big-endian number in @a len bytes.
41
 *
42
 * @pre
43
 * - @a 0 &lt;= len &lt;= sizeof(item_pointer_t)
44
 * - @a value &lt; 2<sup>len * 8</sup>
45
 */
46
static inline void store_bytes_be(std::uint8_t *ptr, int len, item_pointer_t value)
1,436✔
47
{
48
    assert(0 <= len && len <= int(sizeof(item_pointer_t)));
×
49
    assert(len == sizeof(item_pointer_t) || value < (std::uint64_t(1) << (8 * len)));
×
50
    value = htobe<item_pointer_t>(value);
1,436✔
51
    std::memcpy(ptr, reinterpret_cast<const char *>(&value) + sizeof(item_pointer_t) - len, len);
1,436✔
52
}
1,436✔
53

54
/* Copies, then increments dest
55
 */
56
static inline void memcpy_adjust(std::uint8_t *&dest, const void *src, std::size_t length)
2,741✔
57
{
58
    std::memcpy(dest, src, length);
2,741✔
59
    dest += length;
2,741✔
60
}
2,741✔
61

62
static std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>
63
encode_descriptor(const descriptor &d, const flavour &flavour_)
1,218✔
64
{
65
    const int field_size = (flavour_.get_bug_compat() & BUG_COMPAT_DESCRIPTOR_WIDTHS) ? 4 : sizeof(item_pointer_t) + 1 - flavour_.get_heap_address_bits() / 8;
1,218✔
66
    const int shape_size = (flavour_.get_bug_compat() & BUG_COMPAT_DESCRIPTOR_WIDTHS) ? 8 : 1 + flavour_.get_heap_address_bits() / 8;
1,218✔
67

68
    if (d.id <= 0 || d.id >= (s_item_pointer_t(1) << (8 * sizeof(item_pointer_t) - 1 - flavour_.get_heap_address_bits())))
1,218✔
69
        throw std::invalid_argument("Item ID out of range");
×
70

71
    /* The descriptor is a complete SPEAD packet, containing:
72
     * - header
73
     * - heap cnt, payload offset, payload size, heap size
74
     * - ID, name, description, format, shape
75
     * - optionally, numpy_header
76
     */
77
    bool have_numpy = !d.numpy_header.empty();
1,218✔
78
    int n_items = 9 + have_numpy;
1,218✔
79
    std::size_t payload_size =
80
        d.name.size()
1,218✔
81
        + d.description.size()
1,218✔
82
        + d.format.size() * field_size
2,436✔
83
        + d.shape.size() * shape_size
1,218✔
84
        + d.numpy_header.size();
1,218✔
85
    std::size_t total_size = payload_size + n_items * sizeof(item_pointer_t) + 8;
1,218✔
86
    auto out = detail::make_unique_for_overwrite<std::uint8_t[]>(total_size);
1,218✔
87
    std::uint64_t *header = reinterpret_cast<std::uint64_t *>(out.get());
1,218✔
88
    item_pointer_t *pointer = reinterpret_cast<item_pointer_t *>(out.get() + 8);
1,218✔
89
    std::size_t offset = 0;
1,218✔
90
    // TODO: for >64-bit item pointers, this will have alignment issues
91

92
    pointer_encoder encoder(flavour_.get_heap_address_bits());
1,218✔
93
    *header = htobe<std::uint64_t>(
2,436✔
94
            (std::uint64_t(0x5304) << 48)
95
            | (std::uint64_t(8 - flavour_.get_heap_address_bits() / 8) << 40)
1,218✔
96
            | (std::uint64_t(flavour_.get_heap_address_bits() / 8) << 32)
1,218✔
97
            | n_items);
1,218✔
98
    *pointer++ = htobe<item_pointer_t>(encoder.encode_immediate(HEAP_CNT_ID, 1));
1,218✔
99
    *pointer++ = htobe<item_pointer_t>(encoder.encode_immediate(HEAP_LENGTH_ID, payload_size));
1,218✔
100
    *pointer++ = htobe<item_pointer_t>(encoder.encode_immediate(PAYLOAD_OFFSET_ID, 0));
1,218✔
101
    *pointer++ = htobe<item_pointer_t>(encoder.encode_immediate(PAYLOAD_LENGTH_ID, payload_size));
1,218✔
102
    *pointer++ = htobe<item_pointer_t>(encoder.encode_immediate(DESCRIPTOR_ID_ID, d.id));
1,218✔
103
    *pointer++ = htobe<item_pointer_t>(encoder.encode_address(DESCRIPTOR_NAME_ID, offset));
1,218✔
104
    offset += d.name.size();
1,218✔
105
    *pointer++ = htobe<item_pointer_t>(encoder.encode_address(DESCRIPTOR_DESCRIPTION_ID, offset));
1,218✔
106
    offset += d.description.size();
1,218✔
107
    *pointer++ = htobe<item_pointer_t>(encoder.encode_address(DESCRIPTOR_FORMAT_ID, offset));
1,218✔
108
    offset += d.format.size() * field_size;
1,218✔
109
    *pointer++ = htobe<item_pointer_t>(encoder.encode_address(DESCRIPTOR_SHAPE_ID, offset));
1,218✔
110
    offset += d.shape.size() * shape_size;
1,218✔
111
    if (have_numpy)
1,218✔
112
    {
113
        *pointer++ = htobe<item_pointer_t>(encoder.encode_address(DESCRIPTOR_DTYPE_ID, offset));
305✔
114
        offset += d.numpy_header.size();
305✔
115
    }
116
    assert(offset == payload_size);
×
117

118
    std::uint8_t *data = reinterpret_cast<std::uint8_t *>(pointer);
1,218✔
119
    memcpy_adjust(data, d.name.data(), d.name.size());
1,218✔
120
    memcpy_adjust(data, d.description.data(), d.description.size());
1,218✔
121

122
    for (const auto &[ftype, fsize] : d.format)
2,239✔
123
    {
124
        *data = ftype;
1,021✔
125
        // TODO: validate that it fits
126
        store_bytes_be(data + 1, field_size - 1, fsize);
1,021✔
127
        data += field_size;
1,021✔
128
    }
129

130
    const std::uint8_t variable_tag = (flavour_.get_bug_compat() & BUG_COMPAT_SHAPE_BIT_1) ? 2 : 1;
1,218✔
131
    for (const s_item_pointer_t dim : d.shape)
1,633✔
132
    {
133
        *data = (dim < 0) ? variable_tag : 0;
415✔
134
        // TODO: validate that it fits
135
        store_bytes_be(data + 1, shape_size - 1, dim < 0 ? 0 : dim);
415✔
136
        data += shape_size;
415✔
137
    }
138
    if (have_numpy)
1,218✔
139
    {
140
        memcpy_adjust(data, d.numpy_header.data(), d.numpy_header.size());
305✔
141
    }
142
    assert(std::size_t(data - out.get()) == total_size);
×
143
    return {std::move(out), total_size};
2,436✔
144
}
1,218✔
145

146

147
heap::heap(const flavour &flavour_)
5,554✔
148
    : flavour_(flavour_)
5,554✔
149
{
150
}
5,554✔
151

152
void heap::add_descriptor(const descriptor &descriptor)
1,218✔
153
{
154
    auto [ptr, size] = encode_descriptor(descriptor, flavour_);
1,218✔
155
    items.emplace_back(DESCRIPTOR_ID, ptr.get(), size, false);
1,218✔
156
    storage.emplace_back(std::move(ptr));
1,218✔
157
}
1,218✔
158

159
} // namespace spead2::send
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc