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  yarp::os::Searchable *config = &prop;
261  Property p;
262  std::string str = prop.toString();
263  Value *part;
264  if (prop.check("device",part)) {
265  str = part->toString();
266  }
267 
268  DeviceDriver *driver = nullptr;
269 
270  DriverCreator *creator = Drivers::factory().find(str.c_str());
271  if (creator!=nullptr) {
272  Value *val;
273  if (config->check("wrapped",val)&&(creator->getWrapper()!="")) {
274  std::string wrapper = creator->getWrapper();
275  DriverCreator *wrapCreator =
276  Drivers::factory().find(wrapper.c_str());
277  if (wrapCreator!=nullptr) {
278  p.fromString(config->toString());
279  p.unput("wrapped");
280  config = &p;
281  if (wrapCreator!=creator) {
282  p.put("subdevice",str);
283  p.put("device",wrapper);
284  p.setMonitor(prop.getMonitor(),
285  wrapper.c_str()); // pass on any monitoring
286  driver = wrapCreator->create();
287  creator = wrapCreator;
288  } else {
289  // already wrapped
290  driver = creator->create();
291  }
292  }
293  } else {
294  driver = creator->create();
295  }
296  } else {
297  // FIXME do not use yarpdev here
298  yCError(POLYDRIVER, "Could not find device <%s>", str.c_str());
299  return false;
300  }
301 
302  if (driver!=nullptr) {
303  PolyDriver *manager = creator->owner();
304  if (manager!=nullptr) {
305  link(*manager);
306  return true;
307  }
308 
309  yCTrace(POLYDRIVER, "Parameters are %s", config->toString().c_str());
310  bool ok = driver->open(*config);
311  if (!ok) {
312  yCError(POLYDRIVER, "Driver <%s> was found but could not open", config->find("device").toString().c_str());
313  delete driver;
314  driver = nullptr;
315  } else {
316  yarp::dev::DeprecatedDeviceDriver *ddd = nullptr;
317  driver->view(ddd);
318  if(ddd) {
319  if(config->check("allow-deprecated-devices")) {
320  yCWarning(POLYDRIVER, R"(Device "%s" is deprecated. Opening since the "allow-deprecated-devices" option was passed in the configuration.)", str.c_str());
321  } else {
322  yCError(POLYDRIVER, R"(Device "%s" is deprecated. Pass the "allow-deprecated-devices" option in the configuration if you want to open it anyway.)", str.c_str());
323  driver->close();
324  delete driver;
325  return false;
326  }
327  }
328  std::string name = creator->getName();
329  std::string wrapper = creator->getWrapper();
330  std::string code = creator->getCode();
331  yCInfo(POLYDRIVER, "Created %s <%s>. See C++ class %s for documentation.",
332  ((name==wrapper)?"wrapper":"device"),
333  name.c_str(),
334  code.c_str());
335  }
336  dd = driver;
337  return true;
338  }
339 
340  return false;
341 }
342 
343 
345 {
346  // this is not very careful
347  DeviceDriver *result = dd;
348  dd = nullptr;
349  return result;
350 }
351 
352 bool PolyDriver::give(DeviceDriver *dd, bool own)
353 {
354  close();
355  this->dd = dd;
356  if (dd!=nullptr) {
357  if (mPriv==nullptr) {
358  mPriv = new PolyDriver::Private;
359  }
360  yCAssert(POLYDRIVER, mPriv != nullptr);
361  if (!own) {
362  mPriv->addRef();
363  }
364  }
365  return true;
366 }
367 
369 {
370  if(isValid()) {
371  return dd->getImplementation();
372  } else {
373  return nullptr;
374  }
375 }
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:116
Interface implemented by all device drivers.
Definition: DeviceDriver.h:35
virtual DeviceDriver * getImplementation()
Some drivers are bureaucrats, pointing at others.
Definition: DeviceDriver.h:98
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
Definition: DeviceDriver.h:55
bool view(T *&x)
Get an interface to the device driver.
Definition: DeviceDriver.h:74
bool close() override
Close the DeviceDriver.
Definition: DeviceDriver.h:61
A base class for factories that create driver objects.
Definition: Drivers.h:28
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:73
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:275
static Drivers & factory()
Get the global factory for devices.
Definition: Drivers.cpp:251
A container for a device driver.
Definition: PolyDriver.h:24
DeviceDriver * take()
Gets the device this object manages.
Definition: PolyDriver.cpp:344
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:352
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:55
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:368
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:74
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:34
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:66
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:45
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:356
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCAssert(component, x)
Definition: LogComponent.h:169
#define yCTrace(component,...)
Definition: LogComponent.h:85
#define yCWarning(component,...)
Definition: LogComponent.h:143
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
An interface to the operating system, including Port based communication.