GCC Code Coverage Report


Directory: ./
File: pdcom5/src/Subscription.cpp
Date: 2024-11-17 04:08:36
Exec Total Coverage
Lines: 40 85 47.1%
Branches: 21 182 11.5%

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 Subscription::Subscription(Subscription &&s) noexcept :
42 pimpl(std::move(s.pimpl)), state_(s.state_)
43 {
44 if (pimpl)
45 pimpl->This_ = this;
46 s.state_ = State::Invalid;
47 }
48
49
50 56 Subscription::Subscription(
51 PdCom::Subscriber &subscriber,
52 const PdCom::Variable &variable,
53 56 const PdCom::Selector &selector)
54 {
55
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
56 if (!selector.impl_)
56 throw InvalidArgument("Selector must not be null");
57
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
112 pimpl = PdCom::impl::Variable::subscribe(
58 112 this, variable, subscriber, selector);
59
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
56 if (!pimpl)
60 throw InvalidSubscription();
61
1/2
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
56 pimpl->path_ = variable.getPath();
62 56 }
63
64 28 Subscription::Subscription(
65 PdCom::Subscriber &subscriber,
66 PdCom::Process &process,
67 const std::string &path,
68 29 const PdCom::Selector &selector)
69 {
70
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
28 if (!selector.impl_)
71 throw InvalidArgument("Selector must not be null");
72
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
56 pimpl = PdCom::impl::Process::fromUApi(process).subscribe(
73 56 this, path, subscriber, selector);
74
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 27 times.
28 if (!pimpl)
75
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 throw InvalidSubscription();
76
1/2
✓ Branch 5 taken 27 times.
✗ Branch 6 not taken.
27 pimpl->path_ = path;
77 27 }
78
79 67 Subscription &Subscription::operator=(Subscription &&p) noexcept
80 {
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (&p == this)
82 return *this;
83 67 std::swap(p.pimpl, pimpl);
84 67 std::swap(p.state_, state_);
85
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 65 times.
67 if (pimpl)
86 2 pimpl->This_ = this;
87
2/2
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 2 times.
67 if (p.pimpl)
88 65 p.pimpl->This_ = &p;
89 67 return *this;
90 }
91
92 13 void Subscription::poll()
93 {
94
1/2
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 if (pimpl)
95 13 pimpl->poll();
96 else
97 throw InvalidSubscription();
98 13 }
99
100 1277 const void *Subscription::getData() const
101 {
102
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1277 times.
1277 if (!pimpl)
103 throw InvalidSubscription();
104 1277 return pimpl->getData();
105 }
106
107 2508 PdCom::Variable Subscription::getVariable() const
108 {
109
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2508 times.
2508 if (!pimpl)
110 throw InvalidSubscription();
111 2508 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 std::string Subscription::getPath() const
125 {
126 if (!pimpl)
127 throw InvalidSubscription();
128 return pimpl->path_;
129 }
130
131 56 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
1/2
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
112 auto impl_var = fromUApi(var);
138
1/2
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
112 if (const auto p = impl_var->process.lock())
139 return p->subscribe(
140
1/2
✓ Branch 7 taken 56 times.
✗ Branch 8 not taken.
112 subscription, std::move(impl_var), subscriber, selector);
141 else
142 throw ProcessGoneAway();
143 }
144
145
146 namespace {
147 template <class T>
148 inline T convert(T val)
149 {
150 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 print(std::ostream &os, const void *buf, char delim, size_t nelem)
166 {
167 const T *value = reinterpret_cast<const T *>(buf);
168
169 if (nelem > 1)
170 os << '[';
171
172 for (size_t i = 0; i < nelem; ++i) {
173 if (i)
174 os << delim;
175 os << convert(*value++);
176 }
177
178 if (nelem > 1)
179 os << ']';
180 }
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 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 if (getVariable().empty())
202 throw InvalidSubscription();
203
204 printers[getVariable().getTypeInfo().type](
205 os, getData(), delimiter,
206 getVariable().getSizeInfo().totalElements());
207 }
208