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  state = &baseState;
21  flush_if_needed = false;
22  get_mode = false;
23  support_get_mode = false;
24  expecting = false;
25  get_is_vocab = false;
26 }
27 
29 {
30  if (state->need_ok) {
31  std::int32_t dummy;
32  readVocab32(dummy);
33  state->need_ok = false;
34  }
35  if (flush_if_needed) {
36  clear();
37  }
38 }
39 
41 {
42  expecting = true;
43  flush_if_needed = true;
44 }
45 
47 {
48  expecting = false;
49 }
50 
52 {
53  support_get_mode = true;
54 }
55 
57 {
58  size_t pending = reader.getSize();
59  if (pending > 0) {
60  while (pending > 0) {
61  char buf[1000];
62  size_t next = (pending < sizeof(buf)) ? pending : sizeof(buf);
63  reader.expectBlock(&buf[0], next);
64  pending -= next;
65  }
66  return true;
67  }
68  return false;
69 }
70 
72 {
73  clear();
74  Bottle b("[fail]");
75  b.write(getWriter());
76 }
77 
79 {
80  return obj.read(*this);
81 }
82 
84 {
85  return obj.read(reader);
86 }
87 
89 {
90  return obj.read(reader);
91 }
92 
94 {
95  return obj.read(reader);
96 }
97 
98 bool WireReader::readBool(bool& x)
99 {
100  if (state->code < 0) {
101  if (noMore()) {
102  return false;
103  }
104  std::int32_t tag = reader.expectInt32();
105  if (tag != BOTTLE_TAG_INT32 && tag != BOTTLE_TAG_VOCAB32) {
106  return false;
107  }
108  }
109  if (noMore()) {
110  return false;
111  }
112  std::int32_t v = reader.expectInt32();
113  x = (v != 0) && (v != VOCAB_FAIL);
114  state->len--;
115  return !reader.isError();
116 }
117 
118 bool WireReader::readI8(std::int8_t& x)
119 {
120  std::int32_t tag = state->code;
121  if (tag < 0) {
122  if (noMore()) {
123  return false;
124  }
125  tag = reader.expectInt32();
126  }
127  if (noMore()) {
128  return false;
129  }
130  switch (tag) {
131  case BOTTLE_TAG_INT8:
132  x = reader.expectInt8();
133  break;
134  case BOTTLE_TAG_INT32:
135  x = static_cast<std::int8_t>(reader.expectInt32());
136  break;
137  default:
138  return false;
139  }
140 
141  state->len--;
142  return !reader.isError();
143 }
144 
145 bool WireReader::readI16(std::int16_t& x)
146 {
147  std::int32_t tag = state->code;
148  if (tag < 0) {
149  if (noMore()) {
150  return false;
151  }
152  tag = reader.expectInt32();
153  }
154  if (noMore()) {
155  return false;
156  }
157  switch (tag) {
158  case BOTTLE_TAG_INT8:
159  x = static_cast<std::int16_t>(reader.expectInt8());
160  break;
161  case BOTTLE_TAG_INT16:
162  x = reader.expectInt16();
163  break;
164  case BOTTLE_TAG_INT32:
165  x = static_cast<std::int16_t>(reader.expectInt32());
166  break;
167  default:
168  return false;
169  }
170 
171  state->len--;
172  return !reader.isError();
173 }
174 
175 bool WireReader::readI32(std::int32_t& x)
176 {
177  std::int32_t tag = state->code;
178  if (tag < 0) {
179  if (noMore()) {
180  return false;
181  }
182  tag = reader.expectInt32();
183  }
184  if (noMore()) {
185  return false;
186  }
187  switch (tag) {
188  case BOTTLE_TAG_INT8:
189  x = static_cast<std::int32_t>(reader.expectInt8());
190  break;
191  case BOTTLE_TAG_INT16:
192  x = static_cast<std::int32_t>(reader.expectInt16());
193  break;
194  case BOTTLE_TAG_INT32:
195  case BOTTLE_TAG_VOCAB32:
196  x = reader.expectInt32();
197  break;
198  default:
199  return false;
200  }
201  state->len--;
202  return !reader.isError();
203 }
204 
205 bool WireReader::readI64(std::int64_t& x)
206 {
207  std::int32_t tag = state->code;
208  if (tag < 0) {
209  if (noMore()) {
210  return false;
211  }
212  tag = reader.expectInt32();
213  }
214  if (noMore()) {
215  return false;
216  }
217  switch (tag) {
218  case BOTTLE_TAG_INT8:
219  x = static_cast<std::int64_t>(reader.expectInt8());
220  break;
221  case BOTTLE_TAG_INT16:
222  x = static_cast<std::int64_t>(reader.expectInt16());
223  break;
224  case BOTTLE_TAG_INT32:
225  x = static_cast<std::int64_t>(reader.expectInt32());
226  break;
227  case BOTTLE_TAG_INT64:
228  x = reader.expectInt64();
229  break;
230  default:
231  return false;
232  }
233 
234  state->len--;
235  return !reader.isError();
236 }
237 
239 {
240  std::int32_t tag = state->code;
241  if (tag < 0) {
242  if (noMore()) {
243  return false;
244  }
245  tag = reader.expectInt32();
246  }
247  if (noMore()) {
248  return false;
249  }
250  switch (tag) {
251  case BOTTLE_TAG_INT8:
252  x = static_cast<yarp::conf::float32_t>(reader.expectInt8());
253  break;
254  case BOTTLE_TAG_INT16:
255  x = static_cast<yarp::conf::float32_t>(reader.expectInt16());
256  break;
257  case BOTTLE_TAG_INT32:
258  x = static_cast<yarp::conf::float32_t>(reader.expectInt32());
259  break;
260  case BOTTLE_TAG_INT64:
261  x = static_cast<yarp::conf::float32_t>(reader.expectInt64());
262  break;
263  case BOTTLE_TAG_FLOAT32:
264  x = reader.expectFloat32();
265  break;
266  case BOTTLE_TAG_FLOAT64:
267  x = static_cast<yarp::conf::float32_t>(reader.expectFloat64());
268  break;
269  default:
270  return false;
271  }
272 
273  state->len--;
274  return !reader.isError();
275 }
276 
278 {
279  std::int32_t tag = state->code;
280  if (tag < 0) {
281  if (noMore()) {
282  return false;
283  }
284  tag = reader.expectInt32();
285  }
286  if (noMore()) {
287  return false;
288  }
289  switch (tag) {
290  case BOTTLE_TAG_INT8:
291  x = static_cast<yarp::conf::float64_t>(reader.expectInt8());
292  break;
293  case BOTTLE_TAG_INT16:
294  x = static_cast<yarp::conf::float64_t>(reader.expectInt16());
295  break;
296  case BOTTLE_TAG_INT32:
297  x = static_cast<yarp::conf::float64_t>(reader.expectInt32());
298  break;
299  case BOTTLE_TAG_INT64:
300  x = static_cast<yarp::conf::float64_t>(reader.expectInt64());
301  break;
302  case BOTTLE_TAG_FLOAT32:
303  x = static_cast<yarp::conf::float64_t>(reader.expectFloat32());
304  break;
305  case BOTTLE_TAG_FLOAT64:
306  x = reader.expectFloat64();
307  break;
308  default:
309  return false;
310  }
311 
312  state->len--;
313  return !reader.isError();
314 }
315 
316 bool WireReader::readUI8(std::uint8_t& x)
317 {
318  return readI8(reinterpret_cast<std::int8_t&>(x));
319 }
320 
321 bool WireReader::readUI16(std::uint16_t& x)
322 {
323  return readI16(reinterpret_cast<std::int16_t&>(x));
324 }
325 
326 bool WireReader::readUI32(std::uint32_t& x)
327 {
328  return readI32(reinterpret_cast<std::int32_t&>(x));
329 }
330 
331 bool WireReader::readUI64(std::uint64_t& x)
332 {
333  return readI64(reinterpret_cast<std::int64_t&>(x));
334 }
335 
337 {
338  std::int32_t tag = state->code;
339  if (tag < 0) {
340  if (noMore()) {
341  return false;
342  }
343  tag = reader.expectInt32();
344  }
345  if (tag != BOTTLE_TAG_VOCAB32) {
346  return false;
347  }
348  if (noMore()) {
349  return false;
350  }
351  x = reader.expectInt32();
352  state->len--;
353  return !reader.isError();
354 }
355 
356 
358 {
359  std::int32_t tag = state->code;
360  if (tag < 0) {
361  if (noMore()) {
362  return false;
363  }
364  tag = reader.expectInt32();
365  }
366  if (tag != BOTTLE_TAG_INT32) {
367  return false;
368  }
369  if (noMore()) {
370  return false;
371  }
372  std::int32_t tmp = reader.expectInt32();
373  if (tmp < 0) {
374  return false;
375  }
376 
377  x = tmp;
378  state->len--;
379  return !reader.isError();
380 }
381 
382 bool WireReader::readString(std::string& str, bool* is_vocab)
383 {
384  if (state->len <= 0) {
385  return false;
386  }
387  std::int32_t tag = state->code;
388  if (state->code < 0) {
389  if (noMore()) {
390  return false;
391  }
392  tag = reader.expectInt32();
393  if (tag != BOTTLE_TAG_STRING && tag != BOTTLE_TAG_VOCAB32) {
394  return false;
395  }
396  }
397  state->len--;
398  if (tag == BOTTLE_TAG_VOCAB32) {
399  if (is_vocab != nullptr) {
400  *is_vocab = true;
401  }
402  if (noMore()) {
403  return false;
404  }
405  std::int32_t v = reader.expectInt32();
406  if (reader.isError()) {
407  return false;
408  }
409  str = Vocab32::decode(v);
410  return true;
411  }
412  if (is_vocab != nullptr) {
413  *is_vocab = false;
414  }
415  if (noMore()) {
416  return false;
417  }
418  std::int32_t len = reader.expectInt32();
419  if (reader.isError()) {
420  return false;
421  }
422  if (noMore()) {
423  return false;
424  }
425  str.resize(len);
426  reader.expectBlock(const_cast<char*>(str.data()), len);
427  return !reader.isError();
428 }
429 
430 bool WireReader::readBinary(std::string& str)
431 {
432  if (state->len <= 0) {
433  return false;
434  }
435  if (state->code < 0) {
436  if (noMore()) {
437  return false;
438  }
439  std::int32_t tag = reader.expectInt32();
440  if (tag != BOTTLE_TAG_BLOB) {
441  return false;
442  }
443  }
444  state->len--;
445  if (noMore()) {
446  return false;
447  }
448  std::int32_t len = reader.expectInt32();
449  if (reader.isError()) {
450  return false;
451  }
452  if (len == 0) {
453  str = std::string();
454  return true;
455  }
456  if (len < 0) {
457  return false;
458  }
459  if (noMore()) {
460  return false;
461  }
462  str.resize(len);
463  reader.expectBlock(const_cast<char*>(str.data()), len);
464  return !reader.isError();
465 }
466 
467 bool WireReader::readEnum(std::int32_t& x, WireVocab& converter)
468 {
469  std::int32_t tag = state->code;
470  if (tag < 0) {
471  if (noMore()) {
472  return false;
473  }
474  tag = reader.expectInt32();
475  }
476  if (tag == BOTTLE_TAG_INT32) {
477  if (noMore()) {
478  return false;
479  }
480  std::int32_t v = reader.expectInt32();
481  x = v;
482  state->len--;
483  return !reader.isError();
484  }
485  if (tag == BOTTLE_TAG_STRING) {
486  if (noMore()) {
487  return false;
488  }
489  std::int32_t len = reader.expectInt32();
490  if (reader.isError()) {
491  return false;
492  }
493  if (len < 1) {
494  return false;
495  }
496  if (noMore()) {
497  return false;
498  }
499  std::string str;
500  str.resize(len);
501  reader.expectBlock(const_cast<char*>(str.data()), len);
502  str.resize(len - 1);
503  state->len--;
504  if (reader.isError()) {
505  return false;
506  }
507  x = static_cast<std::int32_t>(converter.fromString(str));
508  return (x >= 0);
509  }
510  return false;
511 }
512 
514 {
515  std::int32_t x1 = 0;
516  std::int32_t x2 = 0;
517  if (noMore()) {
518  return false;
519  }
520  x1 = reader.expectInt32();
521  if ((x1 & BOTTLE_TAG_LIST) == 0) {
522  return false;
523  }
524  if (noMore()) {
525  return false;
526  }
527  x2 = reader.expectInt32();
528  int code = (x1 & (~BOTTLE_TAG_LIST));
529  state->len = x2;
530  if (code != 0) {
531  state->code = code;
532  }
533  return !reader.isError();
534 }
535 
537 {
538  if (!readListHeader()) {
539  return false;
540  }
541  return len == state->len;
542 }
543 
545 {
546  if (!readListHeader()) {
547  return false;
548  }
549  if (!support_get_mode) {
550  return true;
551  }
552  if (state->len == 1) {
553  return true;
554  }
555  if (state->len != 4) {
556  return false;
557  }
558  // possibly old-style return: [is] foo val [ok]
559  std::int32_t v = 0;
560  if (!readVocab32(v)) {
561  return false;
562  }
563  if (v != VOCAB_IS) {
564  return false;
565  }
566  std::string dummy;
567  if (!readString(dummy)) {
568  return false; // string OR vocab
569  }
570  // now we are ready to consume real result
571  state->need_ok = true;
572  return true;
573 }
574 
576 {
577  flush_if_needed = false;
578  ConnectionWriter* writer = reader.getWriter();
579  if (writer != nullptr) {
580  return *writer;
581  }
582  return null_writer;
583 }
584 
586 {
587  return reader.isValid();
588 }
589 
591 {
592  return reader.isError();
593 }
594 
595 std::string WireReader::readTag()
596 {
597  flush_if_needed = true;
598  std::string str;
599  bool is_vocab;
600  if (!readString(str, &is_vocab)) {
601  fail();
602  return {};
603  }
604  scanString(str, is_vocab);
605  if (!is_vocab) {
606  return str;
607  }
608  while (is_vocab && state->len > 0) {
609  if (state->code >= 0) {
610  is_vocab = (state->code == BOTTLE_TAG_VOCAB32);
611  } else {
612  if (noMore()) {
613  return {};
614  }
615  std::int32_t x = reader.expectInt32();
616  reader.pushInt(x);
617  is_vocab = (x == BOTTLE_TAG_VOCAB32);
618  }
619  if (is_vocab) {
620  std::string str2;
621  if (!readString(str2, &is_vocab)) {
622  return {};
623  }
624  scanString(str2, is_vocab);
625  str += "_";
626  str += str2;
627  }
628  }
629  return str;
630 }
631 
632 void WireReader::readListBegin(WireState& nstate, std::uint32_t& len)
633 {
634  nstate.parent = state;
635  state = &nstate;
636  len = 0;
637  if (!readListHeader()) {
638  return;
639  }
640  len = static_cast<std::uint32_t>(state->len);
641 }
642 
643 void WireReader::readSetBegin(WireState& nstate, std::uint32_t& len)
644 {
645  readListBegin(nstate, len);
646 }
647 
649  WireState& nstate2,
650  std::uint32_t& len)
651 {
652  YARP_UNUSED(nstate2);
653  readListBegin(nstate, len);
654 }
655 
657 {
658  state = state->parent;
659 }
660 
662 {
663  state = state->parent;
664 }
665 
667 {
668  state = state->parent;
669 }
670 
672 {
673  if (!flush_if_needed) {
674  return false;
675  }
676  size_t pending = reader.getSize();
677  return pending == 0;
678 }
679 
680 void WireReader::scanString(std::string& str, bool is_vocab)
681 {
682  if (!support_get_mode) {
683  return;
684  }
685  if (get_string.empty()) {
686  if (get_mode && get_string.empty()) {
687  get_string = str;
688  get_is_vocab = is_vocab;
689  } else if (str == "get") {
690  get_mode = true;
691  } else {
692  get_string = "alt";
693  }
694  }
695 }
696 
697 
699 {
700  return get_mode;
701 }
702 
704 {
705  return get_is_vocab;
706 }
707 
708 const std::string& WireReader::getString() const
709 {
710  return get_string;
711 }
#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:74
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:25
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:23
virtual bool read(yarp::os::idl::WireReader &reader)
const std::string & getString() const
Definition: WireReader.cpp:708
ConnectionWriter & getWriter()
Definition: WireReader.cpp:575
bool readVocab32(yarp::conf::vocab32_t &x)
Definition: WireReader.cpp:336
bool readEnum(std::int32_t &x, yarp::os::idl::WireVocab &converter)
Definition: WireReader.cpp:467
bool readNested(WirePortable &obj)
Definition: WireReader.cpp:88
bool readUI8(std::uint8_t &x)
Definition: WireReader.cpp:316
bool readString(std::string &str, bool *is_vocab=nullptr)
Definition: WireReader.cpp:382
void readMapBegin(yarp::os::idl::WireState &nstate, yarp::os::idl::WireState &nstate2, std::uint32_t &len)
Definition: WireReader.cpp:648
bool readUI16(std::uint16_t &x)
Definition: WireReader.cpp:321
bool readUI32(std::uint32_t &x)
Definition: WireReader.cpp:326
bool readFloat32(yarp::conf::float32_t &x)
Definition: WireReader.cpp:238
bool readI32(std::int32_t &x)
Definition: WireReader.cpp:175
void readSetBegin(yarp::os::idl::WireState &nstate, std::uint32_t &len)
Definition: WireReader.cpp:643
bool readI16(std::int16_t &x)
Definition: WireReader.cpp:145
bool readI8(std::int8_t &x)
Definition: WireReader.cpp:118
bool readBinary(std::string &str)
Definition: WireReader.cpp:430
WireReader(ConnectionReader &reader)
Definition: WireReader.cpp:16
void readListBegin(yarp::os::idl::WireState &nstate, std::uint32_t &len)
Definition: WireReader.cpp:632
bool readUI64(std::uint64_t &x)
Definition: WireReader.cpp:331
bool read(WirePortable &obj)
Definition: WireReader.cpp:78
bool readSizeT(std::size_t &x)
Definition: WireReader.cpp:357
bool readFloat64(yarp::conf::float64_t &x)
Definition: WireReader.cpp:277
bool readI64(std::int64_t &x)
Definition: WireReader.cpp:205
IDL-friendly state.
Definition: WireState.h:19
virtual int fromString(const std::string &input)=0
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:28
#define YARP_UNUSED(var)
Definition: api.h:162