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