diff -r 417699dc19c9 -r c7e9f1c97567 xml/legacyminidomparser/xmldom/src/gmxmlnode.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/legacyminidomparser/xmldom/src/gmxmlnode.cpp Mon Sep 13 13:16:40 2010 +0530 @@ -0,0 +1,399 @@ +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// MDXMLNode.CPP +// @file +// This file contains the implementation of the CMDXMLNode class which +// is the base class for the Mini-DOM. +// This class forms the basis for the Mini-DOM. It is a +// pure abstract class and it's sole concern is the node +// type and name and the management of the list of child +// nodes. +// The node name and type are set in the constructor and +// cannot be changed thereafter. +// The list of child nodes is managed as a doubly-linked +// list, not an array or similar structure. Derived +// classes which are not allowed children will override the +// operations to manipulate the child list. +// +// + +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "gmxmldummydtd.h" +#endif + +CMDXMLNode::CMDXMLNode( TDOMNodeType aNodeType, TBool aCanHaveChildren, CMDXMLDocument* aOwnerDocument ): + iElementType(KXMLUndefinedElement), + iNodeType(aNodeType), + iCanHaveChildren(aCanHaveChildren) +// +// The node type will normally be hard-wired in any derived class constructor. +// The node name and HaveChildren flag will normally be hard-wired in a derived class constructor unless it +// covers a generic element. +// @param aNodeType The tpe of node to be created +// @param aCanHaveChildren Flag to indicate if the node represents a node which is allowed children +// @param aOwnerDocument Pointer to the document at the root of the DOM tree +// + { + iOwnerDocument = aOwnerDocument; + } + +EXPORT_C CMDXMLNode::~CMDXMLNode() +// +// When this node is deleted it will links its previous and next siblings across the gap, will +// delete all of its children and will correct its parents first and last child pointers if necessary. +// + { + // Perform housekeeping on parent and siblings - shouldn't be necessary as the links to + // this element should have been removed first or we are in a tree delete but + // let's be helpful anyway. + if((iNextSiblingPtr != NULL) && (iNextSiblingPtr->iPrevSiblingPtr == this)) + { + iNextSiblingPtr->iPrevSiblingPtr = iPrevSiblingPtr; + } + if((iPrevSiblingPtr != NULL) && (iPrevSiblingPtr->iNextSiblingPtr == this)) + { + iPrevSiblingPtr->iNextSiblingPtr = iNextSiblingPtr; + } + if( iParentPtr != NULL ) + { + if(iParentPtr->iFirstChildPtr == this) + { + iParentPtr->iFirstChildPtr = iNextSiblingPtr; + } + if(iParentPtr->iLastChildPtr == this) + { + iParentPtr->iLastChildPtr = iPrevSiblingPtr; + } + } + + // Delete all children + CMDXMLNode* childToDelete; + CMDXMLNode* nextChild; + childToDelete = iFirstChildPtr; + while( childToDelete != NULL ) + { + nextChild = childToDelete->iNextSiblingPtr; + delete childToDelete; + childToDelete = nextChild; + } + + delete iNodeName; + iNodeName = NULL; + } + +EXPORT_C void CMDXMLNode::SetNodeNameL( const TDesC& aNodeName) +// +// @param aNodeName The name of the node. +// @leave Can Leave due to OOM +// + { + iNodeName = HBufC::NewMaxL(aNodeName.Length()); + TPtr nodeAccess = iNodeName->Des(); + nodeAccess = aNodeName; + } + +EXPORT_C TPtrC CMDXMLNode::NodeName() +// +// @return Returns the name of the node +// + { + TPtrC retVal = iNodeName->Des(); + return retVal; + } + + +EXPORT_C CMDXMLNode* CMDXMLNode::PreviousSameTypeSibling() +// +// @return Returns a pointer to the previous sibling node of the same type if any, +// oherwise returns NULL +// + { + CMDXMLNode* nodePtr = iPrevSiblingPtr; + while((nodePtr != NULL) && nodePtr->iElementType != iElementType) + { + nodePtr = nodePtr->iPrevSiblingPtr; + } + return nodePtr; + } + +EXPORT_C CMDXMLNode* CMDXMLNode::NextSameTypeSibling() +// +// @return Returns a pointer to the next sibling node of the same type if any, +// oherwise returns NULL +// + { + CMDXMLNode* nodePtr = iNextSiblingPtr; + while((nodePtr != NULL) && nodePtr->iElementType != iElementType) + { + nodePtr = nodePtr->iNextSiblingPtr; + } + return nodePtr; + } + +EXPORT_C TInt CMDXMLNode::RemoveChild(CMDXMLNode* aChildToRemove) +// +// Removes a child from the list of child nodes. The child node is not deleted - that is the responsibility of the caller +// @param aChildToRemove Pointer to child to remove from the list +// @return Returns KERRNone if sucessful or KErrNotFound if the referenced child node is not found +// + { + TInt retVal=KErrNone; + + if(aChildToRemove == NULL) + { + retVal = KErrNotFound; + } + else if( !iCanHaveChildren ) + { + retVal = KErrXMLInvalidChild; + } + else if( aChildToRemove->iParentPtr != this ) + { + retVal = KErrNotFound; + } + else + { + if(iFirstChildPtr == NULL) + { + retVal = KErrNotFound; + } + else + { + if( aChildToRemove == iFirstChildPtr) + { + if( aChildToRemove == iLastChildPtr ) + { // Only child so just zero pointers + iFirstChildPtr = NULL; + iLastChildPtr = NULL; + } + else + { // First but not only child + iFirstChildPtr->iNextSiblingPtr->iPrevSiblingPtr = NULL; + iFirstChildPtr = iFirstChildPtr->iNextSiblingPtr; + } + } + else if( aChildToRemove == iLastChildPtr ) + { // Last but not only child + iLastChildPtr->iPrevSiblingPtr->iNextSiblingPtr = NULL; + iLastChildPtr = iLastChildPtr->iPrevSiblingPtr; + } + else + { // Not first or last so somewhere in the list + CMDXMLNode* nodeBefore = iFirstChildPtr; + while((nodeBefore->iNextSiblingPtr != NULL) && + (nodeBefore->iNextSiblingPtr != aChildToRemove)) + { + nodeBefore = nodeBefore->iNextSiblingPtr; + } + if( nodeBefore->iNextSiblingPtr != aChildToRemove ) + { + retVal = KErrNotFound; + } + else + { + nodeBefore->iNextSiblingPtr = aChildToRemove->iNextSiblingPtr; + aChildToRemove->iNextSiblingPtr->iPrevSiblingPtr = nodeBefore; + } + } + } + }//end if + + if( retVal == KErrNone ) + { // Having cleared this node off the list, clear its own pointers + aChildToRemove->iPrevSiblingPtr = NULL; + aChildToRemove->iNextSiblingPtr = NULL; + aChildToRemove->iParentPtr = NULL; + } + return retVal; + } + +EXPORT_C TInt CMDXMLNode::InsertBefore(CMDXMLNode* aInsertBeforeChild, CMDXMLNode* aChildToInsert) +// +// Inserts a new child node at a specific point in the child list. +// @param aInsertBeforeChild Pointer to the element before which the new child should be inserted (NULL to insert at the start of the list) +// @param aChildToInsert Pointer to the new child node to insert. +// @return Returns KErrNone if successful, KErrXMLInvalidChild if the node cannot have children or KErrNotFound if it cannot fnd the child before which to insert +// + { + TInt retVal = KErrNone; + + if(aChildToInsert == NULL) + { + retVal = KErrNotSupported; + } + else if( !iCanHaveChildren ) + { + retVal = KErrXMLInvalidChild ; + } + else if(iFirstChildPtr == NULL && aInsertBeforeChild != NULL) + { + retVal = KErrNotFound; + } + else if((aInsertBeforeChild == NULL) || (aInsertBeforeChild == iFirstChildPtr)) + { // Insert at start of list + aChildToInsert->iParentPtr = this; + if(iFirstChildPtr != NULL) + { + iFirstChildPtr->iPrevSiblingPtr = aChildToInsert; + aChildToInsert->iNextSiblingPtr = iFirstChildPtr; + } + else + { + iLastChildPtr = aChildToInsert; + aChildToInsert->iNextSiblingPtr = NULL; + } + iFirstChildPtr = aChildToInsert; + } + else + { // Find the insert before child as a check. + CMDXMLNode* nodeBefore = iFirstChildPtr; + while((nodeBefore->iNextSiblingPtr != NULL) && + (nodeBefore->iNextSiblingPtr != aInsertBeforeChild)) + { + nodeBefore = nodeBefore->iNextSiblingPtr; + } + if( nodeBefore->iNextSiblingPtr != aInsertBeforeChild ) + { + retVal = KErrNotFound; + } + else + { + aChildToInsert->iParentPtr = this; + aChildToInsert->iNextSiblingPtr = nodeBefore->iNextSiblingPtr; + aChildToInsert->iPrevSiblingPtr = nodeBefore; + nodeBefore->iNextSiblingPtr = aChildToInsert; + aChildToInsert->iNextSiblingPtr->iPrevSiblingPtr = aChildToInsert; + } + } + return retVal; + } + +EXPORT_C TInt CMDXMLNode::AppendChild(CMDXMLNode* aChildToInsert) +// +// Appends a new child at the end of the child list. +// @param aChildToInsert Pointer to the new child node to append. +// @return Returns KErrNone if successful or KErrXMLInvalidChild if the node cannot have children +// + { + TInt retVal = KErrNone; + + if(aChildToInsert == NULL) + { + retVal = KErrNotSupported; + } + else if( !iCanHaveChildren ) + { + retVal = KErrXMLInvalidChild; + } + else + { + if(iFirstChildPtr == NULL) + { + iFirstChildPtr = aChildToInsert; + } + + if(iLastChildPtr != NULL) + { + iLastChildPtr->iNextSiblingPtr = aChildToInsert; + } + + aChildToInsert->iPrevSiblingPtr = iLastChildPtr; + iLastChildPtr = aChildToInsert; + aChildToInsert->iParentPtr = this; + } + return retVal; + } + +EXPORT_C TInt CMDXMLNode::ReplaceChild(CMDXMLNode* aChildToInsert, CMDXMLNode* aChildToReplace) +// +// Inserts a new child node while removing an existing one. The old child is not deleted. +// @param aChildToInsert Pointer to the new child node to insert. +// @param aChildToReplace Pointer to the child node to be replaced. +// @return Returns KErrNone if successful, KErrXMLInvalidChild if the node cannot have children or KErrNotFound if it cannot fnd the child to replace. +// + { + TInt retVal = KErrNone; + + if(aChildToInsert == NULL) + { + retVal = KErrNotSupported; + } + else if(aChildToReplace == NULL) + { + retVal = KErrNotFound; + } + else if( !iCanHaveChildren ) + { + retVal = KErrXMLInvalidChild ; + } + else + { + if((aChildToReplace == iFirstChildPtr) && (aChildToReplace == iLastChildPtr)) + { // Replace only child + iFirstChildPtr = aChildToInsert; + iLastChildPtr = aChildToInsert; + } + else if(aChildToReplace == iFirstChildPtr) + { // Replace first but not only + aChildToInsert->iNextSiblingPtr = iFirstChildPtr->iNextSiblingPtr; + aChildToInsert->iNextSiblingPtr->iPrevSiblingPtr = aChildToInsert; + iFirstChildPtr = aChildToInsert; + } + else if(aChildToReplace == iLastChildPtr) + { // Replace Last but not only + aChildToInsert->iPrevSiblingPtr = iLastChildPtr->iPrevSiblingPtr; + aChildToInsert->iPrevSiblingPtr->iNextSiblingPtr = aChildToInsert; + iLastChildPtr = aChildToInsert; + } + else if(iFirstChildPtr != NULL) + { // Replace in the middle of the list + CMDXMLNode* nodeBefore = iFirstChildPtr; + while((nodeBefore->iNextSiblingPtr != NULL) && + (nodeBefore->iNextSiblingPtr != aChildToReplace)) + { + nodeBefore = nodeBefore->iNextSiblingPtr; + } + if( nodeBefore->iNextSiblingPtr != aChildToReplace ) + { + retVal = KErrNotFound; + } + else + { // found so just cross link + aChildToInsert->iNextSiblingPtr = aChildToReplace->iNextSiblingPtr; + aChildToInsert->iPrevSiblingPtr = aChildToReplace->iPrevSiblingPtr; + aChildToInsert->iPrevSiblingPtr->iNextSiblingPtr = aChildToInsert; + aChildToInsert->iNextSiblingPtr->iPrevSiblingPtr = aChildToInsert; + } + } + else + { + retVal = KErrNotFound; + } + } + + if( retVal == KErrNone ) + { // Clear out the replaced node + aChildToReplace->iPrevSiblingPtr = NULL; + aChildToReplace->iNextSiblingPtr = NULL; + aChildToReplace->iParentPtr = NULL; + // Point the new child at its parent + aChildToInsert->iParentPtr = this; + } + return retVal; + } + +// End Of File +