0023948: Wrong intersection between a surface of revolution and a plane.
[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>
22
7fd59977 23//=======================================================================
24//function : Create
25//purpose : construction in the Document's data pool
26//=======================================================================
27
28LDOM_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
54void 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
92LDOM_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/*
105LDOM_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
122LDOM_BasicElement::~LDOM_BasicElement ()
123{
124 myTagName = NULL;
125 RemoveNodes ();
126}
127
128//=======================================================================
129//function : GetLastChild
130//purpose :
131//=======================================================================
132
133const 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
154const 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 }
172static const LDOM_BasicAttribute aNullAttribute;
173 return aNullAttribute;
174}
175
176//=======================================================================
177//function : GetFirstAttribute
178//purpose : private method
179//=======================================================================
180
181const 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
215const 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
269const 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
304void 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
327void 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
354void 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
378void 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
399void 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)
449loop_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}