GCC Code Coverage Report


Directory: ./
File: src/Subscription.cpp
Date: 2024-11-05 15:23:15
Exec Total Coverage
Lines: 73 88 83.0%
Branches: 55 182 30.2%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2021 Richard Hacker (lerichi at gmx dot net),
4 * Florian Pose (fp at igh dot de),
5 * Bjarne von Horn (vh at igh dot de).
6 *
7 * This file is part of the PdCom library.
8 *
9 * The PdCom library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at your
12 * option) any later version.
13 *
14 * The PdCom library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the PdCom library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "Subscription.h"
25
26 #include "Process.h"
27 #include "TemplateVodoo.inc"
28 #include "Variable.h"
29
30 #include <algorithm>
31 #include <array>
32 #include <cstring>
33 #include <pdcom5/Exception.h>
34 #include <pdcom5/Subscriber.h>
35 #include <pdcom5/Subscription.h>
36 #include <sstream>
37
38
39 using PdCom::Subscription;
40
41 3 Subscription::Subscription(Subscription &&s) noexcept :
42 3 pimpl(std::move(s.pimpl)), state_(s.state_)
43 {
44
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (pimpl)
45 1 pimpl->This_ = this;
46 3 s.state_ = State::Invalid;
47 3 }
48
49
50 61 Subscription::Subscription(
51 PdCom::Subscriber &subscriber,
52 const PdCom::Variable &variable,
53 72 const PdCom::Selector &selector)
54 {
55
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 61 times.
61 if (!selector.impl_)
56 throw InvalidArgument("Selector must not be null");
57
2/2
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 10 times.
112 pimpl = PdCom::impl::Variable::subscribe(
58 112 this, variable, subscriber, selector);
59
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 50 times.
51 if (!pimpl)
60
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw InvalidSubscription();
61
1/2
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
50 pimpl->path_ = variable.getPath();
62 50 }
63
64 50 Subscription::Subscription(
65 PdCom::Subscriber &subscriber,
66 PdCom::Process &process,
67 const std::string &path,
68 51 const PdCom::Selector &selector)
69 {
70
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if (!selector.impl_)
71 throw InvalidArgument("Selector must not be null");
72
1/2
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
100 pimpl = PdCom::impl::Process::fromUApi(process).subscribe(
73 100 this, path, subscriber, selector);
74
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 49 times.
50 if (!pimpl)
75
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw InvalidSubscription();
76
1/2
✓ Branch 5 taken 49 times.
✗ Branch 6 not taken.
49 pimpl->path_ = path;
77 49 }
78
79 9 Subscription &Subscription::operator=(Subscription &&p) noexcept
80 {
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (&p == this)
82 return *this;
83 9 std::swap(p.pimpl, pimpl);
84 9 std::swap(p.state_, state_);
85
2/2
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
9 if (pimpl)
86 6 pimpl->This_ = this;
87
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 5 times.
9 if (p.pimpl)
88 4 p.pimpl->This_ = &p;
89 9 return *this;
90 }
91
92 24 void Subscription::poll()
93 {
94
2/2
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 1 times.
24 if (pimpl)
95 23 pimpl->poll();
96 else
97
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw InvalidSubscription();
98 13 }
99
100 89 const void *Subscription::getData() const
101 {
102
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 88 times.
89 if (!pimpl)
103
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw InvalidSubscription();
104 88 return pimpl->getData();
105 }
106
107 114 PdCom::Variable Subscription::getVariable() const
108 {
109
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 112 times.
114 if (!pimpl)
110
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 throw InvalidSubscription();
111 112 return PdCom::impl::Variable::toUApi(pimpl->variable_);
112 }
113
114 PdCom::Process *Subscription::getProcess() const
115 {
116 if (!pimpl)
117 throw InvalidSubscription();
118 if (auto p = pimpl->process_.lock()) {
119 return p->This;
120 }
121 throw ProcessGoneAway();
122 }
123
124 2 std::string Subscription::getPath() const
125 {
126
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!pimpl)
127 throw InvalidSubscription();
128 2 return pimpl->path_;
129 }
130
131 61 std::shared_ptr<PdCom::impl::Subscription> PdCom::impl::Variable::subscribe(
132 PdCom::Subscription *subscription,
133 const PdCom::Variable &var,
134 PdCom::Subscriber &subscriber,
135 const PdCom::Selector &selector)
136 {
137
2/2
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 6 times.
116 auto impl_var = fromUApi(var);
138
1/2
✓ Branch 4 taken 55 times.
✗ Branch 5 not taken.
110 if (const auto p = impl_var->process.lock())
139 return p->subscribe(
140
2/2
✓ Branch 7 taken 51 times.
✓ Branch 8 taken 4 times.
106 subscription, std::move(impl_var), subscriber, selector);
141 else
142 throw ProcessGoneAway();
143 }
144
145
146 namespace {
147 template <class T>
148 6 inline T convert(T val)
149 {
150 6 return val;
151 }
152 inline int convert(int8_t val)
153 {
154 return val;
155 }
156 inline unsigned convert(uint8_t val)
157 {
158 return val;
159 }
160
161 template <class T>
162 struct Printer
163 {
164 static void
165 2 print(std::ostream &os, const void *buf, char delim, size_t nelem)
166 {
167 2 const T *value = reinterpret_cast<const T *>(buf);
168
169
2/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
2 if (nelem > 1)
170 1 os << '[';
171
172
4/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
8 for (size_t i = 0; i < nelem; ++i) {
173
3/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
6 if (i)
174 4 os << delim;
175
0/2
✗ Branch 68 not taken.
✗ Branch 69 not taken.
6 os << convert(*value++);
176 }
177
178
2/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
2 if (nelem > 1)
179 1 os << ']';
180 2 }
181 };
182
183 using printFn = void (*)(std::ostream &, const void *, char, size_t);
184
185 template <PdCom::TypeInfo::DataType... src_types>
186 constexpr std::array<printFn, sizeof...(src_types)>
187 getPrintFns(sequence<src_types...>)
188 {
189 return {{Printer<typename PdCom::details::DataTypeTraits<
190 src_types>::value_type>::print...}};
191 }
192 } // namespace
193
194 12 void PdCom::Subscription::print(std::ostream &os, char delimiter) const
195 {
196 static constexpr auto printers = getPrintFns(DataTypeSequence {});
197 static_assert(
198 printers.size() == DataTypeCount,
199 "Print function vector size mismatch");
200
201
2/2
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 2 times.
12 if (getVariable().empty())
202
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 throw InvalidSubscription();
203
204
4/8
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
8 printers[getVariable().getTypeInfo().type](
205 2 os, getData(), delimiter,
206
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 getVariable().getSizeInfo().totalElements());
207 2 }
208