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