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:
223 x = reader.expectInt64();
224 break;
225 default:
226 return false;
227 }
228
229 state->len--;
230 return !reader.isError();
231}
232
234{
235 std::int32_t tag = state->code;
236 if (tag < 0) {
237 if (noMore()) {
238 return false;
239 }
240 tag = reader.expectInt32();
241 }
242 if (noMore()) {
243 return false;
244 }
245 switch (tag) {
246 case BOTTLE_TAG_INT8:
247 x = static_cast<yarp::conf::float32_t>(reader.expectInt8());
248 break;
249 case BOTTLE_TAG_INT16:
250 x = static_cast<yarp::conf::float32_t>(reader.expectInt16());
251 break;
252 case BOTTLE_TAG_INT32:
253 x = static_cast<yarp::conf::float32_t>(reader.expectInt32());
254 break;
255 case BOTTLE_TAG_INT64:
256 x = static_cast<yarp::conf::float32_t>(reader.expectInt64());
257 break;
259 x = reader.expectFloat32();
260 break;
262 x = static_cast<yarp::conf::float32_t>(reader.expectFloat64());
263 break;
264 default:
265 return false;
266 }
267
268 state->len--;
269 return !reader.isError();
270}
271
273{
274 std::int32_t tag = state->code;
275 if (tag < 0) {
276 if (noMore()) {
277 return false;
278 }
279 tag = reader.expectInt32();
280 }
281 if (noMore()) {
282 return false;
283 }
284 switch (tag) {
285 case BOTTLE_TAG_INT8:
286 x = static_cast<yarp::conf::float64_t>(reader.expectInt8());
287 break;
288 case BOTTLE_TAG_INT16:
289 x = static_cast<yarp::conf::float64_t>(reader.expectInt16());
290 break;
291 case BOTTLE_TAG_INT32:
292 x = static_cast<yarp::conf::float64_t>(reader.expectInt32());
293 break;
294 case BOTTLE_TAG_INT64:
295 x = static_cast<yarp::conf::float64_t>(reader.expectInt64());
296 break;
298 x = static_cast<yarp::conf::float64_t>(reader.expectFloat32());
299 break;
301 x = reader.expectFloat64();
302 break;
303 default:
304 return false;
305 }
306
307 state->len--;
308 return !reader.isError();
309}
310
311bool WireReader::readUI8(std::uint8_t& x)
312{
313 return readI8(reinterpret_cast<std::int8_t&>(x));
314}
315
316bool WireReader::readUI16(std::uint16_t& x)
317{
318 return readI16(reinterpret_cast<std::int16_t&>(x));
319}
320
321bool WireReader::readUI32(std::uint32_t& x)
322{
323 return readI32(reinterpret_cast<std::int32_t&>(x));
324}
325
326bool WireReader::readUI64(std::uint64_t& x)
327{
328 return readI64(reinterpret_cast<std::int64_t&>(x));
329}
330
332{
333 std::int32_t tag = state->code;
334 if (tag < 0) {
335 if (noMore()) {
336 return false;
337 }
338 tag = reader.expectInt32();
339 }
340 if (tag != BOTTLE_TAG_VOCAB32) {
341 return false;
342 }
343 if (noMore()) {
344 return false;
345 }
346 x = reader.expectInt32();
347 state->len--;
348 return !reader.isError();
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_VOCAB64) {
361 return false;
362 }
363 if (noMore()) {
364 return false;
365 }
366 x = reader.expectInt64();
367 state->len--;
368 return !reader.isError();
369}
370
371bool WireReader::readSizeT(std::size_t& x)
372{
373 std::int32_t tag = state->code;
374 if (tag < 0) {
375 if (noMore()) {
376 return false;
377 }
378 tag = reader.expectInt32();
379 }
380 if (tag != BOTTLE_TAG_INT32) {
381 return false;
382 }
383 if (noMore()) {
384 return false;
385 }
386 std::int32_t tmp = reader.expectInt32();
387 if (tmp < 0) {
388 return false;
389 }
390
391 x = tmp;
392 state->len--;
393 return !reader.isError();
394}
395
396bool WireReader::readString(std::string& str, bool* is_vocab)
397{
398 if (state->len <= 0) {
399 return false;
400 }
401 std::int32_t tag = state->code;
402 if (state->code < 0) {
403 if (noMore()) {
404 return false;
405 }
406 tag = reader.expectInt32();
407 if (tag != BOTTLE_TAG_STRING && tag != BOTTLE_TAG_VOCAB32) {
408 return false;
409 }
410 }
411 state->len--;
412 if (tag == BOTTLE_TAG_VOCAB32) {
413 if (is_vocab != nullptr) {
414 *is_vocab = true;
415 }
416 if (noMore()) {
417 return false;
418 }
419 std::int32_t v = reader.expectInt32();
420 if (reader.isError()) {
421 return false;
422 }
423 str = Vocab32::decode(v);
424 return true;
425 }
426 if (is_vocab != nullptr) {
427 *is_vocab = false;
428 }
429 if (noMore()) {
430 return false;
431 }
432 std::int32_t len = reader.expectInt32();
433 if (reader.isError()) {
434 return false;
435 }
436 if (len != 0 && noMore()) {
437 return false;
438 }
439 str.resize(len);
440 reader.expectBlock(const_cast<char*>(str.data()), len);
441 return !reader.isError();
442}
443
444bool WireReader::readBlock(char* const data, size_t len)
445{
446 if (state->len <= 0) {
447 return false;
448 }
449 if (noMore()) {
450 return false;
451 }
452 reader.expectBlock(data, len);
453 return !reader.isError();
454}
455
456
457bool WireReader::readBinary(std::string& str)
458{
459 if (state->len <= 0) {
460 return false;
461 }
462 if (state->code < 0) {
463 if (noMore()) {
464 return false;
465 }
466 std::int32_t tag = reader.expectInt32();
467 if (tag != BOTTLE_TAG_BLOB) {
468 return false;
469 }
470 }
471 state->len--;
472 if (noMore()) {
473 return false;
474 }
475 std::int32_t len = reader.expectInt32();
476 if (reader.isError()) {
477 return false;
478 }
479 if (len == 0) {
480 str = std::string();
481 return true;
482 }
483 if (len < 0) {
484 return false;
485 }
486 if (noMore()) {
487 return false;
488 }
489 str.resize(len);
490 reader.expectBlock(const_cast<char*>(str.data()), len);
491 return !reader.isError();
492}
493
495{
496 std::int32_t x1 = 0;
497 std::int32_t x2 = 0;
498 if (noMore()) {
499 return false;
500 }
501 x1 = reader.expectInt32();
502 if ((x1 & BOTTLE_TAG_LIST) == 0) {
503 return false;
504 }
505 if (noMore()) {
506 return false;
507 }
508 x2 = reader.expectInt32();
509 int code = (x1 & (~BOTTLE_TAG_LIST));
510 state->len = x2;
511 if (code != 0) {
512 state->code = code;
513 }
514 return !reader.isError();
515}
516
518{
519 if (!readListHeader()) {
520 return false;
521 }
522 return len == state->len;
523}
524
526{
527 if (!readListHeader()) {
528 return false;
529 }
530 if (!support_get_mode) {
531 return true;
532 }
533 if (state->len == 1) {
534 return true;
535 }
536 if (state->len != 4) {
537 return false;
538 }
539 // possibly old-style return: [is] foo val [ok]
540 std::int32_t v = 0;
541 if (!readVocab32(v)) {
542 return false;
543 }
544 if (v != VOCAB_IS) {
545 return false;
546 }
547 std::string dummy;
548 if (!readString(dummy)) {
549 return false; // string OR vocab
550 }
551 // now we are ready to consume real result
552 state->need_ok = true;
553 return true;
554}
555
557{
558 return reader;
559}
560
562{
563 flush_if_needed = false;
564 ConnectionWriter* writer = reader.getWriter();
565 if (writer != nullptr) {
566 return *writer;
567 }
568 return null_writer;
569}
570
572{
573 return reader.isValid();
574}
575
577{
578 return reader.isError();
579}
580
581std::string WireReader::readTag(size_t len)
582{
583 flush_if_needed = true;
584 std::string str;
585 bool is_vocab;
586 if (!readString(str, &is_vocab)) {
587 fail();
588 return {};
589 }
590 scanString(str, is_vocab);
591 if (!is_vocab) {
592 return str;
593 }
594 while (--len > 0 && is_vocab && state->len > 0) {
595 if (state->code >= 0) {
596 is_vocab = (state->code == BOTTLE_TAG_VOCAB32);
597 } else {
598 if (noMore()) {
599 return {};
600 }
601 std::int32_t x = reader.expectInt32();
602 reader.pushInt(x);
604 }
605 if (is_vocab) {
606 std::string str2;
607 if (!readString(str2, &is_vocab)) {
608 return {};
609 }
610 scanString(str2, is_vocab);
611 str += "_";
612 str += str2;
613 }
614 }
615 return str;
616}
617
619{
620 nstate.parent = state;
621 state = &nstate;
622 len = 0;
623 if (!readListHeader()) {
624 return;
625 }
626 len = static_cast<size_t>(state->len);
627}
628
630{
631 readListBegin(nstate, len);
632}
633
636 size_t& len)
637{
639 readListBegin(nstate, len);
640}
641
643{
644 state = state->parent;
645}
646
648{
649 state = state->parent;
650}
651
653{
654 state = state->parent;
655}
656
658{
659 if (!flush_if_needed) {
660 return false;
661 }
662 size_t pending = reader.getSize();
663 return pending == 0;
664}
665
666void WireReader::scanString(std::string& str, bool is_vocab)
667{
668 if (!support_get_mode) {
669 return;
670 }
671 if (get_string.empty()) {
672 if (get_mode && get_string.empty()) {
673 get_string = str;
674 get_is_vocab32 = is_vocab;
675 } else if (str == "get") {
676 get_mode = true;
677 } else {
678 get_string = "alt";
679 }
680 }
681}
682
683
685{
686 return get_mode;
687}
688
690{
691 return get_is_vocab32;
692}
693
694const std::string& WireReader::getString() const
695{
696 return get_string;
697}
#define BOTTLE_TAG_INT8
Definition Bottle.h:19
#define BOTTLE_TAG_FLOAT64
Definition Bottle.h:26
#define BOTTLE_TAG_VOCAB64
Definition Bottle.h:24
#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:27
#define BOTTLE_TAG_BLOB
Definition Bottle.h:28
#define BOTTLE_TAG_LIST
Definition Bottle.h:29
#define BOTTLE_TAG_VOCAB32
Definition Bottle.h:23
#define BOTTLE_TAG_FLOAT32
Definition Bottle.h:25
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:65
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition Bottle.cpp:236
A mini-server for performing network communication in the background.
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
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.
virtual bool read(yarp::os::idl::WireReader &reader)
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 readVocab64(yarp::conf::vocab64_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::int64_t vocab64_t
Definition numeric.h:79
std::string decode(NetInt32 code)
Convert a vocabulary identifier into a string.
Definition Vocab32.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 Vocab32.h:27
#define YARP_UNUSED(var)
Definition api.h:162