/* =========================================================================
* This file is part of NITRO
* =========================================================================
*
* (C) Copyright 2004 - 2010, General Dynamics - Advanced Information Systems
*
* NITRO is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program;
* If not, see .
*
*/
#ifndef __NRT_TREE_H__
#define __NRT_TREE_H__
#include "nrt/System.h"
#include "nrt/List.h"
NRT_CXX_GUARD
/*!
* \struct nrt_TreeNode
* \brief A Tree Node in a nrt_Tree
*
* This object provides the base node for a tree
* data structure (not to be confused with a TRE,
* or Tagged Record Extension). Trees may be useful
* for certain kinds of parsing, and it may also at
* some point become the default storage for TREs
* themselves. Since a tree isnt really a flat data
* structure, traversal functions may be more appropriate
* than our typical
*
*/
typedef struct _NRT_TreeNode
{
struct _NRT_TreeNode *parent;
/* ! The child nodes List */
nrt_List *children;
/* ! The data */
NRT_DATA *data;
} nrt_TreeNode;
typedef struct _NRT_Tree
{
/* ! The root node */
nrt_TreeNode *root;
} nrt_Tree;
/*!
* Construct a new (detached) TreeNode. This function will assign
* its user data to the tree node, and will only return error if
* memory cannot be allocated for the TreeNode (or its child list).
* The user is assumed to be responsible for the data associated with
* the node
*
* \param data The data to encapsulate
* \param parent Parent (can be NULL if this is the root)
* \param error The error to return
*
*/
NRTAPI(nrt_TreeNode *) nrt_TreeNode_construct(NRT_DATA * data,
nrt_Error * error);
/*!
* Destroy the current node and NULL set it. We are not responsible
* for deleting the data in the node, it is up to the user to delete.
*
* \param node The node
*/
NRTAPI(void) nrt_TreeNode_destruct(nrt_TreeNode ** node);
/*!
* Add a node to our children. The child will be appended to the NITF
* list.
*
* \param node Our node
* \param child The node to add
* \param error The error
* \return NRT_SUCCESS on success, NRT_FAILURE on failure
*
*/
NRTAPI(NRT_BOOL) nrt_TreeNode_addChild(nrt_TreeNode * node,
nrt_TreeNode * child, nrt_Error * error);
/*!
* Return if this tree node has children. This is slightly easier than
* going directly to the underlying list.
*
* \param node The node
* \return 1 if we have children, 0, if not.
*/
NRTAPI(NRT_BOOL) nrt_TreeNode_hasChildren(nrt_TreeNode * node);
/*!
* Remove this child from the list. We will remove our list element
* associated with this node from our Tree, if it exists.
*
* Note, if there are multiple of the same node in this tree,
* we arent currently accounting for that, so if you knew that
* you had it, you would have to call this function repeatedly,
* e.g., while (nrt_TreeNode_remove(tree, node));
*/
NRTAPI(NRT_BOOL) nrt_TreeNode_removeChild(nrt_TreeNode * node,
nrt_TreeNode * child);
/*!
* Clone our TreeNode into a new one. We will need a clone function
* to tell us how to clone our NRT_DATA
*/
NRTAPI(nrt_TreeNode *) nrt_TreeNode_clone(nrt_TreeNode * source,
NRT_DATA_ITEM_CLONE cloner,
nrt_Error * error);
/*!
* Get ourselves a top-level data structure that can be used to control
* an integral tree. It is okay to leave our root element as NULL.
* We will simply not initialize the root
*
* \param An error.
*
*/
NRTAPI(nrt_Tree *) nrt_Tree_construct(nrt_TreeNode * root, nrt_Error * error);
/*!
* Destroy our tree
* \param tree The tree to destruct
*/
NRTAPI(void) nrt_Tree_destruct(nrt_Tree ** tree);
typedef enum _NRT_Traversal
{
NRT_PRE_ORDER = 0,
NRT_POST_ORDER
/* We are not a binary tree, so no inorder traversal */
} nrt_Traversal;
/*!
* This is a traversal function. When you call nrt_Tree_walk()
* you will give it the user data that is necessary to run this
*
* The node will be handed to this function by the traversal
* The function returns true or false if it succeeded or failed.
* If it failed, you should set the nrt_Error*. On failure,
* we will short-circuit the walk method.
*
*/
typedef NRT_BOOL(*NRT_TREE_TRAVERSER) (nrt_TreeNode *, NRT_DATA * userData,
int depth, nrt_Error *);
/*!
* Walk our tree using one of the traversal methods specified.
* Our function will stop if any traversal fails. That means
* that the NRT_TREE_TRAVERSER is returning 1 as NRT_SUCCESS
* and 0 as NRT_FAILURE. On NRT_FAILURE, we expect your onNode()
* to have returned us an error that we will hand back to the application
*
*/
NRTAPI(NRT_BOOL) nrt_Tree_walk(nrt_Tree * tree, NRT_TREE_TRAVERSER onNode,
int traversalOrder, NRT_DATA * userData,
nrt_Error * error);
/*!
* Only providing this because we have to. It looks identical to the
* List clone function.
*
* \param source The tree to clone
* \param cloner the clone function for the NRT_DATA in the element
* \param error An error to populate on failure
*
* \return A Tree that is the clone of source
*/
NRTAPI(nrt_Tree *) nrt_Tree_clone(nrt_Tree * source, NRT_DATA_ITEM_CLONE cloner,
nrt_Error * error);
/*
* There are lots of other tree-type functions that I will ignore
* for now, but that would be useful, including sub-cloning, etc.
*/
NRT_CXX_ENDGUARD
#endif