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 |