GCC Code Coverage Report


Directory: ./
File: src/parser/parser.cc
Date: 2025-06-05 11:04:44
Exec Total Coverage
Lines: 146 173 84.4%
Functions: 33 37 89.2%
Branches: 130 288 45.1%

Line Branch Exec Source
1 // Copyright (c) 2014, LAAS-CNRS
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // 1. Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27 // DAMAGE.
28
29 #include <hpp/util/debug.hh>
30 #include <stdexcept>
31 // #include <resource_retriever/retriever.h>
32
33 #include <pinocchio/parsers/utils.hpp> // ::pinocchio::retrieveResourcePath
34 #include <pinocchio/utils/file-explorer.hpp> // ::pinocchio::rosPaths
35
36 #include "hpp/manipulation/parser/parser.hh"
37 #include "hpp/manipulation/srdf/factories.hh"
38
39 namespace hpp {
40 namespace manipulation {
41 namespace parser {
42 9 Parser::Parser(bool fillWithDefaultFactories, FactoryType defaultFactory)
43 9 : root_(NULL), defaultFactory_(defaultFactory) {
44
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (fillWithDefaultFactories) {
45
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("robot", create<srdf::RobotFactory>);
46
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("handle", create<srdf::HandleFactory>);
47
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("gripper", create<srdf::GripperFactory>);
48
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("position", create<srdf::PositionFactory>);
49
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("mask", create<SequenceFactory<bool> >);
50
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("mask_complement", create<SequenceFactory<bool> >);
51
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("contact", create<srdf::ContactFactory>);
52
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("point", create<srdf::ContactFactory::PointFactory>);
53
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("triangle", create<srdf::ContactFactory::TriangleFactory>);
54
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("shape", create<srdf::ContactFactory::ShapeFactory>);
55
56 /// This removes warnings
57
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("link", create<ObjectFactory>);
58
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("disable_collisions", create<IgnoreTagFactory>);
59
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("material", create<IgnoreTagFactory>);
60
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 addObjectFactory("texture", create<IgnoreTagFactory>);
61 }
62 9 }
63
64 9 Parser::~Parser() {
65 9 for (ObjectFactoryList::iterator it = objectFactories_.begin();
66
2/2
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 9 times.
70 it != objectFactories_.end(); ++it)
67
1/2
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
61 delete *it;
68
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 if (root_ != NULL) delete root_;
69 9 }
70
71 6 void Parser::parseString(const std::string& xmlString, DevicePtr_t robot) {
72 6 device_ = robot;
73
74 6 loadString(xmlString.c_str());
75 try {
76
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 parse();
77 } catch (const std::exception& exc) {
78 std::ostringstream oss;
79 oss << "in XML string, " << exc.what();
80 throw std::runtime_error(oss.str().c_str());
81 }
82 6 }
83
84 3 void Parser::parseFile(const std::string& filename, DevicePtr_t robot) {
85 3 device_ = robot;
86
87 std::string fn =
88
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 ::pinocchio::retrieveResourcePath(filename, ::pinocchio::rosPaths());
89
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 loadFile(fn.c_str());
90 try {
91
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 parse();
92 } catch (const std::exception& exc) {
93 std::ostringstream oss;
94 oss << "in " << filename << ", " << exc.what();
95 throw std::runtime_error(oss.str().c_str());
96 }
97 3 }
98
99 3 void Parser::loadFile(const char* filename) {
100 3 doc_.LoadFile(filename);
101
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (doc_.Error()) {
102 std::cerr << doc_.ErrorStr() << std::endl;
103 return;
104 }
105 }
106
107 6 void Parser::loadString(const char* xmlstring) {
108 6 doc_.Parse(xmlstring);
109
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (doc_.Error()) {
110 std::cerr << doc_.ErrorStr() << std::endl;
111 }
112 6 }
113
114 9 void Parser::parse() {
115 9 const XMLElement* el = doc_.RootElement();
116
1/4
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
9 root_ = new RootFactory(device_);
117 9 root_->prefix(prefix_);
118
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 while (el != NULL) {
119 9 parseElement(el, root_);
120 9 el = el->NextSiblingElement();
121 }
122 9 for (ObjectFactoryList::iterator it = objectFactories_.begin();
123
2/2
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 9 times.
70 it != objectFactories_.end(); ++it)
124
1/2
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
61 (*it)->finishFile();
125 9 }
126
127 37 void Parser::addObjectFactory(const std::string& tagname, FactoryType factory) {
128 ObjectFactoryInsertRet ret =
129
2/4
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
37 objFactoryMap_.insert(ObjectFactoryPair(tagname, factory));
130
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
37 if (!ret.second) throw std::logic_error("This tagname already exist");
131 37 }
132
133 61 void Parser::parseElement(const XMLElement* element, ObjectFactory* parent) {
134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
95 if (element == NULL) return;
135
136 61 ObjectFactory* o = NULL;
137 /// Look for this element in the map
138
3/6
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 61 times.
✗ Branch 8 not taken.
122 ObjectFactoryMap::const_iterator it = objFactoryMap_.find(element->Value());
139
2/2
✓ Branch 3 taken 55 times.
✓ Branch 4 taken 6 times.
61 if (it != objFactoryMap_.end()) {
140
1/2
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
55 o = it->second(parent, element);
141 } else {
142
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 o = defaultFactory_(parent, element);
143 hppDout(warning, "I have no factory for tag " << o->tagName());
144 }
145
1/2
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
61 objectFactories_.push_back(o);
146
3/4
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 27 times.
61 if (!o->init()) return;
147 27 const XMLAttribute* attr = element->FirstAttribute();
148
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 27 times.
53 while (attr != NULL) {
149
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 o->setAttribute(attr);
150 26 attr = attr->Next();
151 }
152
2/4
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
27 if (!o->finishAttributes()) return;
153
154 /// Loop over is child tags
155 27 const XMLNode* el = element->FirstChild();
156
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 27 times.
86 while (el != NULL) {
157
3/4
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
✓ Branch 4 taken 7 times.
59 if (el->ToElement() != NULL) {
158
2/4
✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 52 times.
✗ Branch 5 not taken.
52 parseElement(el->ToElement(), o);
159
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
7 } else if (el->ToUnknown() != NULL) {
160 hppDout(warning, "Unknown Node in XML file: " << el->Value());
161
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
7 } else if (el->ToText() != NULL) {
162
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
7 o->addTextChild(el->ToText());
163 } else if (el->ToComment() != NULL) {
164 }
165 59 el = el->NextSibling();
166 }
167
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 o->finishTags();
168 }
169
170 1 std::ostream& Parser::print(std::ostream& os) const {
171 1 os << "Parser with " << objectFactories_.size() << " object." << std::endl;
172
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (root_ != NULL) os << *root_;
173 1 return os;
174 }
175
176 1 std::ostream& operator<<(std::ostream& os, const Parser& p) {
177 1 return p.print(os);
178 }
179
180 8 std::ostream& operator<<(std::ostream& os, const ObjectFactory& o) {
181 8 return o.print(os);
182 }
183
184 61 ObjectFactory::ObjectFactory(ObjectFactory* parent, const XMLElement* element)
185 61 : parent_(parent), root_(NULL), element_(element), id_(-1) {
186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (parent_ == NULL) {
187 root_ = dynamic_cast<RootFactory*>(this);
188 if (root_ == NULL)
189 throw std::logic_error(
190 "ObjectFactory with no parent must be RootFactory");
191 } else {
192
1/2
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
61 root_ = parent_->root();
193
2/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 61 times.
✗ Branch 4 not taken.
61 if (element_ != NULL) parent_->addChild(this);
194 }
195 61 }
196
197 9 ObjectFactory::ObjectFactory(RootFactory* root)
198 9 : parent_(NULL), root_(root), element_(NULL), id_(-1) {}
199
200 27 bool ObjectFactory::init() { return true; }
201
202 25 bool ObjectFactory::finishAttributes() { return true; }
203
204 12 void ObjectFactory::finishTags() {}
205
206 61 void ObjectFactory::finishFile() {}
207
208 void ObjectFactory::addTextChild(const XMLText* /* text */) {}
209
210 69 std::string ObjectFactory::tagName() const {
211
4/6
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 68 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 68 times.
✗ Branch 7 not taken.
205 if (element_ != NULL) return element_->Value();
212
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return "No element";
213 }
214
215 16 std::string ObjectFactory::name() const { return name_; }
216
217 16 void ObjectFactory::name(const std::string& n) { name_ = n; }
218
219
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
48 void ObjectFactory::name(const char* n) { name(std::string(n)); }
220
221 ObjectFactory* ObjectFactory::parent() { return parent_; }
222
223 77 RootFactory* ObjectFactory::root() {
224 // if (parent_ == NULL)
225 // return this;
226 77 return root_;
227 }
228
229 bool ObjectFactory::hasParent() const { return parent_ != NULL; }
230
231 const XMLElement* ObjectFactory::XMLelement() { return element_; }
232
233 23 void ObjectFactory::impl_setAttribute(const XMLAttribute* /* attr */) {}
234
235 61 void ObjectFactory::addChild(ObjectFactory* child) {
236
3/6
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 61 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 61 times.
✗ Branch 8 not taken.
61 children_[child->tagName()].push_back(child);
237 61 }
238
239 16 ObjectFactory::ObjectFactoryList ObjectFactory::getChildrenOfType(
240 std::string type) {
241 16 return children_[type];
242 }
243
244 2 bool ObjectFactory::getChildOfType(std::string type, ObjectFactory*& o) {
245
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 ObjectFactoryList l = getChildrenOfType(type);
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (l.empty()) {
247 throw std::invalid_argument("Tag " + tagName() + " has no child of type " +
248 type);
249 }
250 2 o = l.front();
251
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (l.size() != 1) {
252 hppDout(warning, "Tag " << tagName() << " has several children of type "
253 << type << ". All but the first will be ignored.");
254 return false;
255 }
256 2 return true;
257 2 }
258
259 8 std::ostream& ObjectFactory::print(std::ostream& os) const {
260
6/12
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
8 os << "ObjectFactory " << tagName() << " with name " << name() << std::endl;
261 8 for (ChildrenMap::const_iterator itTagName = children_.begin();
262
2/2
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 8 times.
20 itTagName != children_.end(); ++itTagName)
263 12 for (ObjectFactoryList::const_iterator itObj = itTagName->second.begin();
264
2/2
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 12 times.
19 itObj != itTagName->second.end(); ++itObj)
265
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 os << **itObj;
266 8 return os;
267 }
268
269 26 void ObjectFactory::setAttribute(const XMLAttribute* attr) {
270
2/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 std::string n = std::string(attr->Name());
271
3/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 10 times.
26 if (n == "name")
272
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
16 name(attr->Value());
273
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 else if (n == "id") {
274 int v;
275 if (attr->QueryIntValue(&v) != tinyxml2::XML_SUCCESS) {
276 hppDout(error, "Attribute ID " << attr->Value() << " is incorrect.");
277 } else {
278 id_ = (int)v;
279 }
280 }
281
3/6
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 26 times.
✗ Branch 8 not taken.
26 attrMap_[n] = attr->Value();
282
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 impl_setAttribute(attr);
283 26 }
284
285 20 bool ObjectFactory::hasAttribute(const std::string& attr) const {
286
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 return attrMap_.find(attr) != attrMap_.end();
287 }
288
289 9 std::string ObjectFactory::getAttribute(const std::string& attr) const {
290
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 AttributeMap::const_iterator it = attrMap_.find(attr);
291
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (it == attrMap_.end()) {
292 hppDout(error, "Asking for attribute " << attr);
293 return std::string();
294 }
295
1/2
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 return it->second;
296 }
297
298 9 RootFactory::RootFactory(const DevicePtr_t dev)
299
1/2
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
27 : ObjectFactory(this), device_(dev), prefix_("") {}
300
301 10 DevicePtr_t RootFactory::device() const { return device_; }
302 } // namespace parser
303 } // namespace manipulation
304 } // namespace hpp
305