GCC Code Coverage Report


Directory: ./
File: src/Selector.cpp
Date: 2024-11-05 15:23:15
Exec Total Coverage
Lines: 59 74 79.7%
Branches: 56 118 47.5%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2021 Bjarne von Horn (vh at igh dot de).
4 *
5 * This file is part of the PdCom library.
6 *
7 * The PdCom library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * The PdCom library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the PdCom library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *****************************************************************************/
21
22
23 #include "Selector.h"
24
25 #include "Variable.h"
26
27 #include <cstring>
28 #include <pdcom5/Exception.h>
29 #include <pdcom5/Subscription.h>
30 #include <sstream>
31
32
33 105 PdCom::Selector::Selector() : impl_(std::make_shared<impl::Selector>())
34 105 {}
35 6 PdCom::ScalarSelector::ScalarSelector(std::vector<int> indices) :
36 6 PdCom::Selector(std::make_shared<impl::ScalarSelector>(std::move(indices)))
37 6 {}
38
39 PdCom::SizeInfo
40 PdCom::Selector::getViewSizeInfo(const PdCom::Variable &variable) const
41 {
42 if (!impl_)
43 throw PdCom::InvalidArgument("impl must not be NULL!");
44 return impl_->getViewSizeInfo(*impl::Variable::fromUApi(variable));
45 }
46
47 using PdCom::impl::Selector;
48 using PdCom::impl::Variable;
49
50
51 Selector::CopyFunctionType
52 85 Selector::getCopyFunction(const Variable &variable) const
53 {
54 85 const auto count = getRequiredSize(variable);
55 97 return [count](void *dest, const void *src) {
56
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
97 std::memcpy(dest, src, count);
57 182 };
58 }
59
60 168 std::size_t Selector::getRequiredSize(const Variable &variable) const
61 {
62 168 return variable.totalSizeInBytes();
63 }
64
65 16 PdCom::Variable::SetValueFuture Selector::applySetValue(
66 const Variable &variable,
67 const void *const src_data,
68 PdCom::TypeInfo::DataType const src_type,
69 size_t const src_count) const
70 {
71
3/6
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 16 times.
16 if (!src_count or src_count > variable.size_info.totalElements()) {
72 throw PdCom::InvalidArgument(
73 "Range Error, got " + std::to_string(src_count)
74 + " Parameter values, expected max. "
75 + std::to_string(variable.size_info.totalElements()));
76 }
77 16 return variable.setValue(src_data, src_type, 0, src_count);
78 }
79
80 PdCom::SizeInfo
81 Selector::getViewSizeInfo(const PdCom::impl::Variable &variable) const
82 {
83 return variable.size_info;
84 }
85
86 using PdCom::impl::ScalarSelector;
87
88 64 ScalarSelector::ScalarSelector(std::vector<int> indices) :
89 65 indices_(std::move(indices))
90 {
91
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 63 times.
64 if (indices_.empty())
92
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw InvalidArgument("indices must not be empty");
93 63 }
94
95
96 43 std::size_t ScalarSelector::getRequiredSize(const Variable &variable) const
97 {
98 43 return variable.type_info->element_size;
99 }
100
101 PdCom::SizeInfo
102 ScalarSelector::getViewSizeInfo(const PdCom::impl::Variable &) const
103 {
104 return PdCom::SizeInfo::Scalar();
105 }
106
107 namespace {
108 template <typename It>
109 103 size_t product(It begin, It end)
110 {
111 103 size_t ans = 1;
112
2/2
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 103 times.
273 while (begin != end) {
113 85 ans *= *begin;
114 85 ++begin;
115 }
116 103 return ans;
117 }
118 } // namespace
119
120 42 size_t ScalarSelector::getOffset(const Variable &variable) const
121 {
122 42 size_t offset_indices = 0;
123
2/2
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 42 times.
145 for (unsigned int dim = 0; dim < indices_.size(); ++dim) {
124 206 offset_indices += indices_[dim]
125 309 * product(variable.size_info.begin() + 1 + dim,
126 206 variable.size_info.end());
127 }
128 42 return offset_indices;
129 }
130
131
132 Selector::CopyFunctionType
133 63 ScalarSelector::getCopyFunction(const Variable &variable) const
134 {
135
3/4
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 62 times.
128 if (variable.size_info.isScalar() and indices_.size() == 1
136
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 61 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
65 and indices_[0] == 0) {
137
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 return Selector::getCopyFunction(variable);
138 }
139
2/2
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 56 times.
62 else if (variable.size_info.dimension() != indices_.size()) {
140
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12 std::ostringstream os;
141
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
6 os << "Dimension error, expected " << variable.size_info.dimension()
142
2/4
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
6 << " dimensions, got " << indices_.size() << " for variable "
143
3/6
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
6 << variable.getPath();
144
2/4
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 throw InvalidArgument(os.str());
145 }
146 112 auto max_idx = variable.size_info.begin();
147
2/2
✓ Branch 8 taken 122 times.
✓ Branch 9 taken 42 times.
178 for (auto idx = indices_.begin(); idx != indices_.end(); ++idx, ++max_idx) {
148
5/6
✓ Branch 2 taken 122 times.
✗ Branch 3 not taken.
✓ Branch 8 taken 14 times.
✓ Branch 9 taken 108 times.
✓ Branch 10 taken 14 times.
✓ Branch 11 taken 108 times.
122 if (*idx < 0 or *idx >= static_cast<int>(*max_idx)) {
149
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 std::ostringstream os;
150
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 os << "Index " << *idx << " at dimension "
151
1/2
✓ Branch 9 taken 14 times.
✗ Branch 10 not taken.
28 << std::to_string(indices_.end() - 1 - idx)
152
5/10
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 21 taken 14 times.
✗ Branch 22 not taken.
28 << " out of range [0, " << *max_idx << "] for variable"
153
3/6
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 14 times.
✗ Branch 13 not taken.
14 << variable.getPath();
154
2/4
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
14 throw InvalidArgument(os.str());
155 }
156 }
157 42 const size_t el_size = variable.type_info->element_size;
158
159
1/2
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
42 const auto offset_bytes = getOffset(variable) * el_size;
160
161 44 return [offset_bytes, el_size](void *dest, const void *src) {
162
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
44 std::memcpy(
163 dest, reinterpret_cast<const char *>(src) + offset_bytes,
164 el_size);
165
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
86 };
166 }
167
168
169 PdCom::Variable::SetValueFuture ScalarSelector::applySetValue(
170 const Variable &variable,
171 const void *src_data,
172 PdCom::TypeInfo::DataType src_type,
173 size_t src_count) const
174 {
175 if (src_count != 1) {
176 throw PdCom::InvalidArgument(
177 "Expected exactly one value, got " + std::to_string(src_count));
178 }
179 return variable.setValue(
180 src_data, src_type, getOffset(variable), src_count);
181 }
182