YARP
Yet Another Robot Platform
RobotInterfaceDTD.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
10 
17 
18 #include <yarp/os/LogStream.h>
19 #include <yarp/os/Network.h>
20 #include <yarp/os/Property.h>
21 
22 #include <algorithm>
23 #include <iterator>
24 #include <sstream>
25 #include <string>
26 #include <tinyxml.h>
27 #include <vector>
28 
29 #define SYNTAX_ERROR(line) yFatal() << "Syntax error while loading" << curr_filename << "at line" << line << "."
30 #define SYNTAX_WARNING(line) yWarning() << "Invalid syntax while loading" << curr_filename << "at line" << line << "."
31 
32 namespace yarp {
33 namespace robotinterface {
34 
35 // Represent something like this in the xml file
36 // <!DOCTYPE robot PUBLIC "-//YARP//DTD yarprobotinterface 1.0//EN" "http://www.yarp.it/DTD/yarprobotinterfaceV1.0.dtd">
37 
38 const std::string RobotInterfaceDTD::baseUri("http://www.yarp.it/DTD/yarprobotinterfaceV");
39 const std::string RobotInterfaceDTD::ext(".dtd");
40 
41 
43 {
44  if (type == "robot") {
46  } else if (type == "devices") {
48  } else if (type == "params") {
50  } else 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  } else {
111  s += *cit + " ";
112  cit = tokens.erase(cit);
113  }
114  }
115  *it = s;
116  }
117  }
118  }
119 
120  if (tokens.size() != 5) {
121  SYNTAX_WARNING(unknownNode->Row()) << "Unknown node found" << tokens.size();
122  }
123 
124  if (tokens.at(0) != "!DOCTYPE") {
125  SYNTAX_WARNING(unknownNode->Row()) << "Unknown node found";
126  }
127 
128  type = StringToDocType(tokens.at(1));
130  SYNTAX_WARNING(unknownNode->Row()) << R"(Unknown document type. Supported document types are: "robot", "devices", "params")";
131  }
132 
133  if (tokens.at(2) != "PUBLIC") {
134  SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Expected \"PUBLIC\", found" << tokens.at(2);
135  }
136 
137  identifier = tokens.at(3); // For now just skip checks on the identifier
138  uri = tokens.at(4);
139 
140  // Extract version numbers from the URI
141  std::size_t end1 = uri.find(RobotInterfaceDTD::ext, 0);
142  if (end1 == std::string::npos) {
143  SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Unknown url" << uri;
144  }
145  std::size_t start = RobotInterfaceDTD::baseUri.size();
146  std::size_t end2 = uri.find(RobotInterfaceDTD::ext, start);
147  if (end2 == std::string::npos) {
148  SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Unknown url" << uri;
149  }
150  std::string versionString = uri.substr(start, end2 - start);
151  std::size_t dot = versionString.find('.');
152  if (dot == std::string::npos) {
153  SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Unknown url" << uri;
154  }
155  std::string majorVersionString = versionString.substr(0, dot);
156  std::string minorVersionString = versionString.substr(dot + 1);
157  std::istringstream majiss(majorVersionString);
158  if (!(majiss >> majorVersion)) {
159  SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Missing version in Url" << uri;
160  }
161  std::istringstream miniss(minorVersionString);
162  if (!(miniss >> minorVersion)) {
163  SYNTAX_WARNING(unknownNode->Row()) << "Unknown document type. Missing version in Url" << uri;
164  }
165 
166  // If we got here, this is a valid DTD declaration
167  return true;
168 }
169 
170 } // namespace robotinterface
171 } // 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:461
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)
RobotInterfaceDTD::DocType StringToDocType(const std::string &type)
The main, catch-all namespace for YARP.
Definition: environment.h:18