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