GCC Code Coverage Report


Directory: ./
File: pdcom5/src/Selector.cpp
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 59 74 79.7%
Branches: 33 118 28.0%

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 42 PdCom::Selector::Selector() : impl_(std::make_shared<impl::Selector>())
34 42 {}
35 24 PdCom::ScalarSelector::ScalarSelector(std::vector<int> indices) :
36 24 PdCom::Selector(std::make_shared<impl::ScalarSelector>(std::move(indices)))
37 24 {}
38
39 PdCom::SizeInfo
40 126 PdCom::Selector::getViewSizeInfo(const PdCom::Variable &variable) const
41 {
42
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 126 times.
126 if (!impl_)
43 throw PdCom::InvalidArgument("impl must not be NULL!");
44
1/2
✓ Branch 10 taken 126 times.
✗ Branch 11 not taken.
126 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 41 Selector::getCopyFunction(const Variable &variable) const
53 {
54 41 const auto count = getRequiredSize(variable);
55 145 return [count](void *dest, const void *src) {
56
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 145 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 145 times.
145 std::memcpy(dest, src, count);
57 186 };
58 }
59
60 82 std::size_t Selector::getRequiredSize(const Variable &variable) const
61 {
62 82 return variable.totalSizeInBytes();
63 }
64
65 36 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
5/6
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 32 times.
36 if (!src_count or src_count > variable.size_info.totalElements()) {
72 throw PdCom::InvalidArgument(
73
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
8 "Range Error, got " + std::to_string(src_count)
74
1/2
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
12 + " Parameter values, expected max. "
75
3/6
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
12 + std::to_string(variable.size_info.totalElements()));
76 }
77 32 return variable.setValue(src_data, src_type, 0, src_count);
78 }
79
80 PdCom::SizeInfo
81 106 Selector::getViewSizeInfo(const PdCom::impl::Variable &variable) const
82 {
83 106 return variable.size_info;
84 }
85
86 using PdCom::impl::ScalarSelector;
87
88 24 ScalarSelector::ScalarSelector(std::vector<int> indices) :
89 24 indices_(std::move(indices))
90 {
91
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
24 if (indices_.empty())
92 throw InvalidArgument("indices must not be empty");
93 24 }
94
95
96 12 std::size_t ScalarSelector::getRequiredSize(const Variable &variable) const
97 {
98 12 return variable.type_info->element_size;
99 }
100
101 PdCom::SizeInfo
102 20 ScalarSelector::getViewSizeInfo(const PdCom::impl::Variable &) const
103 {
104 20 return PdCom::SizeInfo::Scalar();
105 }
106
107 namespace {
108 template <typename It>
109 42 size_t product(It begin, It end)
110 {
111 42 size_t ans = 1;
112
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 42 times.
78 while (begin != end) {
113 18 ans *= *begin;
114 18 ++begin;
115 }
116 42 return ans;
117 }
118 } // namespace
119
120 24 size_t ScalarSelector::getOffset(const Variable &variable) const
121 {
122 24 size_t offset_indices = 0;
123
2/2
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 24 times.
66 for (unsigned int dim = 0; dim < indices_.size(); ++dim) {
124 84 offset_indices += indices_[dim]
125 126 * product(variable.size_info.begin() + 1 + dim,
126 84 variable.size_info.end());
127 }
128 24 return offset_indices;
129 }
130
131
132 Selector::CopyFunctionType
133 12 ScalarSelector::getCopyFunction(const Variable &variable) const
134 {
135
1/4
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
24 if (variable.size_info.isScalar() and indices_.size() == 1
136
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
12 and indices_[0] == 0) {
137 return Selector::getCopyFunction(variable);
138 }
139
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
12 else if (variable.size_info.dimension() != indices_.size()) {
140 std::ostringstream os;
141 os << "Dimension error, expected " << variable.size_info.dimension()
142 << " dimensions, got " << indices_.size() << " for variable "
143 << variable.getPath();
144 throw InvalidArgument(os.str());
145 }
146 24 auto max_idx = variable.size_info.begin();
147
2/2
✓ Branch 8 taken 21 times.
✓ Branch 9 taken 12 times.
33 for (auto idx = indices_.begin(); idx != indices_.end(); ++idx, ++max_idx) {
148
3/6
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 21 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 21 times.
21 if (*idx < 0 or *idx >= static_cast<int>(*max_idx)) {
149 std::ostringstream os;
150 os << "Index " << *idx << " at dimension "
151 << std::to_string(indices_.end() - 1 - idx)
152 << " out of range [0, " << *max_idx << "] for variable"
153 << variable.getPath();
154 throw InvalidArgument(os.str());
155 }
156 }
157 12 const size_t el_size = variable.type_info->element_size;
158
159
1/2
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
12 const auto offset_bytes = getOffset(variable) * el_size;
160
161 28 return [offset_bytes, el_size](void *dest, const void *src) {
162
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
28 std::memcpy(
163 dest, reinterpret_cast<const char *>(src) + offset_bytes,
164 el_size);
165
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
40 };
166 }
167
168
169 12 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 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 12 src_data, src_type, getOffset(variable), src_count);
181 }
182