1 // Created on: 2001-06-26
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 //AGV 140202: Replace(const char *) for (LDOMBasicString)=>myTagName
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>
24 //=======================================================================
26 //purpose : construction in the Document's data pool
27 //=======================================================================
29 LDOM_BasicElement& LDOM_BasicElement::Create
31 const Standard_Integer aLen,
32 const Handle(LDOM_MemManager)& aDoc)
35 static LDOM_BasicElement aVoidElement;
36 aVoidElement = LDOM_BasicElement();
39 void * aMem = aDoc -> Allocate (sizeof(LDOM_BasicElement));
40 LDOM_BasicElement * aNewElem = new (aMem) LDOM_BasicElement;
42 Standard_Integer aHash;
43 // aDoc -> HashedAllocate (aString, strlen(aString), aNewElem -> myTagName);
44 aNewElem -> myTagName = aDoc -> HashedAllocate (aName, aLen, aHash);
46 aNewElem -> myNodeType = LDOM_Node::ELEMENT_NODE;
50 //=======================================================================
51 //function : RemoveNodes
53 //=======================================================================
55 void LDOM_BasicElement::RemoveNodes ()
57 const LDOM_BasicNode * aNode = (const LDOM_BasicNode *) myFirstChild;
59 const LDOM_BasicNode * aNext = aNode -> GetSibling();
60 switch (aNode -> getNodeType ()) {
61 case LDOM_Node::ELEMENT_NODE:
63 LDOM_BasicElement& anElement = * (LDOM_BasicElement *) aNode;
67 case LDOM_Node::ATTRIBUTE_NODE:
69 LDOM_BasicAttribute& anAttr = * (LDOM_BasicAttribute *) aNode;
73 case LDOM_Node::TEXT_NODE:
74 case LDOM_Node::COMMENT_NODE:
75 case LDOM_Node::CDATA_SECTION_NODE:
77 LDOM_BasicText& aTxt = * (LDOM_BasicText *) aNode;
88 //=======================================================================
89 //function : operator =
91 //=======================================================================
93 LDOM_BasicElement& LDOM_BasicElement:: operator = (const LDOM_NullPtr * aNull)
97 LDOM_BasicNode::operator= (aNull);
101 //=======================================================================
102 //function : LDOM_BasicElement
103 //purpose : Constructor
104 //=======================================================================
106 LDOM_BasicElement::LDOM_BasicElement (const LDOM_Element& anElement)
107 : LDOM_BasicNode (LDOM_Node::ELEMENT_NODE),
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();
118 //=======================================================================
119 //function : ~LDOM_BasicElement
120 //purpose : Destructor
121 //=======================================================================
123 LDOM_BasicElement::~LDOM_BasicElement ()
129 //=======================================================================
130 //function : GetLastChild
132 //=======================================================================
134 const LDOM_BasicNode * LDOM_BasicElement::GetLastChild () const
136 const LDOM_BasicNode * aNode = myFirstChild;
138 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
141 while (aNode -> mySibling) {
142 if (aNode -> mySibling -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
144 aNode = aNode -> mySibling;
150 //=======================================================================
151 //function : GetAttribute
153 //=======================================================================
155 const LDOM_BasicAttribute& LDOM_BasicElement::GetAttribute
156 (const LDOMBasicString& aName,
157 const LDOM_BasicNode * aLastCh) const
159 const LDOM_BasicNode * aNode;
161 aNode = aLastCh -> GetSibling ();
163 aNode = myFirstChild;
164 const char * aNameStr = aName.GetString();
166 if (aNode -> getNodeType () == LDOM_Node::ATTRIBUTE_NODE) {
167 const LDOM_BasicAttribute * anAttr = (const LDOM_BasicAttribute *) aNode;
168 if (!strcmp (aNameStr, anAttr -> GetName()))
171 aNode = aNode -> mySibling;
173 static const LDOM_BasicAttribute aNullAttribute;
174 return aNullAttribute;
177 //=======================================================================
178 //function : GetFirstAttribute
179 //purpose : private method
180 //=======================================================================
182 const LDOM_BasicAttribute * LDOM_BasicElement::GetFirstAttribute
183 (const LDOM_BasicNode *& theLastCh,
184 const LDOM_BasicNode **& thePrevNode) const
186 // Find the First Attribute as well as the Last Child among siblings
187 const LDOM_BasicNode * aFirstAttr;
188 const LDOM_BasicNode ** aPrevNode;
190 aFirstAttr = theLastCh -> mySibling;
191 aPrevNode = (const LDOM_BasicNode **) &(theLastCh -> mySibling);
193 if (aFirstAttr -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) break;
194 aPrevNode = (const LDOM_BasicNode **) & (aFirstAttr -> mySibling);
195 aFirstAttr = aFirstAttr -> mySibling;
198 aFirstAttr = myFirstChild;
199 aPrevNode = (const LDOM_BasicNode **) &myFirstChild;
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;
207 thePrevNode = aPrevNode;
208 return (LDOM_BasicAttribute *) aFirstAttr;
211 //=======================================================================
212 //function : AddAttribute
213 //purpose : Add or replace an attribute
214 //=======================================================================
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)
223 Standard_Integer aHash;
224 LDOM_BasicAttribute& anAttr =
225 LDOM_BasicAttribute::Create (anAttrName, aDocument, aHash);
226 anAttr.myValue = anAttrValue;
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();
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;
239 if ((myAttributeMask & anAttributeMask) == 0) {
240 // this is new attribute, OK
241 myAttributeMask |= anAttributeMask;
243 anAttr.SetSibling (aFirstAttr);
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);
254 aCurrentAttr = (LDOM_BasicAttribute *) aCurrentAttr -> mySibling;
256 if (aCurrentAttr == NULL) {
257 // this is new attribute, OK
259 anAttr.SetSibling (aFirstAttr);
265 //=======================================================================
266 //function : RemoveAttribute
267 //purpose : Find and delete an attribute from list
268 //=======================================================================
270 const LDOM_BasicNode * LDOM_BasicElement::RemoveAttribute
271 (const LDOMBasicString& aName,
272 const LDOM_BasicNode * aLastCh) const
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;
283 if ((myAttributeMask & anAttributeMask) == 0) {
284 ; // maybe cause for exception
286 const LDOM_BasicNode ** aPrevNode; // dummy
287 const LDOM_BasicAttribute * anAttr = GetFirstAttribute (aLastCh, aPrevNode);
289 if (anAttr -> getNodeType () == LDOM_Node::ATTRIBUTE_NODE)
290 if (LDOM_MemManager::CompareStrings(aNameStr,aHash,anAttr->GetName())) {
294 anAttr = (const LDOM_BasicAttribute *) anAttr -> mySibling;
300 //=======================================================================
301 //function : RemoveChild
303 //=======================================================================
305 void LDOM_BasicElement::RemoveChild (const LDOM_BasicNode * aChild) const
307 const LDOM_BasicNode * aNode = myFirstChild;
308 const LDOM_BasicNode ** aPrevNode = (const LDOM_BasicNode **) &myFirstChild;
310 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
312 if (aNode == aChild) {
313 * aPrevNode = aNode -> GetSibling();
314 * (LDOM_BasicNode *) aChild = NULL;
317 aPrevNode = (const LDOM_BasicNode **) & (aNode -> mySibling);
318 aNode = aNode -> GetSibling();
320 // here may be the cause to throw an exception
323 //=======================================================================
324 //function : AppendChild
326 //=======================================================================
328 void LDOM_BasicElement::AppendChild (const LDOM_BasicNode * aChild,
329 const LDOM_BasicNode *& aLastChild) const
332 (const LDOM_BasicNode *&) aChild -> mySibling = aLastChild -> mySibling;
333 (const LDOM_BasicNode *&) aLastChild -> mySibling = aChild;
335 const LDOM_BasicNode * aNode = myFirstChild;
336 const LDOM_BasicNode ** aPrevNode = (const LDOM_BasicNode **) &myFirstChild;
338 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE) {
339 (const LDOM_BasicNode *&) aChild -> mySibling = aNode;
342 aPrevNode = (const LDOM_BasicNode **) & (aNode -> mySibling);
343 aNode = aNode -> mySibling;
345 * aPrevNode = aChild;
350 //=======================================================================
351 //function : AddElementsByTagName
352 //purpose : Add to the List all sub-elements with the given name (recursive)
353 //=======================================================================
355 void LDOM_BasicElement::AddElementsByTagName
356 (LDOM_NodeList& aList, const LDOMBasicString& aTagName) const
358 const LDOM_BasicNode * aNode = myFirstChild;
359 const char * aTagString = aTagName.GetString();
361 if (aNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
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);
370 aNode = aNode -> GetSibling();
374 //=======================================================================
375 //function : AddAttributes
377 //=======================================================================
379 void LDOM_BasicElement::AddAttributes (LDOM_NodeList& aList,
380 const LDOM_BasicNode * aLastChild) const
382 const LDOM_BasicNode * aBNode;
384 aBNode = aLastChild -> GetSibling();
386 aBNode = GetFirstChild();
388 if (aBNode -> getNodeType() == LDOM_Node::ATTRIBUTE_NODE)
389 aList.Append (* aBNode);
390 aBNode = aBNode -> GetSibling();
394 //=======================================================================
395 //function : ReplaceElement
396 //purpose : Copy data and children into this node from another one
397 // The only preserved data is mySibling
398 //=======================================================================
400 void LDOM_BasicElement::ReplaceElement
401 (const LDOM_BasicElement& anOtherElem,
402 const Handle(LDOM_MemManager)& aDocument)
404 myTagName = anOtherElem.GetTagName();
405 myAttributeMask = anOtherElem.myAttributeMask;
407 const LDOM_BasicNode * aBNode = anOtherElem.GetFirstChild ();
408 const LDOM_BasicNode * aLastChild = NULL;
410 // Loop on children (non-attributes)
411 for (; aBNode != NULL; aBNode = aBNode -> GetSibling()) {
412 if (aBNode -> isNull())
414 LDOM_BasicNode * aNewBNode;
415 const LDOM_Node::NodeType aNewNodeType = aBNode -> getNodeType();
416 switch (aNewNodeType) {
417 case LDOM_Node::ELEMENT_NODE:
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;
427 case LDOM_Node::ATTRIBUTE_NODE:
429 case LDOM_Node::TEXT_NODE:
430 case LDOM_Node::COMMENT_NODE:
431 case LDOM_Node::CDATA_SECTION_NODE:
433 const LDOM_BasicText& aBNodeText = * (const LDOM_BasicText *) aBNode;
434 aNewBNode = &LDOM_BasicText::Create (aNewNodeType,
435 LDOMString(aBNodeText.GetData(),
443 (const LDOM_BasicNode *&) aLastChild -> mySibling = aNewBNode;
445 (const LDOM_BasicNode *&) myFirstChild = aNewBNode;
446 (const LDOM_BasicNode *&) aLastChild = aNewBNode;
449 // Loop on attributes (in the end of the list of children)
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);
460 aLastAttr -> SetSibling (aNewAtt);
462 myFirstChild = aNewAtt;