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