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