Salome HOME
[Code coverage Config]: Exclude GUI oriented code, improve coverage quality for Confi...
[modules/shaper.git] / src / Config / Config_Common.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "Config_Common.h"
22 #include <Config_Keywords.h>
23
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26
27 #include <sstream> // for stringstream
28
29 #include <string>
30 #include <algorithm> // for std::transform
31 #include <vector>
32
33 bool isElementNode(xmlNodePtr theNode)
34 {
35   if (!theNode)
36     return false;
37   return theNode->type == XML_ELEMENT_NODE;
38 }
39
40 bool isNode(xmlNodePtr theNode, const char* theNodeName, ...)
41 {
42   const xmlChar* aName = theNode->name;
43   if (!aName || !isElementNode(theNode)) {
44     return false;
45   }
46   if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) {
47     return true;
48   }
49   va_list args;  // define argument list variable
50   va_start(args, theNodeName);  // init list; point to last defined argument
51   while (true) {
52     char *anArg = va_arg (args, char*);  // get next argument
53     if (anArg == NULL)
54       break;
55     if (!xmlStrcmp(aName, (const xmlChar *) anArg)) {
56       va_end(args);  // cleanup the system stack
57       return true;
58     }
59   }
60   va_end(args);  // cleanup the system stack
61   return false;
62 }
63
64 bool isAttributeNode(xmlNodePtr theNode)
65 {
66   if(!isElementNode(theNode))
67     return false;
68   // it's parent is "feature" or "source" or page ("case" or "box")
69   if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE,
70                          WDG_GROUP, WDG_OPTIONALBOX,
71                          WDG_TOOLBOX_BOX, WDG_RADIOBOX_ITEM,
72                          WDG_SWITCH_CASE, NULL))
73     return false;
74
75   //it should not be a "source" or a "validator" node
76   bool isLogical = isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NULL);
77   // here must be only widgets not connected to attributes
78   bool isPagedContainer = isNode(theNode, WDG_TOOLBOX_BOX,
79                                           WDG_GROUP,
80                                           WDG_SWITCH_CASE,  NULL);
81   return !isLogical && !isPagedContainer;
82 }
83
84 bool isWidgetNode(xmlNodePtr theNode)
85 {
86   if(!isElementNode(theNode))
87     return false;
88   // it's parent is "feature" or "source" or a page ("box", "case")
89   if(!hasParent(theNode, NODE_FEATURE, NODE_SOURCE, WDG_GROUP, WDG_OPTIONALBOX,
90     WDG_TOOLBOX_BOX, WDG_RADIOBOX_ITEM, WDG_SWITCH_CASE, NULL))
91     return false;
92
93   //it should not be a "source" or a "validator" node
94   return !isNode(theNode, NODE_SOURCE, NODE_VALIDATOR, NULL);
95 }
96
97 // LCOV_EXCL_START
98 // widget api?
99 bool isCaseNode(xmlNodePtr theNode)
100 {
101   if(!isElementNode(theNode))
102     return false;
103
104   return isNode(theNode, WDG_OPTIONALBOX, WDG_SWITCH_CASE, WDG_TOOLBOX_BOX,
105     WDG_RADIOBOX_ITEM, NULL);
106 }
107 // LCOV_EXCL_STOP
108
109 bool hasChild(xmlNodePtr theNode)
110 {
111   xmlNodePtr aNode = theNode->children;
112   for (; aNode; aNode = aNode->next) {
113     if (isElementNode(theNode)) {
114       return true;
115     }
116   }
117   return false;
118 }
119
120 bool hasParent(xmlNodePtr theNode)
121 {
122   xmlNodePtr aNode = theNode->parent;
123   if (!aNode) {
124     return false;
125   }
126   for (; aNode; aNode = aNode->next) {
127     if (isElementNode(theNode)) {
128       return true;
129     }
130   }
131   return false;
132 }
133
134 bool hasParent(xmlNodePtr theNode, const char* theNodeName, ...)
135 {
136   if (!hasParent(theNode)) {
137     return false; // have no parents at all
138   }
139   xmlNodePtr aNode = theNode->parent;
140   const xmlChar* aName = aNode->name;
141   if (!aName || !isElementNode(aNode)) {
142     return false;
143   }
144   if (!xmlStrcmp(aName, (const xmlChar *) theNodeName)) {
145     return true;
146   }
147   va_list args;  // define argument list variable
148   va_start(args, theNodeName);  // init list; point to last defined argument
149   while (true) {
150     char *anArg = va_arg (args, char*);  // get next argument
151     if (anArg == NULL)
152       break;
153     if (!xmlStrcmp(aName, (const xmlChar *) anArg)) {
154       va_end(args);  // cleanup the system stack
155       return true;
156     }
157   }
158   va_end(args);  // cleanup the system stack
159   return false;
160 }
161
162 xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const std::vector<const char*>& theNodeNames)
163 {
164   if (!hasParent(theNode)) {
165     return 0; // have no parents at all
166   }
167   xmlNodePtr aNode = theNode->parent;
168   const xmlChar* aName = aNode->name;
169   if (!aName || !isElementNode(aNode)) {
170     return 0;
171   }
172   for (size_t anIndex = 0; anIndex < theNodeNames.size(); ++anIndex) {
173     if (!xmlStrcmp(aName, (const xmlChar *) theNodeNames[anIndex]))
174       return aNode;
175   }
176   return hasParentRecursive(aNode, theNodeNames);
177 }
178
179 xmlNodePtr hasParentRecursive(xmlNodePtr theNode, const char* theNodeName, ...)
180 {
181   std::vector<const char*> aNodeNames;
182   va_list args;  // define argument list variable
183   va_start(args, theNodeName);  // init list; point to last defined argument
184   aNodeNames.push_back(theNodeName);
185   while (true) {
186     char *anArg = va_arg (args, char*);  // get next argument
187     if (anArg == NULL)
188       break;
189     aNodeNames.push_back(anArg);
190   }
191   va_end(args);  // cleanup the system stack
192   return hasParentRecursive(theNode, aNodeNames);
193 }
194
195 bool getParametersInfo(xmlNodePtr theNode, std::string& outPropertyId,
196                       std::list<std::string>& outValidatorParameters)
197 {
198   //Property id:
199   char* anIdProp = (char*) xmlGetProp(theNode, BAD_CAST _ID);
200   if (!anIdProp || anIdProp[0] == 0) {
201     return false;
202   }
203   outPropertyId = std::string(anIdProp);
204
205   //Property parameters:
206   char* aParamProp = (char*) xmlGetProp(theNode, BAD_CAST _PARAMETERS);
207   if (aParamProp && aParamProp[0] != 0) {
208     std::string aPropString = std::string(aParamProp);
209     std::stringstream aPropStringStream(aPropString);
210     char COMMA_DELIM = ',';
211     std::string aParameter;
212     while (std::getline(aPropStringStream, aParameter, ',')) {
213       outValidatorParameters.push_back(aParameter);
214     }
215   }
216   return true;
217 }
218
219 std::string library(const std::string& theLibName)
220 {
221   if(theLibName.empty())
222     return std::string();
223   std::string aLibName = theLibName;
224 #ifndef WIN32
225   static std::string aLibExt( ".so" );
226   if (aLibName.size() < 3 || aLibName.substr(0, 3) !="lib") {
227     aLibName = "lib" + aLibName;
228   }
229 #else
230   static std::string aLibExt(".dll");
231 #endif
232   std::string anExt = aLibName.substr(aLibName.size() - 4);
233   if (anExt != aLibExt)
234     aLibName += aLibExt;
235
236   return aLibName;
237 }
238
239 bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
240
241 std::string getProperty(xmlNodePtr theNode, const char* thePropName)
242 {
243   std::string result = "";
244   xmlChar* aPropChars = xmlGetProp(theNode, BAD_CAST thePropName);
245   if (!aPropChars || aPropChars[0] == 0)
246     return result;
247   result = std::string((char*)aPropChars);
248   xmlFree(aPropChars);
249
250   std::string::iterator new_end = std::unique(result.begin(), result.end(), BothAreSpaces);
251   result.erase(new_end, result.end());
252
253   return result;
254 }
255
256 // LCOV_EXCL_START
257 std::string getContent(xmlNodePtr theNode)
258 {
259   std::string result = "";
260   xmlChar* aContent = xmlNodeGetContent(theNode);
261   if (!aContent || aContent[0] == 0)
262     return result;
263   result = std::string((char*)aContent);
264   xmlFree(aContent);
265   return result;
266 }
267 // LCOV_EXCL_STOP
268
269 std::string getNormalizedProperty(xmlNodePtr theNode, const char* thePropName)
270 {
271   return normalize(getProperty(theNode, thePropName));
272 }
273
274 bool getBooleanAttribute(xmlNodePtr theNode, const char* theAttributeName, bool theDefault)
275 {
276   std::string prop = normalize(getProperty(theNode, theAttributeName));
277   bool result = theDefault;
278   if (prop == "true" || prop == "1") {
279     result = true;
280   } else if (prop == "false" || prop == "0") {
281     result = false;
282   }
283   return result;
284 }
285
286 CONFIG_EXPORT std::string normalize(const std::string& theString)
287 {
288   std::string result = theString;
289   std::transform(result.begin(), result.end(), result.begin(), ::tolower);
290   return result;
291 }