0024491: Partition algorithm history bug (faces).
[occt.git] / src / XmlObjMgt / XmlObjMgt.cxx
CommitLineData
b311480e 1// Created on: 2001-07-18
2// Created by: Julia DOROVSKIKH
973c2be1 3// Copyright (c) 2001-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
16//AGV 150202: Add parameter isClearText to SetStringValue()
7fd59977 17
18#include <XmlObjMgt.ixx>
19#include <XmlObjMgt_Document.hxx>
20#include <LDOM_Text.hxx>
21
22#include <errno.h>
23#include <stdio.h>
24
25static const char aRefPrefix [] = "/document/label";
26static const char aRefElem1 [] = "/label[@tag=";
27static const char aRefElem2 [] = "]";
28
29//=======================================================================
30//function : IdString
31//purpose : return name of ID attribute to be used everywhere
32//=======================================================================
33
34const XmlObjMgt_DOMString& XmlObjMgt::IdString ()
35{
36 static const LDOMString aString ("id");
37 return aString;
38}
39
40//=======================================================================
41//function : SetStringValue
42//purpose : Add theData as the last child text node to theElement
43//remark : Set isClearText to True if only you guarantee that the string
44// does not contain '&', '<', '>', '\"', '\'', etc.
45//=======================================================================
46
47void XmlObjMgt::SetStringValue (XmlObjMgt_Element& theElement,
48 const XmlObjMgt_DOMString& theData,
49 const Standard_Boolean isClearText)
50{
51 XmlObjMgt_Document aDocument = theElement.getOwnerDocument();
52 LDOM_Text aText = aDocument.createTextNode (theData);
53 if (isClearText) aText.SetValueClear();
54 theElement.appendChild (aText);
55}
56
57//=======================================================================
58//function : GetStringValue
59//purpose : returns the first child text node
60//=======================================================================
61
62XmlObjMgt_DOMString XmlObjMgt::GetStringValue
63 (const XmlObjMgt_Element& theElement)
64{
65 XmlObjMgt_DOMString aString;
66 for (LDOM_Node aNode = theElement.getFirstChild();
67 aNode != NULL;
68 aNode = aNode.getNextSibling())
69 {
70 if (aNode.getNodeType() == LDOM_Node::TEXT_NODE) {
71 aString = ((const LDOM_Text&)aNode).getData();
72 break;
73 }
74 }
75 return aString;
76}
77
78//=======================================================================
79//function : SprintfExtStr
80//purpose : Converts theString to hex printable representation and put it
81// : to the out buffer
82//=======================================================================
83void SprintfExtStr(char * out, const TCollection_ExtendedString& theString) {
84 unsigned short * p = (unsigned short *)theString.ToExtString();
85 int len = theString.Length();
86 int i = 0;
87 unsigned short mask[4] = {0xf000,0x0f00,0x00f0,0x000f};
88 while (len) {
89 for(int j = 0,k=3; j<4; j++,k--) {
90 unsigned short v = *(p+i) & mask[j];//x000
008aef40 91 v = (unsigned short)(v >> (4*k));
7fd59977 92 if(v < 10)
93 v |= 0x30;
94 else
95 v += 87;
96 out[4*i+j] = (char)v;
97 }
98 i++;len--;
99 }
100 out[4*theString.Length()] = 0x00;
101}
102//=======================================================================
103//function : SetExtendedString
104//purpose : Add text node to element and initialize it with string
105//=======================================================================
106
107Standard_Boolean XmlObjMgt::SetExtendedString
108 (XmlObjMgt_Element& theElement,
109 const TCollection_ExtendedString& theString)
110{
111 TCollection_AsciiString anAString;
112 if (theString.IsAscii()) {
113 anAString = TCollection_AsciiString (theString, '?');
114 SetStringValue (theElement, anAString.ToCString());
115 } else {
116 const Standard_Integer aLen = theString.Length();
117// const Standard_ExtCharacter * aString = theString.ToExtString();
118 char * buf0 = new char [4 * (aLen + 1) + 3];
91322f44 119 Sprintf (&buf0[0], "##%04x", 0xfeff); // set UNICODE header
7fd59977 120 char * buf = &buf0[6];
121// Standard_Integer i = 0;
122// while (i <= (aLen - 4)) {
91322f44 123// Sprintf (&buf[i*4], "%04x%04x%04x%04x", aString[i], aString[i+1],
7fd59977 124// aString[i+2], aString[i+3]);
125// i += 4;
126// }
127// while (i < aLen) {
91322f44 128// Sprintf (&buf[i*4], "%04x", aString[i]);
7fd59977 129// ++i;
130// }
131// buf[4*aLen] = '\0';
132
133 SprintfExtStr(buf, theString);
134 SetStringValue (theElement, buf0);
135 delete [] buf0;
136 }
137 return Standard_True;
138}
139
140//=======================================================================
141//function : GetExtendedString
142//purpose : Get the first text node in theElement and convert to ExtendedStr
143//=======================================================================
144
145Standard_Boolean XmlObjMgt::GetExtendedString
146 (const XmlObjMgt_Element& theElement,
147 TCollection_ExtendedString& theString)
148{
149 theString = GetStringValue (theElement);
150 return Standard_True;
151}
152
153//=======================================================================
154//function : GetTagEntryString
155//purpose : Convert XPath expression (DOMString) into TagEntry string
156// Returns False on error
157//=======================================================================
158
159Standard_Boolean XmlObjMgt::GetTagEntryString
160 (const XmlObjMgt_DOMString& theSource,
161 TCollection_AsciiString& theTagEntry)
162{
163 // Check the prefix
164 const size_t aPrefixSize = sizeof(aRefPrefix) - 1;
165 const char * aSource = theSource.GetString();
166 if (strncmp (aSource, aRefPrefix, aPrefixSize))
167 return Standard_False;
168
169 // Beging aTagEntry string
170 char * aTagEntry =
171 (char *) Standard::Allocate (strlen(aSource)/2); // quite enough to hold it
172 char * aTagEntryPtr = aTagEntry + 1;
173 * aTagEntry = '0';
174 aSource += aPrefixSize;
175
176 // Find all individual tags in a loop
177 const size_t anElem1Size = sizeof(aRefElem1) - 1;
178 const size_t anElem2Size = sizeof(aRefElem2) - 1;
179 while (aSource[0] != '\0') {
180 // Check the first part of individual tag: "/label[@tag="
181 if (strncmp (aSource, aRefElem1, anElem1Size))
182 return Standard_False;
183 aSource += anElem1Size;
184 const char aQuote = aSource[0];
185 if (aQuote != '\'' && aQuote != '\"')
186 return Standard_False;
187
188 // Check the integer value of the tag
189 errno = 0;
190 char * aPtr;
191 long aTagValue = strtol (&aSource[1], &aPtr, 10);
192 if (aTagValue <= 0 || aPtr[0] != aQuote ||
193 errno == ERANGE || errno == EINVAL)
194 return Standard_False;
7dc9e047 195 Standard_Integer aLen = (Standard_Integer)(aPtr - &aSource[1]);
7fd59977 196 aTagEntryPtr[0] = ':';
197 memcpy (&aTagEntryPtr[1], &aSource[1], aLen);
198 aTagEntryPtr += (aLen + 1);
199
200 // Check the final part of individual tag : "]"
201 if (strncmp (aPtr + 1, aRefElem2, anElem2Size))
202 return Standard_False;
203 aSource = aPtr + 1 + anElem2Size;
204 }
205 aTagEntryPtr[0] = '\0';
206 theTagEntry = aTagEntry;
207 Standard::Free ((Standard_Address&)aTagEntry);
208 return Standard_True;
209}
210
211//=======================================================================
212//function : SetTagEntryString
213//purpose : Form an XPath string corresponding to the input TagEntry
214//=======================================================================
215
216void XmlObjMgt::SetTagEntryString (XmlObjMgt_DOMString& theTarget,
217 const TCollection_AsciiString& theTagEntry)
218{
219 // Begin parsing theTagEntry
220 const char * aTagEntry = (const char*) theTagEntry.ToCString() + 1;
221 if (aTagEntry[-1] != '0')
222 return;
223
224 // Count the number of tags in the label entry string
225 const char * aPtr = aTagEntry;
226 Standard_Integer aTagCount = 0;
227 while (* aPtr) if (* aPtr++ == ':') aTagCount ++;
228
229 // Create a buffer to accumulate the XPath reference
230 const size_t anElem1Size = sizeof(aRefElem1) - 1;
231 const size_t anElem2Size = sizeof(aRefElem2) - 1;
232 char * aTarget =
233 (char *) Standard::Allocate (sizeof(aRefPrefix) + aTagCount *
234 (anElem1Size + anElem2Size + 12));
235 memcpy (aTarget, aRefPrefix, sizeof (aRefPrefix) - 1);
236 char * aTargetPtr = aTarget + (sizeof (aRefPrefix) - 1);
237
302f96fb 238 for(;;) {
7fd59977 239 // Check for the end-of-string; find the delimeter ':'
240 aPtr = strchr (aTagEntry, ':');
241 if (aPtr == NULL) break;
242 aTagEntry = aPtr + 1;
243
244 // Find the range of characters for an integer number
245 errno = 0;
246 char * ptr;
247 long aTagValue = strtol (aTagEntry, &ptr, 10);
248 if (aTagValue <= 0 || errno == ERANGE || errno == EINVAL)
249 return; // error
7dc9e047 250 Standard_Integer aTagSize = (Standard_Integer)(ptr - aTagEntry);
7fd59977 251
252 // Add one XPath level to the expression in aTarget
253 memcpy (&aTargetPtr[0], aRefElem1, anElem1Size);
254 aTargetPtr[anElem1Size] = '\"';
255 memcpy (&aTargetPtr[anElem1Size+1], aTagEntry, aTagSize);
256 aTargetPtr[anElem1Size+aTagSize+1] = '\"';
257 memcpy (&aTargetPtr[anElem1Size+aTagSize+2],aRefElem2, anElem2Size);
258 aTargetPtr += (anElem1Size + aTagSize + anElem2Size + 2);
259 }
260 * aTargetPtr = '\0';
261 theTarget = aTarget;
262 Standard::Free ((Standard_Address&)aTarget);
263}
264
265//=======================================================================
266//function : FindChildElement
267//purpose :
268//=======================================================================
269XmlObjMgt_Element XmlObjMgt::FindChildElement
270 (const XmlObjMgt_Element& theSource,
271 const Standard_Integer theId)
272{
273 LDOM_Node aNode = theSource.getFirstChild();
274 Standard_Integer anId;
275 while ( !aNode.isNull() )
276 {
277 if ( aNode.getNodeType() == LDOM_Node::ELEMENT_NODE )
278 {
279 LDOM_Element anElem = (LDOM_Element &) aNode;
280 if (anElem.getAttribute (IdString()).GetInteger(anId))
281 if (anId == theId) return anElem;
282 }
283 aNode = aNode.getNextSibling();
284 }
285
286 // find in all the document // to be done
287// LDOM_Document aDoc = theSource.getOwnerDocument();
288
289 return LDOM_Element();
290}
291
292//=======================================================================
293//function : FindChildByRef
294//purpose :
295//=======================================================================
296
297XmlObjMgt_Element XmlObjMgt::FindChildByRef
298 (const XmlObjMgt_Element& theSource,
299 const XmlObjMgt_DOMString& theRefName)
300{
301 Standard_Integer anID;
302 if (theSource.getAttribute (theRefName).GetInteger (anID))
303 return FindChildElement (theSource, anID);
304 return LDOM_Element();
305}
306
307
308//=======================================================================
309//function : FindChildByName
310//purpose :
311//=======================================================================
312XmlObjMgt_Element XmlObjMgt::FindChildByName
313 (const XmlObjMgt_Element& theSource,
314 const XmlObjMgt_DOMString& theName)
315{
316 return theSource.GetChildByTagName(theName);
317}
318
319//=======================================================================
320//function : GetInteger
321//purpose :
322//=======================================================================
323Standard_Boolean XmlObjMgt::GetInteger (Standard_CString& theString,
324 Standard_Integer& theValue)
325{
326 char * ptr;
327 errno = 0;
328 long aValue = strtol (theString, &ptr, 10);
329 if (ptr == theString || errno == ERANGE || errno == EINVAL)
330 return Standard_False;
331 theValue = Standard_Integer (aValue);
332 theString = ptr;
333 return Standard_True;
334}
335
336//=======================================================================
337//function : GetReal
338//purpose :
339//=======================================================================
340Standard_Boolean XmlObjMgt::GetReal (Standard_CString& theString,
341 Standard_Real& theValue)
342{
343 char * ptr;
344 errno = 0;
91322f44 345 double aValue = Strtod (theString, &ptr);
7fd59977 346 if (ptr == theString || errno == ERANGE || errno == EINVAL)
347 return Standard_False;
348 theValue = Standard_Real (aValue);
349 theString = ptr;
350 return Standard_True;
351}
352
353//=======================================================================
354//function : GetReal
355//purpose : Convert LDOMString to Real
356//=======================================================================
357Standard_Boolean XmlObjMgt::GetReal (const XmlObjMgt_DOMString& theString,
358 Standard_Real& theValue)
359{
360 switch (theString.Type()) {
361 case LDOMBasicString::LDOM_NULL:
362 return Standard_False;
363 case LDOMBasicString::LDOM_Integer:
364 {
365 Standard_Integer anIntValue;
366 theString.GetInteger(anIntValue);
367 theValue = Standard_Real(anIntValue);
368 break;
369 }
370 default: // LDOM_Ascii*
371 {
372 char * ptr;
373 const char * aString = theString.GetString();
374 errno = 0;
91322f44 375 double aValue = Strtod (aString, &ptr);
7fd59977 376 if (ptr == aString || errno == ERANGE || errno == EINVAL)
377 return Standard_False;
378 theValue = Standard_Real (aValue);
379 }
380 }
381 return Standard_True;
382}