YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
RobotInterfaceDTD.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) yFatal() << "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
29namespace yarp::robotinterface {
30
31// Represent something like this in the xml file
32// <!DOCTYPE robot PUBLIC "-//YARP//DTD yarprobotinterface 1.0//EN" "http://www.yarp.it/DTD/yarprobotinterfaceV1.0.dtd">
33
34const std::string RobotInterfaceDTD::baseUri("http://www.yarp.it/DTD/yarprobotinterfaceV");
35const std::string RobotInterfaceDTD::ext(".dtd");
36
37
39{
40 if (type == "robot") {
42 }
43 if (type == "devices") {
45 }
46 if (type == "params") {
48 }
49 if (type == "actions") {
51 }
53}
54
56{
57 switch (doctype) {
59 return std::string("robot");
61 return std::string("devices");
63 return std::string("params");
65 return std::string("actions");
66 default:
67 return {};
68 }
69}
70
72{
73 return type != DocTypeUnknown && majorVersion != 0;
74}
75
77{
79 identifier = "-//YARP//DTD yarprobotinterface 3.0//EN";
80 uri = "http://www.yarp.it/DTD/yarprobotinterfaceV3.0.dtd";
81 majorVersion = 1;
82 minorVersion = 0;
83}
84
85bool RobotInterfaceDTD::parse(TiXmlUnknown* unknownNode, const std::string& curr_filename)
86{
87 // Very basic and ugly DTD tag parsing as TinyXML does not support it
88 // We just need the version numbers.
89
90 // Split tag in token
91 std::istringstream iss(unknownNode->ValueStr());
92 std::vector<std::string> tokens;
93 std::copy(std::istream_iterator<std::string>(iss),
94 std::istream_iterator<std::string>(),
95 std::back_inserter<std::vector<std::string>>(tokens));
96
97 // Merge token in quotes (and remove quotes)
98 for (auto it = tokens.begin(); it != tokens.end(); ++it) {
99 if (it->at(0) == '"') {
100 if (it->at(it->size() - 1) == '"') {
101 *it = it->substr(1, it->size() - 2);
102 } else {
103 std::string s = it->substr(1) + " ";
104 for (auto cit = it + 1; cit != tokens.end();) {
105 if (cit->at(cit->size() - 1) == '"') {
106 s += cit->substr(0, cit->size() - 1);
107 cit = tokens.erase(cit);
108 break;
109 }
110 s += *cit + " ";
111 cit = tokens.erase(cit);
112 }
113 *it = s;
114 }
115 }
116 }
117
118 if (tokens.size() != 5) {
119 SYNTAX_WARNING(unknownNode->Row()) << "Unknown node found" << tokens.size();
120 }
121
122 if (tokens.at(0) != "!DOCTYPE") {
123 SYNTAX_WARNING(unknownNode->Row()) << "Unknown node found";
124 }
125
126 type = StringToDocType(tokens.at(1));
128 SYNTAX_WARNING(unknownNode->Row()) << R"(Unknown document type. Supported document types are: "robot", "devices", "params")";
129 }
130
131 if (tokens.at(2) != "PUBLIC") {
132 SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Expected \"PUBLIC\", found" << tokens.at(2);
133 }
134
135 identifier = tokens.at(3); // For now just skip checks on the identifier
136 uri = tokens.at(4);
137
138 // Extract version numbers from the URI
139 std::size_t end1 = uri.find(RobotInterfaceDTD::ext, 0);
140 if (end1 == std::string::npos) {
141 SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Unknown url" << uri;
142 }
143 std::size_t start = RobotInterfaceDTD::baseUri.size();
144 std::size_t end2 = uri.find(RobotInterfaceDTD::ext, start);
145 if (end2 == std::string::npos) {
146 SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Unknown url" << uri;
147 }
148 std::string versionString = uri.substr(start, end2 - start);
149 std::size_t dot = versionString.find('.');
150 if (dot == std::string::npos) {
151 SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Unknown url" << uri;
152 }
153 std::string majorVersionString = versionString.substr(0, dot);
154 std::string minorVersionString = versionString.substr(dot + 1);
155 std::istringstream majiss(majorVersionString);
156 if (!(majiss >> majorVersion)) {
157 SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Missing version in Url" << uri;
158 }
159 std::istringstream miniss(minorVersionString);
160 if (!(miniss >> minorVersion)) {
161 SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Missing version in Url" << uri;
162 }
163
164 // If we got here, this is a valid DTD declaration
165 return true;
166}
167
168} // namespace yarp::robotinterface
#define SYNTAX_WARNING(line)
bool parse(TiXmlUnknown *unknownNode, const std::string &curr_filename)
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)
RobotInterfaceDTD::DocType StringToDocType(const std::string &type)