Directory: | ./ |
---|---|
File: | pdcom5/src/Subscription.cpp |
Date: | 2024-12-15 04:08:34 |
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 |