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