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