0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / LDOM / LDOM_BasicElement.cxx
1 // Created on: 2001-06-26
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 //AGV 140202: Replace(const char *) for (LDOMBasicString)=>myTagName
17
18 #include <LDOM_BasicElement.hxx>
19 #include <LDOM_BasicAttribute.hxx>
20 #include <LDOM_BasicText.hxx>
21 #include <LDOM_MemManager.hxx>
22 #include <LDOM_NodeList.hxx>
23
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);
236 #ifdef OCCT_DEBUG_MASK
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 =
277     LDOM_MemManager::Hash (aNameStr, (Standard_Integer)strlen(aNameStr));
278   const unsigned int anAttrMaskValue = aHash & (8*sizeof(myAttributeMask) - 1);
279   const unsigned long anAttributeMask = (1 << anAttrMaskValue);
280 #ifdef OCCT_DEBUG_MASK
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 =
422           LDOM_BasicElement::Create (aTagString, (Standard_Integer)strlen(aTagString), aDocument);
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 }