YARP
Yet Another Robot Platform
PolyDriver.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
8
9#include <yarp/os/Log.h>
11#include <yarp/os/Property.h>
12
13using namespace yarp::os;
14using namespace yarp::dev;
15
16namespace {
17YARP_LOG_COMPONENT(POLYDRIVER, "yarp.dev.PolyDriver")
18}
19
21 public SearchMonitor
22{
23private:
24 Property comment;
25 Property fallback;
26 Property present;
27 Property actual;
28 Bottle order;
29 int count = 1;
30
31public:
33
34 void report(const SearchReport& report, const char *context) override
35 {
36 std::string ctx = context;
37 std::string key = report.key;
38 std::string prefix;
39
40 prefix = ctx;
41 prefix += ".";
42
43 key = prefix + key;
44 if (key.substr(0,1)==".") {
45 key = key.substr(1,key.length());
46 }
47
48 if (!present.check(key)) {
49 present.put(key,"present");
50 order.addString(key.c_str());
51 }
52
53 if (report.isFound) {
54 actual.put(key,report.value);
55 return;
56 }
57
58 if (report.isComment==true) {
59 comment.put(key,report.value);
60 return;
61 }
62
63 if (report.isDefault==true) {
64 fallback.put(key,report.value);
65 return;
66 }
67 }
68
70 {
71 return order;
72 }
73
74 std::string getComment(const char *option)
75 {
76 std::string desc = comment.find(option).toString();
77 return desc;
78 }
79
80 Value getDefaultValue(const char *option)
81 {
82 return fallback.find(option);
83 }
84
85 Value getValue(const char *option)
86 {
87 return actual.find(option);
88 }
89
90 void addRef()
91 {
92 count++;
93 }
94
96 {
97 count--;
98 return count;
99 }
100
101 int getRef()
102 {
103 return count;
104 }
105};
106
107
108PolyDriver::PolyDriver() :
109 DeviceDriver(),
110 dd(nullptr),
111 mPriv(nullptr)
112{
113}
114
115PolyDriver::PolyDriver(const std::string& txt) :
116 DeviceDriver(),
117 dd(nullptr),
118 mPriv(nullptr)
119{
120 open(txt);
121}
122
124 DeviceDriver(),
125 dd(nullptr),
126 mPriv(nullptr)
127{
128 open(config);
129}
130
132{
133 close();
134 yCAssert(POLYDRIVER, dd == nullptr);
135 yCAssert(POLYDRIVER, mPriv == nullptr);
136}
137
138
139
140bool PolyDriver::open(const std::string& txt)
141{
142 Property p;
143 p.put("device",txt);
144 return open(p);
145}
146
147
149{
150 if (isValid()) {
151 // already open - should close first
152 return false;
153 }
154 if (mPriv==nullptr) {
155 mPriv = new PolyDriver::Private;
156 }
157 yCAssert(POLYDRIVER, mPriv != nullptr);
158 bool removeMonitorAfterwards = false;
159 if (config.getMonitor()==nullptr) {
160 config.setMonitor(mPriv);
161 removeMonitorAfterwards = true;
162 }
163
164 coreOpen(config);
165 mPriv->info.fromString(config.toString());
166 if (removeMonitorAfterwards) {
167 config.setMonitor(nullptr);
168 }
169 return isValid();
170}
171
172
174{
175 bool result = false;
176 if (mPriv!=nullptr) {
177 int ct = mPriv->removeRef();
178 if (ct==0) {
179 yCAssert(POLYDRIVER, mPriv != nullptr);
180 delete mPriv;
181 mPriv = nullptr;
182 if (dd!=nullptr) {
183 result = dd->close();
184 delete dd;
185 dd = nullptr;
186 } else {
187 result = true;
188 }
189 }
190 dd = nullptr;
191 mPriv = nullptr;
192 }
193 return result;
194}
195
197{
198 return dd != nullptr;
199}
200
202{
203 if (!alt.isValid()) {
204 return false;
205 }
206 if (isValid()) {
207 return false;
208 }
209 dd = alt.dd;
210 if (mPriv!=nullptr) {
211 int ct = mPriv->removeRef();
212 if (ct==0) {
213 yCAssert(POLYDRIVER, mPriv != nullptr);
214 delete mPriv;
215 }
216 }
217 mPriv = alt.mPriv;
218 yCAssert(POLYDRIVER, dd != nullptr);
219 yCAssert(POLYDRIVER, mPriv != nullptr);
220 mPriv->addRef();
221 return true;
222}
223
225{
226 if (mPriv==nullptr) {
227 return Bottle::getNullBottle();
228 }
229 return mPriv->getOptions();
230}
231
232std::string PolyDriver::getComment(const char *option)
233{
234 if (mPriv==nullptr) {
235 return {};
236 }
237 return mPriv->getComment(option);
238}
239
241{
242 if (mPriv==nullptr) {
243 return Value::getNullValue();
244 }
245 return mPriv->getDefaultValue(option);
246}
247
248Value PolyDriver::getValue(const char *option)
249{
250 if (mPriv==nullptr) {
251 return Value::getNullValue();
252 }
253 return mPriv->getValue(option);
254}
255
256
257
258bool PolyDriver::coreOpen(yarp::os::Searchable& prop)
259{
260 setId(prop.check("id", prop.check("device", Value("")), "Id assigned to this device").toString());
261 yarp::os::Searchable *config = &prop;
262 Property p;
263 std::string str = prop.toString();
264 Value *part;
265 if (prop.check("device",part)) {
266 str = part->toString();
267 }
268
269 DeviceDriver *driver = nullptr;
270
271 DriverCreator *creator = Drivers::factory().find(str.c_str());
272 if (creator!=nullptr) {
273 Value *val;
274 if (config->check("wrapped",val) && (!creator->getWrapper().empty())) {
275 std::string wrapper = creator->getWrapper();
276 DriverCreator *wrapCreator =
277 Drivers::factory().find(wrapper.c_str());
278 if (wrapCreator!=nullptr) {
279 p.fromString(config->toString());
280 p.unput("wrapped");
281 config = &p;
282 if (wrapCreator!=creator) {
283 p.put("subdevice", str);
284 p.put("device", wrapper);
285 p.setMonitor(prop.getMonitor(),
286 wrapper.c_str()); // pass on any monitoring
287 driver = wrapCreator->create();
288 creator = wrapCreator;
289 } else {
290 // already wrapped
291 driver = creator->create();
292 }
293 }
294 } else {
295 driver = creator->create();
296 }
297 } else {
298 // FIXME do not use yarpdev here
299 yCIError(POLYDRIVER, id(), "Could not find device <%s>", str.c_str());
300 return false;
301 }
302
303 if (driver!=nullptr) {
304 PolyDriver *manager = creator->owner();
305 if (manager!=nullptr) {
306 link(*manager);
307 return true;
308 }
309
310 yCIDebug(POLYDRIVER, id(), "Parameters are %s", config->toString().c_str());
311 driver->setId(id());
312 bool ok = driver->open(*config);
313 if (!ok) {
314 yCIError(POLYDRIVER, id(), "Driver <%s> was found but could not open", config->find("device").toString().c_str());
315 delete driver;
316 driver = nullptr;
317 } else {
319 driver->view(ddd);
320 if(ddd) {
321 if(config->check("allow-deprecated-devices")) {
322 yCIWarning(POLYDRIVER, id(), R"(Device "%s" is deprecated. Opening since the "allow-deprecated-devices" option was passed in the configuration.)", str.c_str());
323 } else {
324 yCIError(POLYDRIVER, id(), R"(Device "%s" is deprecated. Pass the "allow-deprecated-devices" option in the configuration if you want to open it anyway.)", str.c_str());
325 driver->close();
326 delete driver;
327 return false;
328 }
329 }
330 std::string name = creator->getName();
331 std::string wrapper = creator->getWrapper();
332 std::string code = creator->getCode();
333 yCIInfo(POLYDRIVER, id(), "Created %s <%s>. See C++ class %s for documentation.",
334 ((name==wrapper)?"wrapper":"device"),
335 name.c_str(),
336 code.c_str());
337 }
338 dd = driver;
339 return true;
340 }
341
342 return false;
343}
344
345
347{
348 // this is not very careful
349 DeviceDriver *result = dd;
350 dd = nullptr;
351 return result;
352}
353
355{
356 close();
357 this->dd = dd;
358 if (dd!=nullptr) {
359 if (mPriv==nullptr) {
360 mPriv = new PolyDriver::Private;
361 }
362 yCAssert(POLYDRIVER, mPriv != nullptr);
363 if (!own) {
364 mPriv->addRef();
365 }
366 }
367 return true;
368}
369
371{
372 if(isValid()) {
373 return dd->getImplementation();
374 } else {
375 return nullptr;
376 }
377}
Value getValue(const char *option)
Definition: PolyDriver.cpp:85
Value getDefaultValue(const char *option)
Definition: PolyDriver.cpp:80
void report(const SearchReport &report, const char *context) override
Definition: PolyDriver.cpp:34
std::string getComment(const char *option)
Definition: PolyDriver.cpp:74
Interface implemented by deprecated device drivers.
Definition: DeviceDriver.h:136
Interface implemented by all device drivers.
Definition: DeviceDriver.h:30
virtual void setId(const std::string &id)
Set the id for this device.
virtual DeviceDriver * getImplementation()
Some drivers are bureaucrats, pointing at others.
Definition: DeviceDriver.h:112
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
Definition: DeviceDriver.h:53
bool view(T *&x)
Get an interface to the device driver.
Definition: DeviceDriver.h:88
bool close() override
Close the DeviceDriver.
Definition: DeviceDriver.h:59
A base class for factories that create driver objects.
Definition: Drivers.h:27
virtual std::string getName() const =0
Get the common name of the device.
virtual std::string getCode() const =0
Get the name of the C++ class associated with this device.
virtual PolyDriver * owner()
For "links" to other devices.
Definition: Drivers.h:72
virtual std::string getWrapper() const =0
Get the common name of a device that can wrap this one.
virtual DeviceDriver * create() const =0
Create a device.
DriverCreator * find(const char *name)
Find the factory for a named device.
Definition: Drivers.cpp:291
static Drivers & factory()
Get the global factory for devices.
Definition: Drivers.cpp:267
A container for a device driver.
Definition: PolyDriver.h:23
DeviceDriver * take()
Gets the device this object manages.
Definition: PolyDriver.cpp:346
bool close() override
Close the DeviceDriver.
Definition: PolyDriver.cpp:173
bool give(DeviceDriver *dd, bool own)
Take on management of a device.
Definition: PolyDriver.cpp:354
bool link(PolyDriver &alt)
Make this device be a link to an existing one.
Definition: PolyDriver.cpp:201
virtual ~PolyDriver()
Destructor.
Definition: PolyDriver.cpp:131
PolyDriver()
Constructor.
Definition: PolyDriver.cpp:108
std::string getComment(const char *option)
After a call to PolyDriver::open, you can check if the device has documentation on a given option.
Definition: PolyDriver.cpp:232
yarp::os::Value getValue(const char *option)
After a call to PolyDriver::open, you can check what value was found for a particular option,...
Definition: PolyDriver.cpp:248
bool isValid() const
Check if device is valid.
Definition: PolyDriver.cpp:196
DeviceDriver * getImplementation() override
Some drivers are bureaucrats, pointing at others.
Definition: PolyDriver.cpp:370
bool open(const std::string &txt)
Construct and configure a device by its common name.
Definition: PolyDriver.cpp:140
yarp::os::Value getDefaultValue(const char *option)
After a call to PolyDriver::open, you can check if a given option has a particular default value.
Definition: PolyDriver.cpp:240
yarp::os::Bottle getOptions()
After a call to PolyDriver::open, you can get a list of all the options checked by the device.
Definition: PolyDriver.cpp:224
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:64
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
A class for storing options and configuration information.
Definition: Property.h:33
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Property.cpp:1051
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1063
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:1015
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Property.cpp:1041
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
Definition: Property.cpp:1046
A base class for nested structures that can be searched.
Definition: Searchable.h:56
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
A single value (typically within a Bottle).
Definition: Value.h:43
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:356
std::string toString(const T &value)
convert an arbitrary type to string.
#define yCAssert(component, x)
Definition: LogComponent.h:240
#define yCIError(component, id,...)
Definition: LogComponent.h:223
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:76
#define yCIInfo(component, id,...)
Definition: LogComponent.h:181
#define yCIDebug(component, id,...)
Definition: LogComponent.h:138
#define yCIWarning(component, id,...)
Definition: LogComponent.h:202
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.