YARP
Yet Another Robot Platform
WireReader.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
7 
8 using namespace yarp::os::idl;
9 using namespace yarp::os;
10 
11 namespace {
12 constexpr yarp::conf::vocab32_t VOCAB_FAIL = yarp::os::createVocab32('f', 'a', 'i', 'l');
14 } // namespace
15 
17  reader(reader)
18 {
19  reader.convertTextMode();
20 }
21 
23 {
24  if (state->need_ok) {
25  std::int32_t dummy;
26  readVocab32(dummy);
27  state->need_ok = false;
28  }
29  if (flush_if_needed) {
30  clear();
31  }
32 }
33 
35 {
36  expecting = true;
37  flush_if_needed = true;
38 }
39 
41 {
42  expecting = false;
43 }
44 
46 {
47  support_get_mode = true;
48 }
49 
51 {
52  size_t pending = reader.getSize();
53  if (pending > 0) {
54  while (pending > 0) {
55  char buf[1000];
56  size_t next = (pending < sizeof(buf)) ? pending : sizeof(buf);
57  reader.expectBlock(&buf[0], next);
58  pending -= next;
59  }
60  return true;
61  }
62  return false;
63 }
64 
66 {
67  clear();
68  Bottle b("[fail]");
69  b.write(getWriter());
70 }
71 
73 {
74  return obj.read(*this);
75 }
76 
78 {
79  return obj.read(reader);
80 }
81 
83 {
84  return obj.read(reader);
85 }
86 
88 {
89  return obj.read(reader);
90 }
91 
92 bool WireReader::readBool(bool& x)
93 {
94  if (state->code < 0) {
95  if (noMore()) {
96  return false;
97  }
98  std::int32_t tag = reader.expectInt32();
99  if (tag != BOTTLE_TAG_INT32 && tag != BOTTLE_TAG_VOCAB32) {
100  return false;
101  }
102  }
103  if (noMore()) {
104  return false;
105  }
106  std::int32_t v = reader.expectInt32();
107  x = (v != 0) && (v != VOCAB_FAIL);
108  state->len--;
109  return !reader.isError();
110 }
111 
112 bool WireReader::readI8(std::int8_t& x)
113 {
114  std::int32_t tag = state->code;
115  if (tag < 0) {
116  if (noMore()) {
117  return false;
118  }
119  tag = reader.expectInt32();
120  }
121  if (noMore()) {
122  return false;
123  }
124  switch (tag) {
125  case BOTTLE_TAG_INT8:
126  x = reader.expectInt8();
127  break;
128  case BOTTLE_TAG_INT32:
129  x = static_cast<std::int8_t>(reader.expectInt32());
130  break;
131  default:
132  return false;
133  }
134 
135  state->len--;
136  return !reader.isError();
137 }
138 
139 bool WireReader::readI16(std::int16_t& x)
140 {
141  std::int32_t tag = state->code;
142  if (tag < 0) {
143  if (noMore()) {
144  return false;
145  }
146  tag = reader.expectInt32();
147  }
148  if (noMore()) {
149  return false;
150  }
151  switch (tag) {
152  case BOTTLE_TAG_INT8:
153  x = static_cast<std::int16_t>(reader.expectInt8());
154  break;
155  case BOTTLE_TAG_INT16:
156  x = reader.expectInt16();
157  break;
158  case BOTTLE_TAG_INT32:
159  x = static_cast<std::int16_t>(reader.expectInt32());
160  break;
161  default:
162  return false;
163  }
164 
165  state->len--;
166  return !reader.isError();
167 }
168 
169 bool WireReader::readI32(std::int32_t& x)
170 {
171  std::int32_t tag = state->code;
172  if (tag < 0) {
173  if (noMore()) {
174  return false;
175  }
176  tag = reader.expectInt32();
177  }
178  if (noMore()) {
179  return false;
180  }
181  switch (tag) {
182  case BOTTLE_TAG_INT8:
183  x = static_cast<std::int32_t>(reader.expectInt8());
184  break;
185  case BOTTLE_TAG_INT16:
186  x = static_cast<std::int32_t>(reader.expectInt16());
187  break;
188  case BOTTLE_TAG_INT32:
189  case BOTTLE_TAG_VOCAB32:
190  x = reader.expectInt32();
191  break;
192  default:
193  return false;
194  }
195  state->len--;
196  return !reader.isError();
197 }
198 
199 bool WireReader::readI64(std::int64_t& x)
200 {
201  std::int32_t tag = state->code;
202  if (tag < 0) {
203  if (noMore()) {
204  return false;
205  }
206  tag = reader.expectInt32();
207  }
208  if (noMore()) {
209  return false;
210  }
211  switch (tag) {
212  case BOTTLE_TAG_INT8:
213  x = static_cast<std::int64_t>(reader.expectInt8());
214  break;
215  case BOTTLE_TAG_INT16:
216  x = static_cast<std::int64_t>(reader.expectInt16());
217  break;
218  case BOTTLE_TAG_INT32:
219  x = static_cast<std::int64_t>(reader.expectInt32());
220  break;
221  case BOTTLE_TAG_INT64:
222  x = reader.expectInt64();
223  break;
224  default:
225  return false;
226  }
227 
228  state->len--;
229  return !reader.isError();
230 }
231 
233 {
234  std::int32_t tag = state->code;
235  if (tag < 0) {
236  if (noMore()) {
237  return false;
238  }
239  tag = reader.expectInt32();
240  }
241  if (noMore()) {
242  return false;
243  }
244  switch (tag) {
245  case BOTTLE_TAG_INT8:
246  x = static_cast<yarp::conf::float32_t>(reader.expectInt8());
247  break;
248  case BOTTLE_TAG_INT16:
249  x = static_cast<yarp::conf::float32_t>(reader.expectInt16());
250  break;
251  case BOTTLE_TAG_INT32:
252  x = static_cast<yarp::conf::float32_t>(reader.expectInt32());
253  break;
254  case BOTTLE_TAG_INT64:
255  x = static_cast<yarp::conf::float32_t>(reader.expectInt64());
256  break;
257  case BOTTLE_TAG_FLOAT32:
258  x = reader.expectFloat32();
259  break;
260  case BOTTLE_TAG_FLOAT64:
261  x = static_cast<yarp::conf::float32_t>(reader.expectFloat64());
262  break;
263  default:
264  return false;
265  }
266 
267  state->len--;
268  return !reader.isError();
269 }
270 
272 {
273  std::int32_t tag = state->code;
274  if (tag < 0) {
275  if (noMore()) {
276  return false;
277  }
278  tag = reader.expectInt32();
279  }
280  if (noMore()) {
281  return false;
282  }
283  switch (tag) {
284  case BOTTLE_TAG_INT8:
285  x = static_cast<yarp::conf::float64_t>(reader.expectInt8());
286  break;
287  case BOTTLE_TAG_INT16:
288  x = static_cast<yarp::conf::float64_t>(reader.expectInt16());
289  break;
290  case BOTTLE_TAG_INT32:
291  x = static_cast<yarp::conf::float64_t>(reader.expectInt32());
292  break;
293  case BOTTLE_TAG_INT64:
294  x = static_cast<yarp::conf::float64_t>(reader.expectInt64());
295  break;
296  case BOTTLE_TAG_FLOAT32:
297  x = static_cast<yarp::conf::float64_t>(reader.expectFloat32());
298  break;
299  case BOTTLE_TAG_FLOAT64:
300  x = reader.expectFloat64();
301  break;
302  default:
303  return false;
304  }
305 
306  state->len--;
307  return !reader.isError();
308 }
309 
310 bool WireReader::readUI8(std::uint8_t& x)
311 {
312  return readI8(reinterpret_cast<std::int8_t&>(x));
313 }
314 
315 bool WireReader::readUI16(std::uint16_t& x)
316 {
317  return readI16(reinterpret_cast<std::int16_t&>(x));
318 }
319 
320 bool WireReader::readUI32(std::uint32_t& x)
321 {
322  return readI32(reinterpret_cast<std::int32_t&>(x));
323 }
324 
325 bool WireReader::readUI64(std::uint64_t& x)
326 {
327  return readI64(reinterpret_cast<std::int64_t&>(x));
328 }
329 
331 {
332  std::int32_t tag = state->code;
333  if (tag < 0) {
334  if (noMore()) {
335  return false;
336  }
337  tag = reader.expectInt32();
338  }
339  if (tag != BOTTLE_TAG_VOCAB32) {
340  return false;
341  }
342  if (noMore()) {
343  return false;
344  }
345  x = reader.expectInt32();
346  state->len--;
347  return !reader.isError();
348 }
349 
350 
352 {
353  std::int32_t tag = state->code;
354  if (tag < 0) {
355  if (noMore()) {
356  return false;
357  }
358  tag = reader.expectInt32();
359  }
360  if (tag != BOTTLE_TAG_INT32) {
361  return false;
362  }
363  if (noMore()) {
364  return false;
365  }
366  std::int32_t tmp = reader.expectInt32();
367  if (tmp < 0) {
368  return false;
369  }
370 
371  x = tmp;
372  state->len--;
373  return !reader.isError();
374 }
375 
376 bool WireReader::readString(std::string& str, bool* is_vocab)
377 {
378  if (state->len <= 0) {
379  return false;
380  }
381  std::int32_t tag = state->code;
382  if (state->code < 0) {
383  if (noMore()) {
384  return false;
385  }
386  tag = reader.expectInt32();
387  if (tag != BOTTLE_TAG_STRING && tag != BOTTLE_TAG_VOCAB32) {
388  return false;
389  }
390  }
391  state->len--;
392  if (tag == BOTTLE_TAG_VOCAB32) {
393  if (is_vocab != nullptr) {
394  *is_vocab = true;
395  }
396  if (noMore()) {
397  return false;
398  }
399  std::int32_t v = reader.expectInt32();
400  if (reader.isError()) {
401  return false;
402  }
403  str = Vocab32::decode(v);
404  return true;
405  }
406  if (is_vocab != nullptr) {
407  *is_vocab = false;
408  }
409  if (noMore()) {
410  return false;
411  }
412  std::int32_t len = reader.expectInt32();
413  if (reader.isError()) {
414  return false;
415  }
416  if (len != 0 && noMore()) {
417  return false;
418  }
419  str.resize(len);
420  reader.expectBlock(const_cast<char*>(str.data()), len);
421  return !reader.isError();
422 }
423 
424 bool WireReader::readBinary(std::string& str)
425 {
426  if (state->len <= 0) {
427  return false;
428  }
429  if (state->code < 0) {
430  if (noMore()) {
431  return false;
432  }
433  std::int32_t tag = reader.expectInt32();
434  if (tag != BOTTLE_TAG_BLOB) {
435  return false;
436  }
437  }
438  state->len--;
439  if (noMore()) {
440  return false;
441  }
442  std::int32_t len = reader.expectInt32();
443  if (reader.isError()) {
444  return false;
445  }
446  if (len == 0) {
447  str = std::string();
448  return true;
449  }
450  if (len < 0) {
451  return false;
452  }
453  if (noMore()) {
454  return false;
455  }
456  str.resize(len);
457  reader.expectBlock(const_cast<char*>(str.data()), len);
458  return !reader.isError();
459 }
460 
462 {
463  std::int32_t x1 = 0;
464  std::int32_t x2 = 0;
465  if (noMore()) {
466  return false;
467  }
468  x1 = reader.expectInt32();
469  if ((x1 & BOTTLE_TAG_LIST) == 0) {
470  return false;
471  }
472  if (noMore()) {
473  return false;
474  }
475  x2 = reader.expectInt32();
476  int code = (x1 & (~BOTTLE_TAG_LIST));
477  state->len = x2;
478  if (code != 0) {
479  state->code = code;
480  }
481  return !reader.isError();
482 }
483 
485 {
486  if (!readListHeader()) {
487  return false;
488  }
489  return len == state->len;
490 }
491 
493 {
494  if (!readListHeader()) {
495  return false;
496  }
497  if (!support_get_mode) {
498  return true;
499  }
500  if (state->len == 1) {
501  return true;
502  }
503  if (state->len != 4) {
504  return false;
505  }
506  // possibly old-style return: [is] foo val [ok]
507  std::int32_t v = 0;
508  if (!readVocab32(v)) {
509  return false;
510  }
511  if (v != VOCAB_IS) {
512  return false;
513  }
514  std::string dummy;
515  if (!readString(dummy)) {
516  return false; // string OR vocab
517  }
518  // now we are ready to consume real result
519  state->need_ok = true;
520  return true;
521 }
522 
524 {
525  return reader;
526 }
527 
529 {
530  flush_if_needed = false;
531  ConnectionWriter* writer = reader.getWriter();
532  if (writer != nullptr) {
533  return *writer;
534  }
535  return null_writer;
536 }
537 
539 {
540  return reader.isValid();
541 }
542 
544 {
545  return reader.isError();
546 }
547 
548 std::string WireReader::readTag(size_t len)
549 {
550  flush_if_needed = true;
551  std::string str;
552  bool is_vocab;
553  if (!readString(str, &is_vocab)) {
554  fail();
555  return {};
556  }
557  scanString(str, is_vocab);
558  if (!is_vocab) {
559  return str;
560  }
561  while (--len > 0 && is_vocab && state->len > 0) {
562  if (state->code >= 0) {
563  is_vocab = (state->code == BOTTLE_TAG_VOCAB32);
564  } else {
565  if (noMore()) {
566  return {};
567  }
568  std::int32_t x = reader.expectInt32();
569  reader.pushInt(x);
570  is_vocab = (x == BOTTLE_TAG_VOCAB32);
571  }
572  if (is_vocab) {
573  std::string str2;
574  if (!readString(str2, &is_vocab)) {
575  return {};
576  }
577  scanString(str2, is_vocab);
578  str += "_";
579  str += str2;
580  }
581  }
582  return str;
583 }
584 
585 void WireReader::readListBegin(WireState& nstate, std::uint32_t& len)
586 {
587  nstate.parent = state;
588  state = &nstate;
589  len = 0;
590  if (!readListHeader()) {
591  return;
592  }
593  len = static_cast<std::uint32_t>(state->len);
594 }
595 
596 void WireReader::readSetBegin(WireState& nstate, std::uint32_t& len)
597 {
598  readListBegin(nstate, len);
599 }
600 
602  WireState& nstate2,
603  std::uint32_t& len)
604 {
605  YARP_UNUSED(nstate2);
606  readListBegin(nstate, len);
607 }
608 
610 {
611  state = state->parent;
612 }
613 
615 {
616  state = state->parent;
617 }
618 
620 {
621  state = state->parent;
622 }
623 
625 {
626  if (!flush_if_needed) {
627  return false;
628  }
629  size_t pending = reader.getSize();
630  return pending == 0;
631 }
632 
633 void WireReader::scanString(std::string& str, bool is_vocab)
634 {
635  if (!support_get_mode) {
636  return;
637  }
638  if (get_string.empty()) {
639  if (get_mode && get_string.empty()) {
640  get_string = str;
641  get_is_vocab = is_vocab;
642  } else if (str == "get") {
643  get_mode = true;
644  } else {
645  get_string = "alt";
646  }
647  }
648 }
649 
650 
652 {
653  return get_mode;
654 }
655 
657 {
658  return get_is_vocab;
659 }
660 
661 const std::string& WireReader::getString() const
662 {
663  return get_string;
664 }
#define BOTTLE_TAG_INT8
Definition: Bottle.h:19
#define BOTTLE_TAG_FLOAT64
Definition: Bottle.h:25
#define BOTTLE_TAG_INT64
Definition: Bottle.h:22
#define BOTTLE_TAG_INT16
Definition: Bottle.h:20
#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
#define BOTTLE_TAG_FLOAT32
Definition: Bottle.h:24
constexpr yarp::conf::vocab32_t VOCAB_IS
Definition: GenericVocabs.h:14
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:230
An interface for reading from a network connection.
virtual size_t getSize() const =0
Checks how much data is available.
virtual bool expectBlock(char *data, size_t len)=0
Read a block of data from the network connection.
virtual bool pushInt(int x)=0
Store an integer to return on the next call to expectInt()
virtual std::int32_t expectInt32()=0
Read a 32-bit integer from the network connection.
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
virtual yarp::conf::float32_t expectFloat32()=0
Read a 32-bit floating point number from the network connection.
virtual std::int64_t expectInt64()=0
Read a 64-bit integer from the network connection.
virtual bool isValid() const =0
virtual bool isError() const =0
virtual std::int16_t expectInt16()=0
Read a 16-bit integer from the network connection.
virtual std::int8_t expectInt8()=0
Read a 8-bit integer from the network connection.
virtual yarp::conf::float64_t expectFloat64()=0
Read a 64-bit floating point number from the network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
An interface for writing to a network connection.
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition: PortReader.h:24
virtual bool read(ConnectionReader &reader)=0
Read this object from a network connection.
A "tamed" Portable, that promises to serialize itself in an IDL-friendly way.
Definition: WirePortable.h:21
virtual bool read(yarp::os::idl::WireReader &reader)
const std::string & getString() const
Definition: WireReader.cpp:661
ConnectionWriter & getWriter()
Definition: WireReader.cpp:528
bool readVocab32(yarp::conf::vocab32_t &x)
Definition: WireReader.cpp:330
bool readNested(WirePortable &obj)
Definition: WireReader.cpp:82
bool readUI8(std::uint8_t &x)
Definition: WireReader.cpp:310
bool readString(std::string &str, bool *is_vocab=nullptr)
Definition: WireReader.cpp:376
void readMapBegin(yarp::os::idl::WireState &nstate, yarp::os::idl::WireState &nstate2, std::uint32_t &len)
Definition: WireReader.cpp:601
bool readUI16(std::uint16_t &x)
Definition: WireReader.cpp:315
bool readUI32(std::uint32_t &x)
Definition: WireReader.cpp:320
ConnectionReader & getReader()
Definition: WireReader.cpp:523
bool readFloat32(yarp::conf::float32_t &x)
Definition: WireReader.cpp:232
bool readI32(std::int32_t &x)
Definition: WireReader.cpp:169
void readSetBegin(yarp::os::idl::WireState &nstate, std::uint32_t &len)
Definition: WireReader.cpp:596
bool readI16(std::int16_t &x)
Definition: WireReader.cpp:139
std::string readTag(size_t len=static_cast< size_t >(-1))
Definition: WireReader.cpp:548
bool readI8(std::int8_t &x)
Definition: WireReader.cpp:112
bool readBinary(std::string &str)
Definition: WireReader.cpp:424
WireReader(ConnectionReader &reader)
Definition: WireReader.cpp:16
void readListBegin(yarp::os::idl::WireState &nstate, std::uint32_t &len)
Definition: WireReader.cpp:585
bool readUI64(std::uint64_t &x)
Definition: WireReader.cpp:325
bool read(WirePortable &obj)
Definition: WireReader.cpp:72
bool readSizeT(std::size_t &x)
Definition: WireReader.cpp:351
bool readFloat64(yarp::conf::float64_t &x)
Definition: WireReader.cpp:271
bool readI64(std::int64_t &x)
Definition: WireReader.cpp:199
IDL-friendly state.
Definition: WireState.h:17
std::int32_t vocab32_t
Definition: numeric.h:78
double float64_t
Definition: numeric.h:77
float float32_t
Definition: numeric.h:76
std::string decode(NetInt32 code)
Convert a vocabulary identifier into a string.
Definition: Vocab.cpp:33
An interface to the operating system, including Port based communication.
constexpr yarp::conf::vocab32_t createVocab32(char a, char b=0, char c=0, char d=0)
Create a vocab from chars.
Definition: Vocab.h:27
#define YARP_UNUSED(var)
Definition: api.h:162