YARP
Yet Another Robot Platform
Bottle.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * Copyright (C) 2006, 2008 Arjan Gijsberts
5  * All rights reserved.
6  *
7  * This software may be modified and distributed under the terms of the
8  * BSD-3-Clause license. See the accompanying LICENSE file for details.
9  */
10 
11 #include <yarp/os/Bottle.h>
12 #include <yarp/os/DummyConnector.h>
13 #include <yarp/os/NetType.h>
16 
17 
18 using yarp::os::Bottle;
21 using yarp::os::Property;
22 using yarp::os::Value;
25 
26 namespace {
27 YARP_OS_LOG_COMPONENT(BOTTLE, "yarp.os.Bottle")
28 }
29 
30 // FIXME this can be constexpr, but swig 3.0.8 is not happy
31 const Bottle::size_type Bottle::npos = static_cast<Bottle::size_type>(-1);
32 
33 class NullBottle : public Bottle
34 {
35 public:
37  Bottle()
38  {
39  setReadOnly(true);
40  }
41  bool isNull() const override
42  {
43  return true;
44  }
45 };
46 
47 Bottle::Bottle() :
48  Portable(),
49  Searchable(),
50  implementation(new BottleImpl(this))
51 {
52  yCAssert(BOTTLE, implementation != nullptr);
53  implementation->invalid = false;
54  implementation->ro = false;
55 }
56 
57 Bottle::Bottle(const std::string& text) :
58  Portable(),
59  Searchable(),
60  implementation(new BottleImpl(this))
61 {
62  yCAssert(BOTTLE, implementation != nullptr);
63  implementation->invalid = false;
64  implementation->ro = false;
65  fromString(text);
66 }
67 
68 Bottle::Bottle(const Bottle& rhs) :
69  Portable(),
70  Searchable(rhs),
71  implementation(new BottleImpl(this))
72 {
73  yCAssert(BOTTLE, implementation != nullptr);
74  implementation->invalid = false;
75  implementation->ro = false;
76  copy(rhs);
77 }
78 
79 Bottle::Bottle(Bottle&& rhs) noexcept :
80  Portable(std::move(static_cast<Portable&>(rhs))),
81  Searchable(std::move(static_cast<Searchable&>(rhs))),
82  implementation(rhs.implementation)
83 {
84  implementation->parent = this;
85  rhs.implementation = new BottleImpl(&rhs);
86 }
87 
88 Bottle::Bottle(std::initializer_list<Value> values) :
89  Portable(),
90  Searchable(),
91  implementation(new BottleImpl(this))
92 {
93  yCAssert(BOTTLE, implementation != nullptr);
94  implementation->invalid = false;
95  implementation->ro = false;
96 
97  for (const auto& val : values) {
98  add(val);
99  }
100 }
101 
103 {
104  if (&rhs != this) {
105  implementation->edit();
106  copy(rhs);
107  }
108  return *this;
109 }
110 
112 {
113  std::swap(implementation, rhs.implementation);
114  implementation->parent = this;
115  rhs.implementation->parent = &rhs;
116  return *this;
117 }
118 
120 {
121  delete implementation;
122 }
123 
125 {
126  implementation->edit();
127  implementation->invalid = false;
128  implementation->clear();
129 }
130 
131 void Bottle::addInt8(std::int8_t x)
132 {
133  implementation->edit();
134  implementation->addInt8(x);
135 }
136 
137 void Bottle::addInt16(std::int16_t x)
138 {
139  implementation->edit();
140  implementation->addInt16(x);
141 }
142 
143 void Bottle::addInt32(std::int32_t x)
144 {
145  implementation->edit();
146  implementation->addInt32(x);
147 }
148 
149 void Bottle::addInt64(std::int64_t x)
150 {
151  implementation->edit();
152  implementation->addInt64(x);
153 }
154 
156 {
157  implementation->edit();
158  implementation->addFloat32(x);
159 }
160 
162 {
163  implementation->edit();
164  implementation->addFloat64(x);
165 }
166 
167 void Bottle::addVocab(int x)
168 {
169  implementation->edit();
170  implementation->addVocab(x);
171 }
172 
173 void Bottle::addString(const char* str)
174 {
175  implementation->edit();
176  implementation->addString(str);
177 }
178 
179 void Bottle::addString(const std::string& str)
180 {
181  implementation->edit();
182  implementation->addString(str);
183 }
184 
186 {
187  implementation->edit();
188  return implementation->addList();
189 }
190 
192 {
193  implementation->edit();
194  return implementation->addDict();
195 }
196 
198 {
199  implementation->edit();
200  Storable* stb = implementation->pop();
201  Value val(*stb);
202  // here we take responsibility for deallocation of the Storable instance
203  delete stb;
204  return val;
205 }
206 
207 void Bottle::fromString(const std::string& text)
208 {
209  implementation->edit();
210  implementation->invalid = false;
211  implementation->fromString(text);
212 }
213 
214 std::string Bottle::toString() const
215 {
216  return implementation->toString();
217 }
218 
219 void Bottle::fromBinary(const char* buf, size_t len)
220 {
221  implementation->edit();
222  implementation->fromBinary(buf, len);
223 }
224 
225 const char* Bottle::toBinary(size_t* size)
226 {
227  if (size != nullptr) {
228  *size = implementation->byteCount();
229  }
230  return implementation->getBytes();
231 }
232 
233 bool Bottle::write(ConnectionWriter& writer) const
234 {
235  return implementation->write(writer);
236 }
237 
239 {
240  implementation->onCommencement();
241 }
242 
244 {
245  implementation->edit();
246  return implementation->read(reader);
247 }
248 
249 Value& Bottle::get(size_t index) const
250 {
251  return implementation->get(index);
252 }
253 
254 size_t Bottle::size() const
255 {
256  return static_cast<int>(implementation->size());
257 }
258 
260 {
261  implementation->hasChanged();
262 }
263 
265 {
266  return implementation->getSpecialization();
267 }
268 
269 void Bottle::copy(const Bottle& alt, size_t first, size_t len)
270 {
271  implementation->edit();
272  if (alt.isNull()) {
273  clear();
274  implementation->invalid = true;
275  return;
276  }
277  implementation->copyRange(alt.implementation, first, len);
278 }
279 
280 bool Bottle::check(const std::string& key) const
281 {
282  Bottle& val = findGroup(key);
283  if (!val.isNull()) {
284  return true;
285  }
286  Value& val2 = find(key);
287  return !val2.isNull();
288 }
289 
290 Value& Bottle::find(const std::string& key) const
291 {
292  Value& val = implementation->findBit(key);
293 
294  if (getMonitor() != nullptr) {
295  SearchReport report;
296  report.key = key;
297  report.isFound = !val.isNull();
298  report.value = val.toString();
299  reportToMonitor(report);
300  }
301 
302  return val;
303 }
304 
305 Bottle& Bottle::findGroup(const std::string& key) const
306 {
307  Value& bb = implementation->findGroupBit(key);
308 
309  if (getMonitor() != nullptr) {
310  SearchReport report;
311  report.key = key;
312  report.isGroup = true;
313  if (bb.isList()) {
314  report.isFound = true;
315  report.value = bb.toString();
316  }
317  reportToMonitor(report);
318  if (bb.isList()) {
319  std::string context = getMonitorContext();
320  context += ".";
321  context += key;
322  bb.asList()->setMonitor(getMonitor(),
323  context.c_str()); // pass on any monitoring
324  }
325  }
326 
327  if (bb.isList()) {
328  return *(bb.asList());
329  }
330  return getNullBottle();
331 }
332 
333 void Bottle::add(Value* value)
334 {
335  implementation->edit();
336  implementation->addBit(value);
337 }
338 
339 void Bottle::add(const Value& value)
340 {
341  implementation->edit();
342  implementation->addBit(value);
343 }
344 
346 {
347  static NullBottle bottleNull;
348  return bottleNull;
349 }
350 
351 bool Bottle::operator==(const Bottle& alt) const
352 {
353  return toString() == alt.toString();
354 }
355 
356 bool Bottle::write(PortReader& reader, bool textMode)
357 {
358  DummyConnector con;
359  con.setTextMode(textMode);
360  write(con.getWriter());
361  return reader.read(con.getReader());
362 }
363 
364 bool Bottle::read(const PortWriter& writer, bool textMode)
365 {
366  implementation->edit();
367  DummyConnector con;
368  con.setTextMode(textMode);
369  writer.write(con.getWriter());
370  return read(con.getReader());
371 }
372 
373 bool Bottle::isNull() const
374 {
375  return implementation->invalid;
376 }
377 
378 bool Bottle::operator!=(const Bottle& alt) const
379 {
380  return !((*this) == alt);
381 }
382 
383 void Bottle::append(const Bottle& alt)
384 {
385  implementation->edit();
386  for (size_t i = 0; i < alt.size(); i++) {
387  add(alt.get(i));
388  }
389 }
390 
392 {
393  Bottle b;
394  if (isNull()) {
395  return *this;
396  }
397  b.copy(*this, 1, size() - 1);
398  return b;
399 }
400 
401 std::string Bottle::toString(int x)
402 {
404 }
405 
406 std::string Bottle::describeBottleCode(int code)
407 {
408  int unit = code & ~(BOTTLE_TAG_LIST | BOTTLE_TAG_DICT);
409  std::string unitName = "mixed";
410  switch (unit) {
411  case 0:
412  unitName = "mixed";
413  break;
414  case BOTTLE_TAG_INT32:
415  unitName = "int";
416  break;
417  case BOTTLE_TAG_VOCAB32:
418  unitName = "vocab";
419  break;
420  case BOTTLE_TAG_FLOAT64:
421  unitName = "float";
422  break;
423  case BOTTLE_TAG_STRING:
424  unitName = "string";
425  break;
426  case BOTTLE_TAG_BLOB:
427  unitName = "blob";
428  break;
429  default:
430  unitName = "unknown";
431  break;
432  }
433  std::string result = unitName;
434  if ((code & BOTTLE_TAG_LIST) != 0) {
435  result = "list of " + unitName;
436  } else if ((code & BOTTLE_TAG_DICT) != 0) {
437  result = "dict of " + unitName;
438  }
439  return result;
440 }
441 
442 void Bottle::setReadOnly(bool readOnly)
443 {
444  implementation->ro = readOnly;
445 }
#define BOTTLE_TAG_FLOAT64
Definition: Bottle.h:27
#define BOTTLE_TAG_DICT
Definition: Bottle.h:31
#define BOTTLE_TAG_INT32
Definition: Bottle.h:23
#define BOTTLE_TAG_STRING
Definition: Bottle.h:28
#define BOTTLE_TAG_BLOB
Definition: Bottle.h:29
#define BOTTLE_TAG_LIST
Definition: Bottle.h:30
#define BOTTLE_TAG_VOCAB32
Definition: Bottle.h:25
RandScalar * implementation(void *t)
Definition: RandnScalar.cpp:20
bool isNull() const override
Checks if the object is invalid.
Definition: Bottle.cpp:41
NullBottle()
Definition: Bottle.cpp:36
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:76
static Bottle & getNullBottle()
A special Bottle with no content.
Definition: Bottle.cpp:345
void add(const Value &value)
Add a Value to the bottle, at the end of the list.
Definition: Bottle.cpp:339
static std::string describeBottleCode(int code)
Convert a numeric bottle code to a string.
Definition: Bottle.cpp:406
Value pop()
Removes a Value v from the end of the list and returns this value.
Definition: Bottle.cpp:197
Bottle & operator=(const Bottle &rhs)
Copy assignment operator.
Definition: Bottle.cpp:102
void fromString(const std::string &text)
Initializes bottle from a string.
Definition: Bottle.cpp:207
virtual ~Bottle()
Destructor.
Definition: Bottle.cpp:119
void append(const Bottle &alt)
Append the content of the given bottle to the current list.
Definition: Bottle.cpp:383
int getSpecialization()
Get numeric bottle code for this bottle.
Definition: Bottle.cpp:264
Property & addDict()
Places an empty key/value object in the bottle, at the end of the list.
Definition: Bottle.cpp:191
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
Definition: Bottle.cpp:185
virtual Bottle & findGroup(const std::string &key) const=0
Gets a list corresponding to a given keyword.
void addInt8(std::int8_t x)
Places a 8-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:131
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:243
void addFloat64(yarp::conf::float64_t x)
Places a 64-bit floating point number in the bottle, at the end of the list.
Definition: Bottle.cpp:161
void addFloat32(yarp::conf::float32_t x)
Places a 32-bit floating point number in the bottle, at the end of the list.
Definition: Bottle.cpp:155
void addVocab(int x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:167
void setReadOnly(bool readOnly)
Definition: Bottle.cpp:442
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
void copy(const Bottle &alt, size_type first=0, size_type len=npos)
Copy all or part of another Bottle.
Definition: Bottle.cpp:269
Bottle tail() const
Get all but the first element of a bottle.
Definition: Bottle.cpp:391
bool operator==(const Bottle &alt) const
Equality test.
Definition: Bottle.cpp:351
void onCommencement() const override
This is called when the port is about to begin writing operations.
Definition: Bottle.cpp:238
virtual bool check(const std::string &key) const=0
Check if there exists a property of the given name.
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:124
void addInt16(std::int16_t x)
Places a 16-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:137
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:233
void addInt64(std::int64_t x)
Places a 64-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:149
bool operator!=(const Bottle &alt) const
Inequality test.
Definition: Bottle.cpp:378
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:143
bool isNull() const override
Checks if the object is invalid.
Definition: Bottle.cpp:373
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:173
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:214
void hasChanged()
Declare that the content of the Bottle has been changed.
Definition: Bottle.cpp:259
const char * toBinary(size_t *size=nullptr)
Returns binary representation of bottle.
Definition: Bottle.cpp:225
void fromBinary(const char *buf, size_t len)
Initializes bottle from a binary representation.
Definition: Bottle.cpp:219
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:290
Bottle()
Constructor.
Definition: Bottle.cpp:47
An interface for reading from a network connection.
An interface for writing to a network connection.
A dummy connection to test yarp::os::Portable implementations.
ConnectionWriter & getWriter()
Get the dummy ConnectionWriter loaded with whatever was written the ConnectionWriter since it was las...
void setTextMode(bool textmode)
Set the textMode of the dummy connection.
ConnectionReader & getReader(ConnectionWriter *replyWriter=nullptr)
Get the dummy ConnectionReader loaded with whatever was written the ConnectionWriter since it was las...
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition: PortReader.h:28
virtual bool read(ConnectionReader &reader)=0
Read this object from a network connection.
Interface implemented by all objects that can write themselves to the network, such as Bottle objects...
Definition: PortWriter.h:27
virtual bool write(ConnectionWriter &writer) const =0
Write this object to a network connection.
This is a base class for objects that can be both read from and be written to the YARP network.
Definition: Portable.h:29
A class for storing options and configuration information.
Definition: Property.h:37
A base class for nested structures that can be searched.
Definition: Searchable.h:69
A single value (typically within a Bottle).
Definition: Value.h:47
virtual bool isList() const
Checks if value is a list.
Definition: Value.cpp:165
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:243
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:359
bool isNull() const override
Checks if the object is invalid.
Definition: Value.cpp:383
A flexible data format for holding a bunch of numbers and strings.
Definition: BottleImpl.h:36
A single item in a Bottle.
Definition: Storable.h:47
#define yCAssert(component, x)
Definition: LogComponent.h:172
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:37
std::string to_string(Integer x)
Definition: numeric.h:118
double float64_t
Definition: numeric.h:80
float float32_t
Definition: numeric.h:79