/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/sgx/core/xml/xmltree.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/core/xml/xmltree.hpp"

sgxXMLTree::sgxXMLTree()
{
	clear();
}

sgxXMLTree::~sgxXMLTree()
{
	delete	m_pRoot;
}

void
sgxXMLTree::clear()
{
	m_pRoot = new sgxXMLNode();
	m_pRoot->setElement("xml");
	m_pRoot->addAttribute("version", "1.0");
	m_pRoot->addAttribute("encoding", "UTF-8");
}

/**
traverse the entire tree, from the root, calling @cb at each node.

  An arbitrary userdata value of @param is passed to this method, allowing
custom pointers and handled to be used, without creating globals.

The tree is traversed depth-first.

The callback method has the signature,

  (sgxXMLTree *tree, sgxXMLNode *node, tMEM_SIZE param)

and can return FALSE to ignore the children of the current node, to
stop the traversal. This also allows the callback to handle the 
node and its sub-tree in its entirety.

To terminate recursion on the whole tree, the cb should set a flag 
(internal to itself) and return FALSE on every subsequent invocation.

*/
tBOOL sgxXMLTree::traverse(cbfn_TreeTraverse cb, tMEM_SIZE param)
{
	return traverseFromNode(getRootNode(), cb, param);
}

tBOOL sgxXMLTree::traverse(cbfn_TreeTraverseConst cb, tMEM_SIZE param) const
{
	return traverseFromNode(getRootNode(), cb, param);
}

/**
traverse the entire tree, starting from the specified @pNode, calling 
@cb at each node.

  An arbitrary userdata value of @param is passed to this method, allowing
custom pointers and handled to be used, without creating globals.

The tree is traversed depth-first.

See @traverse.
*/
tBOOL sgxXMLTree::traverseFromNode(const sgxXMLNode *pNode, cbfn_TreeTraverseConst cb, tMEM_SIZE param) const
{
	sgxVector<sgxXMLNode *>::const_iterator cit = pNode->m_ChildNodes.begin();

	for(;cit!=pNode->m_ChildNodes.end();++cit) {
		if ((*cb)(this, (*cit), param)) {
			traverseFromNode((*cit), cb, param);
		}
	}

	return TRUE;
}

tBOOL sgxXMLTree::traverseFromNode(sgxXMLNode *pNode, cbfn_TreeTraverse cb, tMEM_SIZE param)
{
	sgxVector<sgxXMLNode *>::iterator it = pNode->m_ChildNodes.begin();

	for(;it!=pNode->m_ChildNodes.end();++it) {
		if ((*cb)(this, (*it), param)) {
			traverseFromNode((*it), cb, param);
		}
	}

	return TRUE;
}
