YARP
Yet Another Robot Platform
XMLReaderFileV3.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
14
15#include <yarp/os/LogStream.h>
16#include <yarp/os/Network.h>
17#include <yarp/os/Property.h>
18
19#include <algorithm>
20#include <iterator>
21#include <sstream>
22#include <string>
23#include <tinyxml.h>
24#include <vector>
25
26#define SYNTAX_ERROR(line) yError() << "Syntax error while loading" << curr_filename << "at line" << line << "."
27#define SYNTAX_WARNING(line) yWarning() << "Invalid syntax while loading" << curr_filename << "at line" << line << "."
28
29// BUG in TinyXML, see
30// https://sourceforge.net/tracker/?func=detail&aid=3567726&group_id=13559&atid=113559
31// When this bug is fixed upstream we can enable this
32#define TINYXML_UNSIGNED_INT_BUG 0
33
35{
36public:
38 virtual ~Private();
39
43
47
54
58
59 bool PerformInclusions(TiXmlNode* pParent, const std::string& parent_fileName, const std::string& current_path);
60 void ReplaceAllStrings(std::string& str, const std::string& from, const std::string& to);
62
63#ifdef USE_DTD
65#endif
66
69 std::string curr_filename;
70 unsigned int minorVersion;
71 unsigned int majorVersion;
72};
73
74
76 parent(p),
77 minorVersion(0),
78 majorVersion(0)
79{
80 verbose_output = false;
81}
82
84
86{
87 yDebug() << "Reading file" << fileName.c_str();
88 auto* doc = new TiXmlDocument(fileName.c_str());
89 if (!doc->LoadFile()) {
90 SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
92 }
93
94 if (!doc->RootElement()) {
95 SYNTAX_ERROR(doc->Row()) << "No root element.";
97 }
98
99#ifdef USE_DTD
100 for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
101 if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
102 if (dtd.parse(childNode->ToUnknown(), curr_filename)) {
103 break;
104 }
105 }
106 }
107
108 if (!dtd.valid()) {
109 SYNTAX_WARNING(doc->Row()) << "No DTD found. Assuming version yarprobotinterfaceV1.0";
110 dtd.setDefault();
112 }
113
114 if (dtd.type != RobotInterfaceDTD::DocTypeRobot) {
115 SYNTAX_WARNING(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeRobot)
116 << ". Found" << DocTypeToString(dtd.type);
117 }
118
119 if (dtd.majorVersion != 1 || dtd.minorVersion != 0) {
120 SYNTAX_WARNING(doc->Row()) << "Only yarprobotinterface DTD version 1.0 is supported";
121 }
122#endif
123
124 std::string current_path;
125 current_path = fileName.substr(0, fileName.find_last_of("\\/"));
126 std::string current_filename;
127 std::string log_filename;
128 current_filename = fileName.substr(fileName.find_last_of("\\/") + 1);
129 log_filename = current_filename.substr(0, current_filename.find(".xml"));
130 log_filename += "_preprocessor_log.xml";
131 double start_time = yarp::os::Time::now();
132 PerformInclusions(doc->RootElement(), current_filename, current_path);
133 double end_time = yarp::os::Time::now();
134 std::string full_log_withpath = current_path + std::string("\\") + log_filename;
135 std::replace(full_log_withpath.begin(), full_log_withpath.end(), '\\', '/');
136 yDebug() << "Preprocessor complete in: " << end_time - start_time << "s";
137 if (verbose_output) {
138 yDebug() << "Preprocessor output stored in: " << full_log_withpath;
139 doc->SaveFile(full_log_withpath);
140 }
141 yarp::robotinterface::XMLReaderResult result = readRobotTag(doc->RootElement());
142 delete doc;
143
144 // yDebug() << robot;
145
146 return result;
147}
148
150{
151 curr_filename = " XML runtime string ";
152 auto* doc = new TiXmlDocument();
153 if (!doc->Parse(xmlString.c_str())) {
154 SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
156 }
157
158 if (!doc->RootElement()) {
159 SYNTAX_ERROR(doc->Row()) << "No root element.";
161 }
162
163 yarp::robotinterface::XMLReaderResult result = readRobotTag(doc->RootElement());
164 delete doc;
165
166 return result;
167}
168
169bool yarp::robotinterface::impl::XMLReaderFileV3::Private::PerformInclusions(TiXmlNode* pParent, const std::string& parent_fileName, const std::string& current_path)
170{
171loop_start: //goto label
172 for (TiXmlElement* childElem = pParent->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
173#ifdef DEBUG_PARSER
174 std::string a;
175 if (childElem->FirstAttribute())
176 a = childElem->FirstAttribute()->Value();
177 yDebug() << "Parsing" << childElem->Value() << a;
178#endif
179 std::string elemString = childElem->ValueStr();
180 if (elemString == "file") {
181 yFatal() << "'file' attribute is forbidden in yarprobotinterface DTD format 3.0. Error found in " << parent_fileName;
182 return false;
183 }
184
185 if (elemString == "xi:include") {
186 std::string href_filename;
187 std::string included_filename;
188 std::string included_path;
189 if (childElem->QueryStringAttribute("href", &href_filename) == TIXML_SUCCESS) {
190 included_path = std::string(current_path).append("\\").append(href_filename.substr(0, href_filename.find_last_of("\\/")));
191 included_filename = href_filename.substr(href_filename.find_last_of("\\/") + 1);
192 std::string full_path_file = std::string(included_path).append("\\").append(included_filename);
193 TiXmlDocument included_file;
194
195 std::replace(full_path_file.begin(), full_path_file.end(), '\\', '/');
196 if (included_file.LoadFile(full_path_file)) {
197 PerformInclusions(included_file.RootElement(), included_filename, included_path);
198 //included_file.RootElement()->SetAttribute("xml:base", href_filename); //not yet implemented
199 included_file.RootElement()->RemoveAttribute("xmlns:xi");
200 if (pParent->ReplaceChild(childElem, *included_file.FirstChildElement())) {
201 //the replace operation invalidates the iterator, hence we need to restart the parsing of this level
202 goto loop_start;
203 } else {
204 //fatal error
205 yFatal() << "Failed to include: " << included_filename << " in: " << parent_fileName;
206 return false;
207 }
208 } else {
209 //fatal error
210 yError() << included_file.ErrorDesc() << " file" << full_path_file << "included by " << parent_fileName << "at line" << childElem->Row();
211 yFatal() << "In file:" << included_filename << " included by: " << parent_fileName << " at line: " << childElem->Row();
212 return false;
213 }
214 } else {
215 //fatal error
216 yFatal() << "Syntax error in: " << parent_fileName << " while searching for href attribute";
217 return false;
218 }
219 }
220 PerformInclusions(childElem, parent_fileName, current_path);
221 }
222 return true;
223}
224
226{
228 result.parsingIsSuccessful = true;
229
230 if (robotElem->ValueStr() != "robot") {
231 SYNTAX_ERROR(robotElem->Row()) << "Root element should be \"robot\". Found" << robotElem->ValueStr();
233 }
234
235 if (robotElem->QueryStringAttribute("name", &result.robot.name()) != TIXML_SUCCESS) {
236 SYNTAX_ERROR(robotElem->Row()) << R"("robot" element should contain the "name" attribute)";
238 }
239
240#if TINYXML_UNSIGNED_INT_BUG
241 if (robotElem->QueryUnsignedAttribute("build", &result.robot.build()) != TIXML_SUCCESS) {
242 // No build attribute. Assuming build="0"
243 SYNTAX_WARNING(robotElem->Row()) << "\"robot\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
244 }
245#else
246 int tmp;
247 if (robotElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) {
248 // No build attribute. Assuming build="0"
249 SYNTAX_WARNING(robotElem->Row()) << R"("robot" element should contain the "build" attribute [unsigned int]. Assuming 0)";
250 tmp = 0;
251 }
252 result.robot.build() = static_cast<unsigned>(tmp);
253#endif
254
255 // If portprefix is already present in config we use that one
256 if (!config.check("portprefix"))
257 {
258 if (robotElem->QueryStringAttribute("portprefix", &result.robot.portprefix()) != TIXML_SUCCESS) {
259 SYNTAX_WARNING(robotElem->Row()) << R"("robot" element should contain the "portprefix" attribute. Using "name" attribute)";
260 result.robot.portprefix() = result.robot.name();
261 }
262 config.put("portprefix",result.robot.portprefix());
263 } else {
264 result.robot.portprefix() = config.find("portprefix").asString();
265 }
266
267 // FIXME DTD >= 4 Make this the default behaviour
268 bool reverse = false;
269 if (robotElem->QueryBoolAttribute("reverse-shutdown-action-order", &reverse) == TIXML_WRONG_TYPE) {
270 SYNTAX_ERROR(robotElem->Row()) << R"(The "reverse-shutdown-action-order" attribute in the "robot" element should be a bool.)";
272 }
273 result.robot.setReverseShutdownActionOrder(reverse);
274
275 // yDebug() << "Found robot [" << robot.name() << "] build [" << robot.build() << "] portprefix [" << robot.portprefix() << "]";
276
277 for (TiXmlElement* childElem = robotElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
278 std::string elemString = childElem->ValueStr();
279 if (elemString == "device" || elemString == "devices") {
280 for (const auto& childDevice : readDevices(childElem, result)) {
281 result.robot.devices().push_back(childDevice);
282 }
283 } else {
284 for (const auto& childParam : readParams(childElem, result)) {
285 result.robot.params().push_back(childParam);
286 }
287 }
288 }
289
290 return result;
291}
292
293
296{
297 const std::string& valueStr = devicesElem->ValueStr();
298
299 if (valueStr == "device") {
300 // yDebug() << valueStr;
302 deviceList.push_back(readDeviceTag(devicesElem, result));
303 return deviceList;
304 }
305 if (valueStr == "devices") {
306 // "devices"
307 return readDevicesTag(devicesElem, result);
308 }
309
310 SYNTAX_ERROR(devicesElem->Row()) << R"(Expected "device" or "devices". Found)" << valueStr;
311 result.parsingIsSuccessful = false;
313}
314
317{
318 const std::string& valueStr = deviceElem->ValueStr();
319
320 if (valueStr != "device") {
321 SYNTAX_ERROR(deviceElem->Row()) << "Expected \"device\". Found" << valueStr;
322 result.parsingIsSuccessful = false;
324 }
325
327
328 if (deviceElem->QueryStringAttribute("name", &device.name()) != TIXML_SUCCESS) {
329 SYNTAX_ERROR(deviceElem->Row()) << R"("device" element should contain the "name" attribute)";
330 result.parsingIsSuccessful = false;
331 return device;
332 }
333
334 // yDebug() << "Found device [" << device.name() << "]";
335
336 if (deviceElem->QueryStringAttribute("type", &device.type()) != TIXML_SUCCESS) {
337 SYNTAX_ERROR(deviceElem->Row()) << R"("device" element should contain the "type" attribute)";
338 result.parsingIsSuccessful = false;
339 return device;
340 }
341
342 device.params().push_back(yarp::robotinterface::Param("robotName", result.robot.portprefix()));
343
344 for (TiXmlElement* childElem = deviceElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
345 if (childElem->ValueStr() == "action" || childElem->ValueStr() == "actions") {
346 for (const auto& childAction : readActions(childElem, result)) {
347 device.actions().push_back(childAction);
348 }
349 } else {
350 for (const auto& childParam : readParams(childElem, result)) {
351 device.params().push_back(childParam);
352 }
353 }
354 }
355
356 // yDebug() << device;
357 return device;
358}
359
362{
363 //const std::string &valueStr = devicesElem->ValueStr();
364
367
368 for (TiXmlElement* childElem = devicesElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
369 // FIXME Check DTD >= 3.2
370 // "subdevice" is not allowed in the "devices" tag
371 if (childElem->ValueStr() == "param" || childElem->ValueStr() == "group" || childElem->ValueStr() == "paramlist" || childElem->ValueStr() == "params") {
372 for (const auto& childParam : readParams(childElem, result)) {
373 params.push_back(childParam);
374 }
375 } else {
376 for (const auto& childDevice : readDevices(childElem, result)) {
377 devices.push_back(childDevice);
378 }
379 }
380 }
381
382
383 for (auto& device : devices) {
384 device.params().insert(device.params().begin(), params.begin(), params.end());
385 }
386
387 return devices;
388}
389
392{
393 const std::string& valueStr = paramsElem->ValueStr();
394
395 if (valueStr == "param") {
397 params.push_back(readParamTag(paramsElem, result));
398 return params;
399 }
400 if (valueStr == "group") {
402 params.push_back(readGroupTag(paramsElem, result));
403 return params;
404 }
405 if (valueStr == "paramlist") {
406 return readParamListTag(paramsElem, result);
407 }
408 if (valueStr == "subdevice") {
409 return readSubDeviceTag(paramsElem, result);
410 }
411 if (valueStr == "params") {
412 return readParamsTag(paramsElem, result);
413 }
414
415 SYNTAX_ERROR(paramsElem->Row()) << R"(Expected "param", "group", "paramlist", "subdevice", or "params". Found)" << valueStr;
416 result.parsingIsSuccessful = false;
418}
419
420void yarp::robotinterface::impl::XMLReaderFileV3::Private::ReplaceAllStrings(std::string& str, const std::string& from, const std::string& to)
421{
422 if(from.empty())
423 return;
424 size_t start_pos = 0;
425 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
426 str.replace(start_pos, from.length(), to);
427 start_pos += to.length();
428 }
429}
430
431
434{
435 if (paramElem->ValueStr() != "param") {
436 SYNTAX_ERROR(paramElem->Row()) << "Expected \"param\". Found" << paramElem->ValueStr();
437 result.parsingIsSuccessful = false;
439 }
440
442
443 if (paramElem->QueryStringAttribute("name", &param.name()) != TIXML_SUCCESS) {
444 SYNTAX_ERROR(paramElem->Row()) << R"("param" element should contain the "name" attribute)";
445 result.parsingIsSuccessful = false;
447 }
448
449 // yDebug() << "Found param [" << param.name() << "]";
450
451 const char* valueText = paramElem->GetText();
452 if (!valueText) {
453 SYNTAX_ERROR(paramElem->Row()) << R"("param" element should have a value [ "name" = )" << param.name() << "]";
454 result.parsingIsSuccessful = false;
456 }
457
458 // First process extern-name
459 std::string extern_name;
460 if (paramElem->QueryStringAttribute("extern-name", &extern_name) == TIXML_SUCCESS && config.check(extern_name)) {
461 // FIXME Check DTD >= 3.1
462 if (config.find(extern_name).isList())
463 {
464 param.value() = "(" + config.find(extern_name).asList()->toString() + ")";
465 }
466 else
467 {
468 param.value() = config.find(extern_name).toString();
469 }
470 } else {
471 param.value() = valueText;
472 }
473
474 // After process ${portprefix}
475 std::string paramValueBefore = param.value();
476 std::string paramValueAfter = paramValueBefore;
477 std::string portprefix = config.find("portprefix").toString();
478 ReplaceAllStrings(paramValueAfter, "${portprefix}", portprefix);
479 param.value() = paramValueAfter;
480
481
482
483 // yDebug() << param;
484 return param;
485}
486
489{
490 if (groupElem->ValueStr() != "group") {
491 SYNTAX_ERROR(groupElem->Row()) << "Expected \"group\". Found" << groupElem->ValueStr();
492 result.parsingIsSuccessful = false;
494 }
495
496 yarp::robotinterface::Param group(true);
497
498 if (groupElem->QueryStringAttribute("name", &group.name()) != TIXML_SUCCESS) {
499 SYNTAX_ERROR(groupElem->Row()) << R"("group" element should contain the "name" attribute)";
500 result.parsingIsSuccessful = false;
502 }
503
504 // yDebug() << "Found group [" << group.name() << "]";
505
507 for (TiXmlElement* childElem = groupElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
508 for (const auto& childParam : readParams(childElem, result)) {
509 params.push_back(childParam);
510 }
511 }
512 if (params.empty()) {
513 SYNTAX_ERROR(groupElem->Row()) << "\"group\" cannot be empty";
514 result.parsingIsSuccessful = false;
516 }
517
518 std::string groupString;
519 for (auto& param : params) {
520 if (!groupString.empty()) {
521 groupString += " ";
522 }
523 groupString += "(" + param.name() + " " + param.value() + ")";
524 }
525
526 group.value() = groupString;
527
528 return group;
529}
530
533{
534 if (paramListElem->ValueStr() != "paramlist") {
535 SYNTAX_ERROR(paramListElem->Row()) << "Expected \"paramlist\". Found" << paramListElem->ValueStr();
536 result.parsingIsSuccessful = false;
538 }
539
542
543 if (paramListElem->QueryStringAttribute("name", &mainparam.name()) != TIXML_SUCCESS) {
544 SYNTAX_ERROR(paramListElem->Row()) << R"("paramlist" element should contain the "name" attribute)";
545 result.parsingIsSuccessful = false;
547 }
548
549 params.push_back(mainparam);
550
551 // yDebug() << "Found paramlist [" << params.at(0).name() << "]";
552
553 for (TiXmlElement* childElem = paramListElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
554 if (childElem->ValueStr() != "elem") {
555 SYNTAX_ERROR(childElem->Row()) << "Expected \"elem\". Found" << childElem->ValueStr();
556 result.parsingIsSuccessful = false;
558 }
559
561
562 if (childElem->QueryStringAttribute("name", &childParam.name()) != TIXML_SUCCESS) {
563 SYNTAX_ERROR(childElem->Row()) << R"("elem" element should contain the "name" attribute)";
564 result.parsingIsSuccessful = false;
566 }
567
568 const char* valueText = childElem->GetText();
569 if (!valueText) {
570 SYNTAX_ERROR(childElem->Row()) << R"("elem" element should have a value [ "name" = )" << childParam.name() << "]";
571 result.parsingIsSuccessful = false;
573 }
574 childParam.value() = valueText;
575
576 params.push_back(childParam);
577 }
578
579 if (params.empty()) {
580 SYNTAX_ERROR(paramListElem->Row()) << "\"paramlist\" cannot be empty";
581 result.parsingIsSuccessful = false;
583 }
584
585 // +1 skips the first element, that is the main param
586 for (auto it = params.begin() + 1; it != params.end(); ++it) {
587 yarp::robotinterface::Param& param = *it;
588 params.at(0).value() += (params.at(0).value().empty() ? "(" : " ") + param.name();
589 }
590 params.at(0).value() += ")";
591
592 // yDebug() << params;
593 return params;
594}
595
598{
599 if (subDeviceElem->ValueStr() != "subdevice") {
600 SYNTAX_ERROR(subDeviceElem->Row()) << "Expected \"subdevice\". Found" << subDeviceElem->ValueStr();
601 result.parsingIsSuccessful = false;
603 }
604
606
607 //FIXME yarp::robotinterface::Param featIdParam;
608 yarp::robotinterface::Param subDeviceParam;
609
610 //FIXME featIdParam.name() = "FeatId";
611 subDeviceParam.name() = "subdevice";
612
613 //FIXME if (subDeviceElem->QueryStringAttribute("name", &featIdParam.value()) != TIXML_SUCCESS) {
614 // SYNTAX_ERROR(subDeviceElem->Row()) << "\"subdevice\" element should contain the \"name\" attribute";
615 // }
616
617 if (subDeviceElem->QueryStringAttribute("type", &subDeviceParam.value()) != TIXML_SUCCESS) {
618 SYNTAX_ERROR(subDeviceElem->Row()) << R"("subdevice" element should contain the "type" attribute)";
619 result.parsingIsSuccessful = false;
621 }
622
623 //FIXME params.push_back(featIdParam);
624 params.push_back(subDeviceParam);
625
626 // yDebug() << "Found subdevice [" << params.at(0).value() << "]";
627
628 for (TiXmlElement* childElem = subDeviceElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
629 for (const auto& childParam : readParams(childElem, result)) {
630 params.push_back(yarp::robotinterface::Param(childParam.name(), childParam.value()));
631 }
632 }
633
634 // yDebug() << params;
635 return params;
636}
637
640{
641 //const std::string &valueStr = paramsElem->ValueStr();
642
644 for (TiXmlElement* childElem = paramsElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
645 for (const auto & childParam : readParams(childElem, result)) {
646 params.push_back(childParam);
647 }
648 }
649
650 return params;
651}
652
655{
656 const std::string& valueStr = actionsElem->ValueStr();
657
658 if (valueStr != "action" && valueStr != "actions") {
659 SYNTAX_ERROR(actionsElem->Row()) << R"(Expected "action" or "actions". Found)" << valueStr;
660 }
661
662 if (valueStr == "action") {
664 actionList.push_back(readActionTag(actionsElem, result));
665 return actionList;
666 }
667 // "actions"
668 return readActionsTag(actionsElem, result);
669}
670
673{
674 if (actionElem->ValueStr() != "action") {
675 SYNTAX_ERROR(actionElem->Row()) << "Expected \"action\". Found" << actionElem->ValueStr();
676 result.parsingIsSuccessful = false;
678 }
679
681
682 if (actionElem->QueryValueAttribute<yarp::robotinterface::ActionPhase>("phase", &action.phase()) != TIXML_SUCCESS || action.phase() == yarp::robotinterface::ActionPhaseUnknown) {
683 SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "phase" attribute [startup|interrupt{1,2,3}|shutdown])";
684 result.parsingIsSuccessful = false;
686 }
687
688
689 if (actionElem->QueryValueAttribute<yarp::robotinterface::ActionType>("type", &action.type()) != TIXML_SUCCESS || action.type() == yarp::robotinterface::ActionTypeUnknown) {
690 SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "type" attribute [configure|calibrate|attach|abort|detach|park|custom])";
691 result.parsingIsSuccessful = false;
693 }
694
695 // yDebug() << "Found action [ ]";
696
697#if TINYXML_UNSIGNED_INT_BUG
698 if (actionElem->QueryUnsignedAttribute("level", &action.level()) != TIXML_SUCCESS) {
699 SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"level\" attribute [unsigned int]";
700 }
701#else
702 int tmp;
703 if (actionElem->QueryIntAttribute("level", &tmp) != TIXML_SUCCESS || tmp < 0) {
704 SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "level" attribute [unsigned int])";
705 result.parsingIsSuccessful = false;
707 }
708 action.level() = static_cast<unsigned>(tmp);
709#endif
710
711 for (TiXmlElement* childElem = actionElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
712 for (const auto& childParam : readParams(childElem, result)) {
713 action.params().push_back(childParam);
714 }
715 }
716
717 // yDebug() << action;
718 return action;
719}
720
723{
724 //const std::string &valueStr = actionsElem->ValueStr();
725
726 std::string robotName;
727 if (actionsElem->QueryStringAttribute("robot", &robotName) != TIXML_SUCCESS) {
728 SYNTAX_WARNING(actionsElem->Row()) << R"("actions" element should contain the "robot" attribute)";
729 }
730
731 if (robotName != result.robot.name()) {
732 SYNTAX_WARNING(actionsElem->Row()) << "Trying to import a file for the wrong robot. Found" << robotName << "instead of" << result.robot.name();
733 }
734
735 unsigned int build;
736#if TINYXML_UNSIGNED_INT_BUG
737 if (actionsElem->QueryUnsignedAttribute("build", &build()) != TIXML_SUCCESS) {
738 // No build attribute. Assuming build="0"
739 SYNTAX_WARNING(actionsElem->Row()) << "\"actions\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
740 }
741#else
742 int tmp;
743 if (actionsElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) {
744 // No build attribute. Assuming build="0"
745 SYNTAX_WARNING(actionsElem->Row()) << R"("actions" element should contain the "build" attribute [unsigned int]. Assuming 0)";
746 tmp = 0;
747 }
748 build = static_cast<unsigned>(tmp);
749#endif
750
751 if (build != result.robot.build()) {
752 SYNTAX_WARNING(actionsElem->Row()) << "Import a file for a different robot build. Found" << build << "instead of" << result.robot.build();
753 }
754
756 for (TiXmlElement* childElem = actionsElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
757 for (const auto & childAction : readActions(childElem, result)) {
758 actions.push_back(childAction);
759 }
760 }
761
762 return actions;
763}
764
765
767 const yarp::os::Searchable& config,
768 bool verb)
769{
770 mPriv->config.fromString(config.toString());
771 mPriv->verbose_output = verb;
772 auto ret = mPriv->readRobotFromFile(filename);
773 mPriv->config.clear();
774 return ret;
775}
776
778 const yarp::os::Searchable& config,
779 bool verb)
780{
781 mPriv->config.fromString(config.toString());
782 mPriv->verbose_output = verb;
783 auto ret = mPriv->readRobotFromString(xmlString);
784 mPriv->config.clear();
785 return ret;
786}
787
788
790 mPriv(new Private(this))
791{
792}
793
795{
796 delete mPriv;
797}
bool ret
#define yError(...)
Definition: Log.h:356
#define yDebug(...)
Definition: Log.h:270
#define yFatal(...)
Definition: Log.h:377
#define SYNTAX_ERROR(line)
#define SYNTAX_WARNING(line)
A class for storing options and configuration information.
Definition: Property.h:33
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1063
void clear()
Remove all associations.
Definition: Property.cpp:1057
A base class for nested structures that can be searched.
Definition: Searchable.h:56
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
unsigned int & level()
Definition: Action.cpp:102
ActionPhase & phase()
Definition: Action.cpp:92
ActionList & actions()
Definition: Device.cpp:270
std::string & type()
Definition: Device.cpp:260
std::string & name()
Definition: Device.cpp:255
std::string & name()
Definition: Param.cpp:80
std::string & value()
Definition: Param.cpp:85
std::string & portprefix()
Definition: Robot.cpp:520
DeviceList & devices()
Definition: Robot.cpp:562
ParamList & params()
Definition: Robot.cpp:557
void setReverseShutdownActionOrder(bool reverseShutdownActionOrder)
Definition: Robot.cpp:552
std::string & name()
Definition: Robot.cpp:510
unsigned int & build()
Definition: Robot.cpp:515
Result of the parsing of yarp::robotinterface::XMLReader.
Definition: XMLReader.h:26
bool parsingIsSuccessful
True if the parsing was successful, false otherwise.
Definition: XMLReader.h:38
Robot robot
If parsingIsSuccessful is true, contains a valid robot instance.
Definition: XMLReader.h:43
static XMLReaderResult ParsingFailed()
Definition: XMLReader.h:28
void ReplaceAllStrings(std::string &str, const std::string &from, const std::string &to)
yarp::robotinterface::Device readDeviceTag(TiXmlElement *deviceElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::Param readParamTag(TiXmlElement *paramElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::XMLReaderResult readRobotFromString(const std::string &xmlString)
yarp::robotinterface::ActionList readActionsTag(TiXmlElement *actionsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readSubDeviceTag(TiXmlElement *subDeviceElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::DeviceList readDevices(TiXmlElement *devicesElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readParamListTag(TiXmlElement *paramListElem, yarp::robotinterface::XMLReaderResult &result)
bool PerformInclusions(TiXmlNode *pParent, const std::string &parent_fileName, const std::string &current_path)
yarp::robotinterface::XMLReaderResult readRobotTag(TiXmlElement *robotElem)
yarp::robotinterface::Param readGroupTag(TiXmlElement *groupElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readParams(TiXmlElement *paramsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::DeviceList readDevicesTag(TiXmlElement *devicesElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ActionList readActions(TiXmlElement *actionsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::Action readActionTag(TiXmlElement *actionElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readParamsTag(TiXmlElement *paramsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::XMLReaderResult readRobotFromFile(const std::string &fileName)
yarp::robotinterface::XMLReaderResult getRobotFromString(const std::string &xmlString, const yarp::os::Searchable &config, bool verbose=false) override
yarp::robotinterface::XMLReaderResult getRobotFromFile(const std::string &filename, const yarp::os::Searchable &config, bool verbose=false) override
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121
yarp::robotinterface::Param Param
Definition: Param.h:26
yarp::robotinterface::Device Device
Definition: Device.h:31
yarp::robotinterface::Action Action
Definition: Action.h:26
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)
std::vector< robotinterface::Action > ActionList
Definition: Types.h:31
std::vector< robotinterface::Param > ParamList
Definition: Types.h:30
std::vector< robotinterface::Device > DeviceList
Definition: Types.h:32