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