GCC Code Coverage Report


Directory: ./
File: src/parser.cc
Date: 2025-05-17 13:07:10
Exec Total Coverage
Lines: 0 153 0.0%
Functions: 0 39 0.0%
Branches: 0 206 0.0%

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/parser.hh"
30
31 #include <stdexcept>
32
33 #include "hpp/util/debug.hh"
34
35 namespace hpp {
36 namespace util {
37 namespace parser {
38 Parser::Parser(FactoryType defaultFactory)
39 : doc_(), root_(NULL), defaultFactory_(defaultFactory) {}
40
41 Parser::~Parser() {
42 for (ObjectFactoryList::iterator it = objectFactories_.begin();
43 it != objectFactories_.end(); ++it)
44 delete *it;
45 if (root_ != NULL) delete root_;
46 }
47
48 void Parser::parse(const char* xmlString) {
49 doc_.Parse(xmlString);
50
51 parse();
52 }
53
54 void Parser::parseFile(const std::string& filename) {
55 doc_.LoadFile(filename.c_str());
56 parse();
57 }
58
59 bool Parser::checkError() const {
60 if (doc_.Error()) {
61 hppDout(error, doc_.ErrorStr());
62 return true;
63 }
64 return false;
65 }
66
67 void Parser::parse() {
68 const XMLElement* el = doc_.RootElement();
69 root_ = new ObjectFactory();
70 while (el != NULL) {
71 parseElement(el, root_);
72 el = el->NextSiblingElement();
73 }
74 for (ObjectFactoryList::iterator it = objectFactories_.begin();
75 it != objectFactories_.end(); ++it)
76 (*it)->finishFile();
77 }
78
79 void Parser::addObjectFactory(const std::string& tagname, FactoryType factory) {
80 ObjectFactoryInsertRet ret =
81 objFactoryMap_.insert(ObjectFactoryPair(tagname, factory));
82 if (!ret.second) throw std::logic_error("This tagname already exist");
83 }
84
85 void Parser::parseElement(const XMLElement* element, ObjectFactory* parent) {
86 if (element == NULL) return;
87
88 ObjectFactory* o = NULL;
89 /// Look for this element in the map
90 ObjectFactoryMap::const_iterator it = objFactoryMap_.find(element->Value());
91 if (it != objFactoryMap_.end())
92 o = it->second(parent, element);
93 else {
94 o = defaultFactory_(parent, element);
95 hppDout(warning, "I have no factory for tag " << o->tagName());
96 }
97 objectFactories_.push_back(o);
98 if (!o->init()) return;
99 for (const XMLAttribute* attr = element->FirstAttribute(); attr;
100 attr = attr->Next())
101 o->setAttribute(attr);
102 if (!o->finishAttributes()) return;
103
104 /// Loop over is child tags
105 for (const XMLNode* el = element->FirstChild(); el; el = el->NextSibling()) {
106 if (el->ToElement() != NULL) {
107 parseElement(el->ToElement(), o);
108 } else if (el->ToUnknown() != NULL) {
109 hppDout(warning, "Unknown Node in XML file: " << el->Value());
110 } else if (el->ToText() != NULL) {
111 o->addTextChild(el->ToText());
112 } else if (el->ToComment() != NULL) {
113 }
114 }
115 o->finishTags();
116 }
117
118 ObjectFactory* Parser::root() const { return root_; }
119
120 std::ostream& Parser::print(std::ostream& os) const {
121 os << "Parser with " << objectFactories_.size() << " object." << std::endl;
122 if (root_ != NULL) os << *root_;
123 return os;
124 }
125
126 std::ostream& operator<<(std::ostream& os, const Parser& p) {
127 return p.print(os);
128 }
129
130 std::ostream& operator<<(std::ostream& os, const ObjectFactory& o) {
131 return o.print(os);
132 }
133
134 ObjectFactory::ObjectFactory(ObjectFactory* parent, const XMLElement* element)
135 : parent_(parent), root_(NULL), element_(element), id_(-1) {
136 if (element_ != NULL)
137 tagName_ = element_->Value();
138 else
139 tagName_ = "unamed_tag";
140 if (parent_ == NULL) {
141 root_ = this;
142 } else {
143 root_ = parent_->root();
144 if (element_ != NULL) parent_->addChild(this);
145 }
146 }
147
148 ObjectFactory::ObjectFactory(ObjectFactory* root)
149 : parent_(NULL), root_(root), element_(NULL), id_(-1) {}
150
151 bool ObjectFactory::init() { return true; }
152
153 bool ObjectFactory::finishAttributes() { return true; }
154
155 void ObjectFactory::finishTags() {}
156
157 void ObjectFactory::finishFile() {}
158
159 void ObjectFactory::addTextChild(const XMLText* /* text */) {}
160
161 ObjectFactory::ObjectFactory(const std::string& tagName, ObjectFactory* parent)
162 : parent_(parent), root_(NULL), element_(NULL), tagName_(tagName), id_(-1) {
163 if (parent_ == NULL)
164 root_ = this;
165 else {
166 root_ = parent_->root();
167 parent_->addChild(this);
168 }
169 }
170
171 void ObjectFactory::addAttribute(const std::string& name,
172 const std::string& value) {
173 attrMap_[name] = value;
174 }
175
176 /// Get a new XMLElement from the content of this factory
177 XMLNode* ObjectFactory::write(XMLNode* parent) const {
178 XMLElement* el = parent->GetDocument()->NewElement(tagName().c_str());
179 for (AttributeMap::const_iterator it = attrMap_.begin(); it != attrMap_.end();
180 ++it)
181 el->SetAttribute(it->first.c_str(), it->second.c_str());
182 for (ChildrenMap::const_iterator it = children_.begin();
183 it != children_.end(); ++it)
184 for (ObjectFactoryList::const_iterator of = it->second.begin();
185 of != it->second.end(); ++of)
186 (*of)->write(el);
187 impl_write(el);
188 return parent->InsertEndChild(el);
189 }
190
191 std::string ObjectFactory::tagName() const { return tagName_; }
192
193 std::string ObjectFactory::name() const { return name_; }
194
195 void ObjectFactory::name(const std::string& n) { name_ = n; }
196
197 void ObjectFactory::name(const char* n) { name(std::string(n)); }
198
199 ObjectFactory* ObjectFactory::parent() { return parent_; }
200
201 ObjectFactory* ObjectFactory::root() { return root_; }
202
203 bool ObjectFactory::hasParent() const { return parent_ != NULL; }
204
205 const XMLElement* ObjectFactory::XMLelement() { return element_; }
206
207 void ObjectFactory::impl_setAttribute(const XMLAttribute* /* attr */) {}
208
209 void ObjectFactory::impl_write(XMLElement*) const {}
210
211 void ObjectFactory::addChild(ObjectFactory* child) {
212 children_[child->tagName()].push_back(child);
213 }
214
215 std::list<ObjectFactory*> ObjectFactory::getChildrenOfType(std::string type) {
216 return children_[type];
217 }
218
219 bool ObjectFactory::getChildOfType(std::string type, ObjectFactory*& o) {
220 ObjectFactoryList l = getChildrenOfType(type);
221 if (l.empty()) {
222 throw std::invalid_argument("Tag " + tagName() + " has no child of type " +
223 type);
224 }
225 o = l.front();
226 if (l.size() != 1) {
227 hppDout(warning, "Tag " << tagName() << " has several children of type "
228 << type << ". All but the first will be ignored.");
229 return false;
230 }
231 return true;
232 }
233
234 std::ostream& ObjectFactory::print(std::ostream& os) const {
235 os << "ObjectFactory " << tagName() << " with name " << name() << std::endl;
236 for (ChildrenMap::const_iterator itTagName = children_.begin();
237 itTagName != children_.end(); ++itTagName)
238 for (ObjectFactoryList::const_iterator itObj = itTagName->second.begin();
239 itObj != itTagName->second.end(); ++itObj)
240 os << **itObj;
241 return os;
242 }
243
244 void ObjectFactory::setAttribute(const XMLAttribute* attr) {
245 std::string n = std::string(attr->Name());
246 if (n == "name")
247 name(attr->Value());
248 else if (n == "id") {
249 int v;
250 if (attr->QueryIntValue(&v) != tinyxml2::XML_SUCCESS) {
251 hppDout(error, "Attribute ID " << attr->Value() << " is incorrect.");
252 } else {
253 id_ = (int)v;
254 }
255 }
256 attrMap_[n] = attr->Value();
257 impl_setAttribute(attr);
258 }
259
260 bool ObjectFactory::hasAttribute(const std::string& attr) const {
261 return attrMap_.find(attr) != attrMap_.end();
262 }
263
264 std::string ObjectFactory::getAttribute(const std::string& attr) const {
265 AttributeMap::const_iterator it = attrMap_.find(attr);
266 if (it == attrMap_.end()) {
267 hppDout(error, "Asking for attribute " << attr);
268 return std::string();
269 }
270 return it->second;
271 }
272 } // namespace parser
273 } // namespace util
274 } // namespace hpp
275