1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15 
16 #include <cstdlib>
17 
18 #include "XMLtools.hxx"
19 #include "SLint.hxx"
20 #include "SLintXMLException.hxx"
21 #include "UTF8.hxx"
22 
23 extern "C"
24 {
25 #include "sci_malloc.h"
26 #include "charEncoding.h"
27 #include "localization.h"
28 }
29 
30 #define SLINT_XML_ERROR_BUFFER_SIZE 1024
31 
32 namespace slint
33 {
34 
35 std::ostringstream XMLtools::errorBuffer;
36 
getDouble(xmlNode * node,const char * attrName,double & out)37 bool XMLtools::getDouble(xmlNode * node, const char * attrName, double & out)
38 {
39     xmlAttr * attr = xmlHasProp(node, (const xmlChar *)attrName);
40     if (attr)
41     {
42         out = std::atof((const char *)attr->children->content);
43         return true;
44     }
45     return false;
46 }
47 
getUIntVector(xmlNode * node,const char * attrName,std::vector<unsigned int> & out)48 bool XMLtools::getUIntVector(xmlNode * node, const char * attrName, std::vector<unsigned int> & out)
49 {
50     xmlAttr * attr = xmlHasProp(node, (const xmlChar *)attrName);
51     if (attr)
52     {
53         std::vector<std::string> toks = tokenize((const char *)attr->children->content, ',');
54         for (const auto & tok : toks)
55         {
56             const int i = std::stoi(tok);
57             if (i > 0)
58             {
59                 out.emplace_back((unsigned int)i);
60             }
61         }
62         return !toks.empty();
63     }
64     return false;
65 }
66 
getInt(xmlNode * node,const char * attrName,int & out)67 bool XMLtools::getInt(xmlNode * node, const char * attrName, int & out)
68 {
69     xmlAttr * attr = xmlHasProp(node, (const xmlChar *)attrName);
70     if (attr)
71     {
72         out = std::atoi((const char *)attr->children->content);
73         return true;
74     }
75     return false;
76 }
77 
getString(xmlNode * node,const char * attrName,std::string & out)78 bool XMLtools::getString(xmlNode * node, const char * attrName, std::string & out)
79 {
80     xmlAttr * attr = xmlHasProp(node, (const xmlChar *)attrName);
81     if (attr)
82     {
83         out = std::string((const char *)attr->children->content);
84         return true;
85     }
86     return false;
87 }
88 
getWString(xmlNode * node,const char * attrName,std::wstring & out)89 bool XMLtools::getWString(xmlNode * node, const char * attrName, std::wstring & out)
90 {
91     xmlAttr * attr = xmlHasProp(node, (const xmlChar *)attrName);
92     if (attr)
93     {
94         wchar_t * content = to_wide_string((const char *)attr->children->content);
95         out = std::wstring(content);
96         FREE(content);
97 
98         return true;
99     }
100     return false;
101 }
102 
getBool(xmlNode * node,const char * attrName,bool & out)103 bool XMLtools::getBool(xmlNode * node, const char * attrName, bool & out)
104 {
105     xmlAttr * attr = xmlHasProp(node, (const xmlChar *)attrName);
106     if (attr)
107     {
108         std::string val((const char *)attr->children->content);
109         if (val == "true" || val == "1" || val == "yes")
110         {
111             out = true;
112             return true;
113         }
114         else if (val == "false" || val == "0" || val == "no")
115         {
116             out = false;
117             return true;
118         }
119     }
120     return false;
121 }
122 
readXML(const std::wstring & path)123 xmlDoc * XMLtools::readXML(const std::wstring & path)
124 {
125     const std::string fullpath = scilab::UTF8::toUTF8(SLint::getFullPath(path));
126     xmlParserCtxt * ctxt = xmlNewParserCtxt();
127     if (!ctxt)
128     {
129         throw SLintXMLException(fullpath, gettext("Cannot create a parser context"));
130     }
131 
132     xmlSetGenericErrorFunc(ctxt, errorFunction);
133 
134     int options = XML_PARSE_NSCLEAN | XML_PARSE_NOBLANKS;
135     xmlDoc * doc = xmlCtxtReadFile(ctxt, fullpath.c_str(), "UTF-8", options);
136     if (!doc || !ctxt->valid)
137     {
138         std::string error = errorBuffer.str();
139         errorBuffer.str("");
140         errorBuffer.clear();
141         throw SLintXMLException(fullpath, error);
142     }
143 
144     xmlFreeParserCtxt(ctxt);
145 
146     return doc;
147 }
148 
errorFunction(void * ctx,const char * msg,...)149 void XMLtools::errorFunction(void * ctx, const char * msg, ...)
150 {
151     char str[SLINT_XML_ERROR_BUFFER_SIZE];
152     va_list args;
153 
154     va_start(args, msg);
155     vsnprintf(str, SLINT_XML_ERROR_BUFFER_SIZE, msg, args);
156     va_end(args);
157 
158     errorBuffer << str;
159 }
160 
tokenize(const std::string & str,const char delim)161 std::vector<std::string> XMLtools::tokenize(const std::string & str, const char delim)
162 {
163     std::vector<std::string> tokens;
164     std::string token;
165     std::for_each(str.begin(), str.end(), [&](char c)
166     {
167         if (c != ' ' && c != '\t')
168         {
169             if (c != delim)
170             {
171                 token += c;
172             }
173             else if (!token.empty())
174             {
175                 tokens.emplace_back(token);
176                 token.clear();
177             }
178         }
179     });
180 
181     if (!token.empty())
182     {
183         tokens.emplace_back(token);
184     }
185     return tokens;
186 }
187 
188 } // namespace slint
189