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 
7 #include <yarp/dev/PolyDriver.h>
8 
9 #include <yarp/os/Log.h>
10 #include <yarp/os/LogComponent.h>
11 #include <yarp/os/Property.h>
12 
13 using namespace yarp::os;
14 using namespace yarp::dev;
15 
16 namespace {
17 YARP_LOG_COMPONENT(POLYDRIVER, "yarp.dev.PolyDriver")
18 }
19 
21  public SearchMonitor
22 {
23 private:
24  Property comment;
25  Property fallback;
26  Property present;
27  Property actual;
28  Bottle order;
29  int count = 1;
30 
31 public:
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 
95  int removeRef()
96  {
97  count--;
98  return count;
99  }
100 
101  int getRef()
102  {
103  return count;
104  }
105 };
106 
107 
108 PolyDriver::PolyDriver() :
109  DeviceDriver(),
110  dd(nullptr),
111  mPriv(nullptr)
112 {
113 }
114 
115 PolyDriver::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 
140 bool 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 
232 std::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 
248 Value PolyDriver::getValue(const char *option)
249 {
250  if (mPriv==nullptr) {
251  return Value::getNullValue();
252  }
253  return mPriv->getValue(option);
254 }
255 
256 
257 
258 bool 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 {
318  yarp::dev::DeprecatedDeviceDriver *ddd = nullptr;
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 
354 bool PolyDriver::give(DeviceDriver *dd, bool own)
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 DeviceDriver * create() const =0
Create a 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.
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
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
Definition: DeviceDriver.h:53
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
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:73
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:63
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
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.
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.