b311480e |
1 | // Created on: 2001-06-26 |
2 | // Created by: Alexander GRIGORIEV |
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 140202: Replace(const char *) for (LDOMBasicString)=>myTagName |
7fd59977 |
17 | |
18 | #include <LDOM_BasicElement.hxx> |
19 | #include <LDOM_BasicAttribute.hxx> |
20 | #include <LDOM_BasicText.hxx> |
21 | #include <LDOM_MemManager.hxx> |
e8862cf4 |
22 | #include <LDOM_NodeList.hxx> |
7fd59977 |
23 | |
7fd59977 |
24 | //======================================================================= |
25 | //function : Create |
26 | //purpose : construction in the Document's data pool |
27 | //======================================================================= |
28 | |
29 | LDOM_BasicElement& LDOM_BasicElement::Create |
30 | (const char * aName, |
31 | const Standard_Integer aLen, |
32 | const Handle(LDOM_MemManager)& aDoc) |
33 | { |
34 | if (aName == NULL) { |
35 | static LDOM_BasicElement aVoidElement; |
36 | aVoidElement = LDOM_BasicElement(); |
37 | return aVoidElement; |
38 | } |
39 | void * aMem = aDoc -> Allocate (sizeof(LDOM_BasicElement)); |
40 | LDOM_BasicElement * aNewElem = new (aMem) LDOM_BasicElement; |
41 | |
42 | Standard_Integer aHash; |
43 | // aDoc -> HashedAllocate (aString, strlen(aString), aNewElem -> myTagName); |
44 | aNewElem -> myTagName = aDoc -> HashedAllocate (aName, aLen, aHash); |
45 | |
46 | aNewElem -> myNodeType = LDOM_Node::ELEMENT_NODE; |
47 | return * aNewElem; |
48 | } |
49 | |
50 | //======================================================================= |
51 | //function : RemoveNodes |
52 | //purpose : |
53 | //======================================================================= |
54 | |
55 | void LDOM_BasicElement::RemoveNodes () |
56 | { |
57 | const LDOM_BasicNode * aNode = (const LDOM_BasicNode *) myFirstChild; |
58 | while (aNode) { |
59 | const LDOM_BasicNode * aNext = aNode -> GetSibling(); |
60 | switch (aNode -> getNodeType ()) { |
61 | case LDOM_Node::ELEMENT_NODE: |
62 | { |
63 | LDOM_BasicElement& anElement = * (LDOM_BasicElement *) aNode; |
64 | anElement = NULL; |
65 | break; |
66 | } |
67 | case LDOM_Node::ATTRIBUTE_NODE: |
68 | { |
69 | LDOM_BasicAttribute& anAttr = * (LDOM_BasicAttribute *) aNode; |
70 | anAttr = NULL; |
71 | break; |
72 | } |
73 | case LDOM_Node::TEXT_NODE: |
74 | case LDOM_Node::COMMENT_NODE: |
75 | case LDOM_Node::CDATA_SECTION_NODE: |
76 | { |
77 | LDOM_BasicText& aTxt = * (LDOM_BasicText *) aNode; |
78 | aTxt = NULL; |
79 | break; |
80 | } |
81 | default: ; |
82 | } |
83 | aNode = aNext; |
84 | } |
85 | myFirstChild = NULL; |
86 | } |
87 | |
88 | //======================================================================= |
89 | //function : operator = |
90 | //purpose : Nullify |
91 | //======================================================================= |
92 | |
93 | LDOM_BasicElement& LDOM_BasicElement:: operator = (const LDOM_NullPtr * aNull) |
94 | { |
95 | myTagName = NULL; |
96 | RemoveNodes (); |
97 | LDOM_BasicNode::operator= (aNull); |
98 | return * this; |
99 | } |
100 | |
101 | //======================================================================= |
102 | //function : LDOM_BasicElement |
103 | //purpose : Constructor |
104 | //======================================================================= |
105 | /* |
106 | LDOM_BasicElement::LDOM_BasicElement (const LDOM_Element& anElement) |
107 | : LDOM_BasicNode (LDOM_Node::ELEMENT_NODE), |
108 | myAttributeMask (0), |
109 | myFirstChild (NULL) |
110 | { |
111 | // LDOMString aNewTagName (anElement.getTagName(), anElement.myDocument); |
112 | // myTagName = aNewTagName; |
113 | const LDOM_BasicElement& anOther = |
114 | (const LDOM_BasicElement&) anElement.Origin(); |
115 | myTagName = anOther.GetTagName(); |
116 | } |
117 | */ |
118 | //======================================================================= |
119 | //function : ~LDOM_BasicElement |
120 | //purpose : Destructor |
121 | //======================================================================= |
122 | |
123 | LDOM_BasicElement::~LDOM_BasicElement () |
124 | { |
125 | myTagName = NULL; |
126 | RemoveNodes (); |
127 | } |
128 | |
129 | //======================================================================= |
130 | //function : GetLastChild |
131 | //purpose : |
132 | //======================================================================= |
133 | |
134 | const LDOM_BasicNode * LDOM_BasicElement::GetLastChild () const |
135 | { |
136 | const LDOM_BasicNode * aNode = myFirstChild; |
137 | if (aNode) { |
138 | if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) |
139 | aNode = NULL; |
140 | else |
141 | while (aNode -> mySibling) { |
142 | if (aNode -> mySibling -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) |
143 | break; |
144 | aNode = aNode -> mySibling; |
145 | } |
146 | } |
147 | return aNode; |
148 | } |
149 | |
150 | //======================================================================= |
151 | //function : GetAttribute |
152 | //purpose : |
153 | //======================================================================= |
154 | |
155 | const LDOM_BasicAttribute& LDOM_BasicElement::GetAttribute |
156 | (const LDOMBasicString& aName, |
157 | const LDOM_BasicNode * aLastCh) const |
158 | { |
159 | const LDOM_BasicNode * aNode; |
160 | if (aLastCh) |
161 | aNode = aLastCh -> GetSibling (); |
162 | else |
163 | aNode = myFirstChild; |
164 | const char * aNameStr = aName.GetString(); |
165 | while (aNode) { |
166 | if (aNode -> getNodeType () == LDOM_Node::ATTRIBUTE_NODE) { |
167 | const LDOM_BasicAttribute * anAttr = (const LDOM_BasicAttribute *) aNode; |
168 | if (!strcmp (aNameStr, anAttr -> GetName())) |
169 | return * anAttr; |
170 | } |
171 | aNode = aNode -> mySibling; |
172 | } |
173 | static const LDOM_BasicAttribute aNullAttribute; |
174 | return aNullAttribute; |
175 | } |
176 | |
177 | //======================================================================= |
178 | //function : GetFirstAttribute |
179 | //purpose : private method |
180 | //======================================================================= |
181 | |
182 | const LDOM_BasicAttribute * LDOM_BasicElement::GetFirstAttribute |
183 | (const LDOM_BasicNode *& theLastCh, |
184 | const LDOM_BasicNode **& thePrevNode) const |
185 | { |
186 | // Find the First Attribute as well as the Last Child among siblings |
187 | const LDOM_BasicNode * aFirstAttr; |
188 | const LDOM_BasicNode ** aPrevNode; |
189 | if (theLastCh) { |
190 | aFirstAttr = theLastCh -> mySibling; |
191 | aPrevNode = (const LDOM_BasicNode **) &(theLastCh -> mySibling); |
192 | while (aFirstAttr) { |
193 | if (aFirstAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) break; |
194 | aPrevNode = (const LDOM_BasicNode **) & (aFirstAttr -> mySibling); |
195 | aFirstAttr = aFirstAttr -> mySibling; |
196 | } |
197 | } else { |
198 | aFirstAttr = myFirstChild; |
199 | aPrevNode = (const LDOM_BasicNode **) &myFirstChild; |
200 | while (aFirstAttr) { |
201 | if (aFirstAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) break; |
202 | if (aFirstAttr -> isNull() == Standard_False) theLastCh = aFirstAttr; |
203 | aPrevNode = (const LDOM_BasicNode **) & (aFirstAttr -> mySibling); |
204 | aFirstAttr = aFirstAttr -> mySibling; |
205 | } |
206 | } |
207 | thePrevNode = aPrevNode; |
208 | return (LDOM_BasicAttribute *) aFirstAttr; |
209 | } |
210 | |
211 | //======================================================================= |
212 | //function : AddAttribute |
213 | //purpose : Add or replace an attribute |
214 | //======================================================================= |
215 | |
216 | const LDOM_BasicNode * LDOM_BasicElement::AddAttribute |
217 | (const LDOMBasicString& anAttrName, |
218 | const LDOMBasicString& anAttrValue, |
219 | const Handle(LDOM_MemManager)& aDocument, |
220 | const LDOM_BasicNode * aLastCh) |
221 | { |
222 | // Create attribute |
223 | Standard_Integer aHash; |
224 | LDOM_BasicAttribute& anAttr = |
225 | LDOM_BasicAttribute::Create (anAttrName, aDocument, aHash); |
226 | anAttr.myValue = anAttrValue; |
227 | |
228 | // Initialize the loop of attribute name search |
229 | const LDOM_BasicNode ** aPrNode; |
230 | const LDOM_BasicAttribute * aFirstAttr = GetFirstAttribute (aLastCh, aPrNode); |
231 | const char * aNameStr = anAttrName.GetString(); |
232 | |
233 | // Check attribute hash value against the current mask |
234 | const unsigned int anAttrMaskValue = aHash & (8*sizeof(myAttributeMask) - 1); |
235 | const unsigned long anAttributeMask = (1 << anAttrMaskValue); |
0797d9d3 |
236 | #ifdef OCCT_DEBUG_MASK |
7fd59977 |
237 | anAttributeMask = 0xffffffff; |
238 | #endif |
239 | if ((myAttributeMask & anAttributeMask) == 0) { |
240 | // this is new attribute, OK |
241 | myAttributeMask |= anAttributeMask; |
242 | * aPrNode = &anAttr; |
243 | anAttr.SetSibling (aFirstAttr); |
244 | } else { |
245 | // this attribute may have already been installed |
246 | LDOM_BasicAttribute * aCurrentAttr = (LDOM_BasicAttribute *) aFirstAttr; |
247 | while (aCurrentAttr) { |
248 | if (aCurrentAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) |
249 | if (LDOM_MemManager::CompareStrings (aNameStr, aHash, |
250 | aCurrentAttr -> GetName())) { |
251 | aCurrentAttr -> SetValue (anAttrValue, aDocument); |
252 | break; |
253 | } |
254 | aCurrentAttr = (LDOM_BasicAttribute *) aCurrentAttr -> mySibling; |
255 | } |
256 | if (aCurrentAttr == NULL) { |
257 | // this is new attribute, OK |
258 | * aPrNode = &anAttr; |
259 | anAttr.SetSibling (aFirstAttr); |
260 | } |
261 | } |
262 | return aLastCh; |
263 | } |
264 | |
265 | //======================================================================= |
266 | //function : RemoveAttribute |
267 | //purpose : Find and delete an attribute from list |
268 | //======================================================================= |
269 | |
270 | const LDOM_BasicNode * LDOM_BasicElement::RemoveAttribute |
271 | (const LDOMBasicString& aName, |
272 | const LDOM_BasicNode * aLastCh) const |
273 | { |
274 | // Check attribute hash value against the current mask |
275 | const char * const aNameStr = aName.GetString(); |
276 | const Standard_Integer aHash = |
7dc9e047 |
277 | LDOM_MemManager::Hash (aNameStr, (Standard_Integer)strlen(aNameStr)); |
7fd59977 |
278 | const unsigned int anAttrMaskValue = aHash & (8*sizeof(myAttributeMask) - 1); |
279 | const unsigned long anAttributeMask = (1 << anAttrMaskValue); |
0797d9d3 |
280 | #ifdef OCCT_DEBUG_MASK |
7fd59977 |
281 | anAttributeMask = 0xffffffff; |
282 | #endif |
283 | if ((myAttributeMask & anAttributeMask) == 0) { |
284 | ; // maybe cause for exception |
285 | } else { |
286 | const LDOM_BasicNode ** aPrevNode; // dummy |
287 | const LDOM_BasicAttribute * anAttr = GetFirstAttribute (aLastCh, aPrevNode); |
288 | while (anAttr) { |
289 | if (anAttr -> getNodeType () == LDOM_Node::ATTRIBUTE_NODE) |
290 | if (LDOM_MemManager::CompareStrings(aNameStr,aHash,anAttr->GetName())) { |
291 | anAttr = NULL; |
292 | break; |
293 | } |
294 | anAttr = (const LDOM_BasicAttribute *) anAttr -> mySibling; |
295 | } |
296 | } |
297 | return aLastCh; |
298 | } |
299 | |
300 | //======================================================================= |
301 | //function : RemoveChild |
302 | //purpose : |
303 | //======================================================================= |
304 | |
305 | void LDOM_BasicElement::RemoveChild (const LDOM_BasicNode * aChild) const |
306 | { |
307 | const LDOM_BasicNode * aNode = myFirstChild; |
308 | const LDOM_BasicNode ** aPrevNode = (const LDOM_BasicNode **) &myFirstChild; |
309 | while (aNode) { |
310 | if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) |
311 | break; |
312 | if (aNode == aChild) { |
313 | * aPrevNode = aNode -> GetSibling(); |
314 | * (LDOM_BasicNode *) aChild = NULL; |
315 | break; |
316 | } |
317 | aPrevNode = (const LDOM_BasicNode **) & (aNode -> mySibling); |
318 | aNode = aNode -> GetSibling(); |
319 | } |
320 | // here may be the cause to throw an exception |
321 | } |
322 | |
323 | //======================================================================= |
324 | //function : AppendChild |
325 | //purpose : |
326 | //======================================================================= |
327 | |
328 | void LDOM_BasicElement::AppendChild (const LDOM_BasicNode * aChild, |
329 | const LDOM_BasicNode *& aLastChild) const |
330 | { |
331 | if (aLastChild) { |
332 | (const LDOM_BasicNode *&) aChild -> mySibling = aLastChild -> mySibling; |
333 | (const LDOM_BasicNode *&) aLastChild -> mySibling = aChild; |
334 | } else { |
335 | const LDOM_BasicNode * aNode = myFirstChild; |
336 | const LDOM_BasicNode ** aPrevNode = (const LDOM_BasicNode **) &myFirstChild; |
337 | while (aNode) { |
338 | if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) { |
339 | (const LDOM_BasicNode *&) aChild -> mySibling = aNode; |
340 | break; |
341 | } |
342 | aPrevNode = (const LDOM_BasicNode **) & (aNode -> mySibling); |
343 | aNode = aNode -> mySibling; |
344 | } |
345 | * aPrevNode = aChild; |
346 | } |
347 | aLastChild = aChild; |
348 | } |
349 | |
350 | //======================================================================= |
351 | //function : AddElementsByTagName |
352 | //purpose : Add to the List all sub-elements with the given name (recursive) |
353 | //======================================================================= |
354 | |
355 | void LDOM_BasicElement::AddElementsByTagName |
356 | (LDOM_NodeList& aList, const LDOMBasicString& aTagName) const |
357 | { |
358 | const LDOM_BasicNode * aNode = myFirstChild; |
359 | const char * aTagString = aTagName.GetString(); |
360 | while (aNode) { |
361 | if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) |
362 | break; |
363 | if (aNode -> getNodeType() == LDOM_Node::ELEMENT_NODE) { |
364 | LDOM_BasicElement& anElement = * (LDOM_BasicElement *) aNode; |
365 | // if (anElement.GetTagName().equals(aTagName)) |
366 | if (strcmp (anElement.GetTagName(), aTagString) == 0) |
367 | aList.Append (anElement); |
368 | anElement.AddElementsByTagName (aList, aTagName); |
369 | } |
370 | aNode = aNode -> GetSibling(); |
371 | } |
372 | } |
373 | |
374 | //======================================================================= |
375 | //function : AddAttributes |
376 | //purpose : |
377 | //======================================================================= |
378 | |
379 | void LDOM_BasicElement::AddAttributes (LDOM_NodeList& aList, |
380 | const LDOM_BasicNode * aLastChild) const |
381 | { |
382 | const LDOM_BasicNode * aBNode; |
383 | if (aLastChild) |
384 | aBNode = aLastChild -> GetSibling(); |
385 | else |
386 | aBNode = GetFirstChild(); |
387 | while (aBNode) { |
388 | if (aBNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) |
389 | aList.Append (* aBNode); |
390 | aBNode = aBNode -> GetSibling(); |
391 | } |
392 | } |
393 | |
394 | //======================================================================= |
395 | //function : ReplaceElement |
396 | //purpose : Copy data and children into this node from another one |
397 | // The only preserved data is mySibling |
398 | //======================================================================= |
399 | |
400 | void LDOM_BasicElement::ReplaceElement |
401 | (const LDOM_BasicElement& anOtherElem, |
402 | const Handle(LDOM_MemManager)& aDocument) |
403 | { |
404 | myTagName = anOtherElem.GetTagName(); |
405 | myAttributeMask = anOtherElem.myAttributeMask; |
406 | myFirstChild = NULL; |
407 | const LDOM_BasicNode * aBNode = anOtherElem.GetFirstChild (); |
408 | const LDOM_BasicNode * aLastChild = NULL; |
409 | |
410 | // Loop on children (non-attributes) |
411 | for (; aBNode != NULL; aBNode = aBNode -> GetSibling()) { |
412 | if (aBNode -> isNull()) |
413 | continue; |
414 | LDOM_BasicNode * aNewBNode; |
415 | const LDOM_Node::NodeType aNewNodeType = aBNode -> getNodeType(); |
416 | switch (aNewNodeType) { |
417 | case LDOM_Node::ELEMENT_NODE: |
418 | { |
419 | const LDOM_BasicElement& aBNodeElem = *(const LDOM_BasicElement*)aBNode; |
420 | const char * aTagString = aBNodeElem.GetTagName(); |
421 | LDOM_BasicElement& aNewBNodeElem = |
7dc9e047 |
422 | LDOM_BasicElement::Create (aTagString, (Standard_Integer)strlen(aTagString), aDocument); |
7fd59977 |
423 | aNewBNodeElem.ReplaceElement (aBNodeElem, aDocument); //reccur |
424 | aNewBNode = &aNewBNodeElem; |
425 | break; |
426 | } |
427 | case LDOM_Node::ATTRIBUTE_NODE: |
428 | goto loop_attr; |
429 | case LDOM_Node::TEXT_NODE: |
430 | case LDOM_Node::COMMENT_NODE: |
431 | case LDOM_Node::CDATA_SECTION_NODE: |
432 | { |
433 | const LDOM_BasicText& aBNodeText = * (const LDOM_BasicText *) aBNode; |
434 | aNewBNode = &LDOM_BasicText::Create (aNewNodeType, |
435 | LDOMString(aBNodeText.GetData(), |
436 | aDocument), |
437 | aDocument); |
438 | break; |
439 | } |
440 | default: continue; |
441 | } |
442 | if (GetFirstChild()) |
443 | (const LDOM_BasicNode *&) aLastChild -> mySibling = aNewBNode; |
444 | else |
445 | (const LDOM_BasicNode *&) myFirstChild = aNewBNode; |
446 | (const LDOM_BasicNode *&) aLastChild = aNewBNode; |
447 | } |
448 | |
449 | // Loop on attributes (in the end of the list of children) |
450 | loop_attr: |
451 | LDOM_BasicNode * aLastAttr = (LDOM_BasicNode *) aLastChild; |
452 | for (; aBNode != NULL; aBNode = aBNode -> GetSibling()) { |
453 | Standard_Integer aHash; |
454 | if (aBNode -> isNull()) continue; |
455 | const LDOM_BasicAttribute * aBNodeAtt= (const LDOM_BasicAttribute *) aBNode; |
456 | LDOM_BasicAttribute * aNewAtt = |
457 | &LDOM_BasicAttribute::Create (aBNodeAtt -> GetName(), aDocument, aHash); |
458 | aNewAtt -> SetValue (aBNodeAtt->myValue, aDocument); |
459 | if (aLastAttr) |
460 | aLastAttr -> SetSibling (aNewAtt); |
461 | else |
462 | myFirstChild = aNewAtt; |
463 | aLastAttr = aNewAtt; |
464 | } |
465 | } |