YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
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
8using namespace yarp::os::idl;
9using namespace yarp::os;
10
11namespace {
12constexpr 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
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
112bool 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
139bool 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
169bool 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:
190 x = reader.expectInt32();
191 break;
192 default:
193 return false;
194 }
195 state->len--;
196 return !reader.isError();
197}
198
199bool 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;
258 x = reader.expectFloat32();
259 break;
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;
297 x = static_cast<yarp::conf::float64_t>(reader.expectFloat32());
298 break;
300 x = reader.expectFloat64();
301 break;
302 default:
303 return false;
304 }
305
306 state->len--;
307 return !reader.isError();
308}
309
310bool WireReader::readUI8(std::uint8_t& x)
311{
312 return readI8(reinterpret_cast<std::int8_t&>(x));
313}
314
315bool WireReader::readUI16(std::uint16_t& x)
316{
317 return readI16(reinterpret_cast<std::int16_t&>(x));
318}
319
320bool WireReader::readUI32(std::uint32_t& x)
321{
322 return readI32(reinterpret_cast<std::int32_t&>(x));
323}
324
325bool 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
351bool WireReader::readSizeT(std::size_t& x)
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
376bool 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
424bool WireReader::readBlock(char* const data, size_t len)
425{
426 if (state->len <= 0) {
427 return false;
428 }
429 if (noMore()) {
430 return false;
431 }
432 reader.expectBlock(data, len);
433 return !reader.isError();
434}
435
436
437bool WireReader::readBinary(std::string& str)
438{
439 if (state->len <= 0) {
440 return false;
441 }
442 if (state->code < 0) {
443 if (noMore()) {
444 return false;
445 }
446 std::int32_t tag = reader.expectInt32();
447 if (tag != BOTTLE_TAG_BLOB) {
448 return false;
449 }
450 }
451 state->len--;
452 if (noMore()) {
453 return false;
454 }
455 std::int32_t len = reader.expectInt32();
456 if (reader.isError()) {
457 return false;
458 }
459 if (len == 0) {
460 str = std::string();
461 return true;
462 }
463 if (len < 0) {
464 return false;
465 }
466 if (noMore()) {
467 return false;
468 }
469 str.resize(len);
470 reader.expectBlock(const_cast<char*>(str.data()), len);
471 return !reader.isError();
472}
473
475{
476 std::int32_t x1 = 0;
477 std::int32_t x2 = 0;
478 if (noMore()) {
479 return false;
480 }
481 x1 = reader.expectInt32();
482 if ((x1 & BOTTLE_TAG_LIST) == 0) {
483 return false;
484 }
485 if (noMore()) {
486 return false;
487 }
488 x2 = reader.expectInt32();
489 int code = (x1 & (~BOTTLE_TAG_LIST));
490 state->len = x2;
491 if (code != 0) {
492 state->code = code;
493 }
494 return !reader.isError();
495}
496
498{
499 if (!readListHeader()) {
500 return false;
501 }
502 return len == state->len;
503}
504
506{
507 if (!readListHeader()) {
508 return false;
509 }
510 if (!support_get_mode) {
511 return true;
512 }
513 if (state->len == 1) {
514 return true;
515 }
516 if (state->len != 4) {
517 return false;
518 }
519 // possibly old-style return: [is] foo val [ok]
520 std::int32_t v = 0;
521 if (!readVocab32(v)) {
522 return false;
523 }
524 if (v != VOCAB_IS) {
525 return false;
526 }
527 std::string dummy;
528 if (!readString(dummy)) {
529 return false; // string OR vocab
530 }
531 // now we are ready to consume real result
532 state->need_ok = true;
533 return true;
534}
535
537{
538 return reader;
539}
540
542{
543 flush_if_needed = false;
544 ConnectionWriter* writer = reader.getWriter();
545 if (writer != nullptr) {
546 return *writer;
547 }
548 return null_writer;
549}
550
552{
553 return reader.isValid();
554}
555
557{
558 return reader.isError();
559}
560
561std::string WireReader::readTag(size_t len)
562{
563 flush_if_needed = true;
564 std::string str;
565 bool is_vocab;
566 if (!readString(str, &is_vocab)) {
567 fail();
568 return {};
569 }
570 scanString(str, is_vocab);
571 if (!is_vocab) {
572 return str;
573 }
574 while (--len > 0 && is_vocab && state->len > 0) {
575 if (state->code >= 0) {
576 is_vocab = (state->code == BOTTLE_TAG_VOCAB32);
577 } else {
578 if (noMore()) {
579 return {};
580 }
581 std::int32_t x = reader.expectInt32();
582 reader.pushInt(x);
584 }
585 if (is_vocab) {
586 std::string str2;
587 if (!readString(str2, &is_vocab)) {
588 return {};
589 }
590 scanString(str2, is_vocab);
591 str += "_";
592 str += str2;
593 }
594 }
595 return str;
596}
597
599{
600 nstate.parent = state;
601 state = &nstate;
602 len = 0;
603 if (!readListHeader()) {
604 return;
605 }
606 len = static_cast<size_t>(state->len);
607}
608
610{
611 readListBegin(nstate, len);
612}
613
616 size_t& len)
617{
619 readListBegin(nstate, len);
620}
621
623{
624 state = state->parent;
625}
626
628{
629 state = state->parent;
630}
631
633{
634 state = state->parent;
635}
636
638{
639 if (!flush_if_needed) {
640 return false;
641 }
642 size_t pending = reader.getSize();
643 return pending == 0;
644}
645
646void WireReader::scanString(std::string& str, bool is_vocab)
647{
648 if (!support_get_mode) {
649 return;
650 }
651 if (get_string.empty()) {
652 if (get_mode && get_string.empty()) {
653 get_string = str;
654 get_is_vocab = is_vocab;
655 } else if (str == "get") {
656 get_mode = true;
657 } else {
658 get_string = "alt";
659 }
660 }
661}
662
663
665{
666 return get_mode;
667}
668
670{
671 return get_is_vocab;
672}
673
674const std::string& WireReader::getString() const
675{
676 return get_string;
677}
#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
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition Bottle.cpp:230
A mini-server for performing network communication in the background.
T * read(bool shouldWait=true) override
Read an available object from the port.
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 ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
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.
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
A "tamed" Portable, that promises to serialize itself in an IDL-friendly way.
const std::string & getString() const
ConnectionWriter & getWriter()
bool readVocab32(yarp::conf::vocab32_t &x)
bool readNested(WirePortable &obj)
bool readUI8(std::uint8_t &x)
bool readString(std::string &str, bool *is_vocab=nullptr)
bool readUI16(std::uint16_t &x)
bool readUI32(std::uint32_t &x)
void readListBegin(yarp::os::idl::WireState &nstate, size_t &len)
ConnectionReader & getReader()
bool readFloat32(yarp::conf::float32_t &x)
bool readI32(std::int32_t &x)
bool readI16(std::int16_t &x)
std::string readTag(size_t len=static_cast< size_t >(-1))
bool readI8(std::int8_t &x)
bool readBinary(std::string &str)
WireReader(ConnectionReader &reader)
void readMapBegin(yarp::os::idl::WireState &nstate, yarp::os::idl::WireState &nstate2, size_t &len)
bool readBlock(char *const data, size_t len)
bool readUI64(std::uint64_t &x)
bool read(WirePortable &obj)
void readSetBegin(yarp::os::idl::WireState &nstate, size_t &len)
bool readSizeT(std::size_t &x)
bool readFloat64(yarp::conf::float64_t &x)
bool readI64(std::int64_t &x)
IDL-friendly state.
Definition WireState.h:17
std::int32_t vocab32_t
Definition numeric.h:78
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