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 | |
25 | static const char aRefPrefix [] = "/document/label"; |
26 | static const char aRefElem1 [] = "/label[@tag="; |
27 | static const char aRefElem2 [] = "]"; |
28 | |
29 | //======================================================================= |
30 | //function : IdString |
31 | //purpose : return name of ID attribute to be used everywhere |
32 | //======================================================================= |
33 | |
34 | const 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 | |
47 | void 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 | |
62 | XmlObjMgt_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 | //======================================================================= |
83 | void 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 | |
107 | Standard_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 | |
145 | Standard_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 | |
159 | Standard_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; |
547702a1 |
207 | Standard::Free (aTagEntry); |
7fd59977 |
208 | return Standard_True; |
209 | } |
210 | |
211 | //======================================================================= |
212 | //function : SetTagEntryString |
213 | //purpose : Form an XPath string corresponding to the input TagEntry |
214 | //======================================================================= |
215 | |
216 | void 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; |
547702a1 |
262 | Standard::Free (aTarget); |
7fd59977 |
263 | } |
264 | |
265 | //======================================================================= |
266 | //function : FindChildElement |
267 | //purpose : |
268 | //======================================================================= |
269 | XmlObjMgt_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 | |
297 | XmlObjMgt_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 | //======================================================================= |
312 | XmlObjMgt_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 | //======================================================================= |
323 | Standard_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 | //======================================================================= |
340 | Standard_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 | //======================================================================= |
357 | Standard_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 | } |