Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpXmlParser.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See https://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Tool to automatize the creation of xml parser based on the libXML2.
33 *
34*****************************************************************************/
35
36#include <visp3/core/vpConfig.h>
37#include <visp3/core/vpXmlParser.h>
38
39#ifdef VISP_HAVE_XML2
40
41#include <libxml/parser.h>
42#include <visp3/core/vpDebug.h>
43#include <visp3/core/vpException.h>
44
45#include <iomanip>
46#include <sstream>
47#include <string>
48#include <typeinfo>
49
55vpXmlParser::vpXmlParser() : nodeMap(), main_tag("config") {}
56
73{
74 // xmlCleanupParser();
75}
76
82vpXmlParser::vpXmlParser(const vpXmlParser &_twin) : nodeMap(_twin.nodeMap), main_tag(_twin.main_tag) {}
83
84/* utilities functions to read/write data from an xml document */
85
97char *vpXmlParser::xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
98{
99 if (node->xmlChildrenNode == NULL) {
100 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read char*";
101 std::cerr << errorMsg << std::endl;
102 throw vpException(vpException::fatalError, errorMsg);
103 }
104 return (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
105}
106
117std::string vpXmlParser::xmlReadStringChild(xmlDocPtr doc, xmlNodePtr node)
118{
119 if (node->xmlChildrenNode == NULL) {
120 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read std::string";
121 std::cerr << errorMsg << std::endl;
122 throw vpException(vpException::fatalError, errorMsg);
123 }
124 char *dataCh = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
125 std::string dataStr = dataCh;
126 xmlFree(dataCh);
127 return dataStr;
128}
129
141int vpXmlParser::xmlReadIntChild(xmlDocPtr doc, xmlNodePtr node)
142{
143 if (node->xmlChildrenNode == NULL) {
144 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read int";
145 std::cerr << errorMsg << std::endl;
146 throw vpException(vpException::fatalError, errorMsg);
147 }
148 char *val_char;
149 char *control_convert;
150 int val_int;
151
152 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
153 val_int = (int)strtol((char *)val_char, &control_convert, 10);
154
155 if (val_char == control_convert) {
156 xmlFree((xmlChar *)val_char);
157 throw vpException(vpException::ioError, "cannot parse entry to int");
158 }
159 xmlFree((xmlChar *)val_char);
160
161 return val_int;
162}
163
175unsigned int vpXmlParser::xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
176{
177 if (node->xmlChildrenNode == NULL) {
178 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read unsigned int";
179 std::cerr << errorMsg << std::endl;
180 throw vpException(vpException::fatalError, errorMsg);
181 }
182 char *val_char;
183 char *control_convert;
184 unsigned int val_uint;
185
186 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
187 val_uint = (unsigned int)strtoul((char *)val_char, &control_convert, 10);
188
189 if (val_char == control_convert) {
190 xmlFree((xmlChar *)val_char);
191 throw vpException(vpException::ioError, "cannot parse entry to int");
192 }
193 xmlFree((xmlChar *)val_char);
194
195 return val_uint;
196}
197
209double vpXmlParser::xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
210{
211 if (node->xmlChildrenNode == NULL) {
212 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read double";
213 std::cerr << errorMsg << std::endl;
214 throw vpException(vpException::fatalError, errorMsg);
215 }
216 char *val_char;
217 char *control_convert;
218 double val_double;
219
220 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
221 val_double = strtod((char *)val_char, &control_convert);
222
223 if (val_char == control_convert) {
224 xmlFree((xmlChar *)val_char);
225 throw vpException(vpException::ioError, "cannot parse entry to double");
226 }
227 xmlFree((xmlChar *)val_char);
228 return val_double;
229}
230
242float vpXmlParser::xmlReadFloatChild(xmlDocPtr doc, xmlNodePtr node)
243{
244 if (node->xmlChildrenNode == NULL) {
245 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read float";
246 std::cerr << errorMsg << std::endl;
247 throw vpException(vpException::fatalError, errorMsg);
248 }
249 char *val_char;
250 char *control_convert;
251 float val_float;
252
253 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
254#if defined(VISP_HAVE_FUNC_STRTOF)
255 val_float = strtof((char *)val_char, &control_convert);
256#else
257 val_float = (float)strtod((char *)val_char, &control_convert);
258#endif
259
260 if (val_char == control_convert) {
261 xmlFree((xmlChar *)val_char);
262 throw vpException(vpException::ioError, "cannot parse entry to float");
263 }
264 xmlFree((xmlChar *)val_char);
265 return val_float;
266}
267
279bool vpXmlParser::xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
280{
281 if (node->xmlChildrenNode == NULL) {
282 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read bool";
283 std::cerr << errorMsg << std::endl;
284 throw vpException(vpException::fatalError, errorMsg);
285 }
286 char *val_char;
287 bool val_bool;
288
289 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
290 val_bool = val_char[0] != '0'; // reading only 1st character : bool xml storage is '0' or '1'
291
292 xmlFree((xmlChar *)val_char);
293 return val_bool;
294}
295
303void vpXmlParser::xmlWriteCharChild(xmlNodePtr node, const char *label, const char *value)
304{
305 xmlNodePtr tmp;
306 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)value);
307 xmlAddChild(node, tmp);
308}
309
317void vpXmlParser::xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
318{
319 xmlNodePtr tmp;
320 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)value.c_str());
321 xmlAddChild(node, tmp);
322}
323
331void vpXmlParser::xmlWriteIntChild(xmlNodePtr node, const char *label, int value)
332{
333 char str[100];
334 snprintf(str, 100, "%d", value);
335 xmlNodePtr tmp;
336 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
337 xmlAddChild(node, tmp);
338}
339
347void vpXmlParser::xmlWriteUnsignedIntChild(xmlNodePtr node, const char *label, unsigned int value)
348{
349 char str[100];
350 snprintf(str, 100, "%u", value);
351 xmlNodePtr tmp;
352 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
353 xmlAddChild(node, tmp);
354}
355
363void vpXmlParser::xmlWriteDoubleChild(xmlNodePtr node, const char *label, double value)
364{
365 char str[100];
366 snprintf(str, 100, "%lf", value);
367 xmlNodePtr tmp;
368 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
369 xmlAddChild(node, tmp);
370}
371
379void vpXmlParser::xmlWriteFloatChild(xmlNodePtr node, const char *label, float value)
380{
381 char str[100];
382 snprintf(str, 100, "%f", value);
383 xmlNodePtr tmp;
384 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
385 xmlAddChild(node, tmp);
386}
387
395void vpXmlParser::xmlWriteBoolChild(xmlNodePtr node, const char *label, bool value)
396{
397 char str[2];
398 snprintf(str, 2, "%d", (int)value);
399 xmlNodePtr tmp;
400 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
401 xmlAddChild(node, tmp);
402}
403
404/* --------------------------------------------------------------------------
405 */
406/* MAIN METHODS */
407/* --------------------------------------------------------------------------
408 */
409
418void vpXmlParser::parse(const std::string &filename)
419{
420 xmlDocPtr doc;
421 xmlNodePtr root_node;
422
423 doc = xmlParseFile(filename.c_str());
424 if (doc == NULL) {
425 vpERROR_TRACE("cannot open file");
426 throw vpException(vpException::ioError, "cannot open file");
427 }
428
429 root_node = xmlDocGetRootElement(doc);
430 if (root_node == NULL) {
431 vpERROR_TRACE("cannot get root element");
432 throw vpException(vpException::ioError, "cannot get root element");
433 }
434
435 readMainClass(doc, root_node);
436
437 xmlFreeDoc(doc);
438}
439
450void vpXmlParser::save(const std::string &filename, bool append)
451{
452 xmlDocPtr doc;
453 xmlNodePtr root_node;
454
455 doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOWARNING + XML_PARSE_NOERROR + XML_PARSE_NOBLANKS);
456 if (doc == NULL) {
457 doc = xmlNewDoc((xmlChar *)"1.0");
458 root_node = xmlNewNode(NULL, (xmlChar *)main_tag.c_str());
459 xmlDocSetRootElement(doc, root_node);
460 } else {
461 if (!append) {
462 xmlFreeDoc(doc);
463 if (remove(filename.c_str()) != 0)
464 throw vpException(vpException::ioError, "Cannot remove existing xml file");
465
466 doc = xmlNewDoc((xmlChar *)"1.0");
467 root_node = xmlNewNode(NULL, (xmlChar *)main_tag.c_str());
468 xmlDocSetRootElement(doc, root_node);
469 }
470 }
471
472 root_node = xmlDocGetRootElement(doc);
473 if (root_node == NULL) {
474 vpERROR_TRACE("problem to get the root node");
475 throw vpException(vpException::ioError, "problem to get the root node");
476 }
477
478 writeMainClass(root_node);
479
480 xmlSaveFormatFile(filename.c_str(), doc, 1);
481 xmlFreeDoc(doc);
482}
483
484#elif !defined(VISP_BUILD_SHARED_LIBS)
485// Work around to avoid warning: libvisp_core.a(vpXmlParser.cpp.o) has no
486// symbols
487void dummy_vpXmlParser(){};
488#endif
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ ioError
I/O error.
Definition vpException.h:79
@ fatalError
Fatal error.
Definition vpException.h:84
void xmlWriteIntChild(xmlNodePtr node, const char *label, int value)
void xmlWriteBoolChild(xmlNodePtr node, const char *label, bool value)
void xmlWriteFloatChild(xmlNodePtr node, const char *label, float value)
double xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
void xmlWriteDoubleChild(xmlNodePtr node, const char *label, double value)
float xmlReadFloatChild(xmlDocPtr doc, xmlNodePtr node)
void xmlWriteUnsignedIntChild(xmlNodePtr node, const char *label, unsigned int value)
void xmlWriteCharChild(xmlNodePtr node, const char *label, const char *value)
void xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
int xmlReadIntChild(xmlDocPtr doc, xmlNodePtr node)
void save(const std::string &filename, bool append=false)
bool xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
unsigned int xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
virtual ~vpXmlParser()
void parse(const std::string &filename)
char * xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
virtual void readMainClass(xmlDocPtr doc, xmlNodePtr node)=0
std::string xmlReadStringChild(xmlDocPtr doc, xmlNodePtr node)
virtual void writeMainClass(xmlNodePtr node)=0
std::string main_tag
#define vpERROR_TRACE
Definition vpDebug.h:388