0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / LDOM / LDOM_BasicElement.cxx
CommitLineData
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
29LDOM_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
55void 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
93LDOM_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/*
106LDOM_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
123LDOM_BasicElement::~LDOM_BasicElement ()
124{
125 myTagName = NULL;
126 RemoveNodes ();
127}
128
129//=======================================================================
130//function : GetLastChild
131//purpose :
132//=======================================================================
133
134const 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
155const 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 }
173static const LDOM_BasicAttribute aNullAttribute;
174 return aNullAttribute;
175}
176
177//=======================================================================
178//function : GetFirstAttribute
179//purpose : private method
180//=======================================================================
181
182const 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
216const 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
270const 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
305void 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
328void 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
355void 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
379void 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
400void 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)
450loop_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}