aboutsummaryrefslogtreecommitdiff
path: root/src/xmlnode.h
blob: c895cd8b3adee95a713b3bc7dfc58c537b197948 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#ifndef XMLNODE
#define XMLNODE

#include <iostream>
#include "bu/list.h"
#include "bu/hash.h"
#include "bu/fstring.h"

/**
 * Maintains all data pertient to an XML node, including sub-nodes and content.
 * All child nodes can be accessed through index and through name via a hash
 * table.  This makes it very easy to gain simple and fast access to all of
 * your data.  For most applications, the memory footprint is also rather
 * small.  While XmlNode objects can be used directly to create XML structures
 * it is highly reccomended that all operations be performed through the
 * XmlDocument class.
 *@author Mike Buland
 */
class XmlNode
{
public:
	/**
	 * Construct a new XmlNode.
	 *@param sName The name of the node.
	 *@param pParent The parent node.
	 *@param sContent The initial content string.
	 */
	XmlNode(
		const Bu::FString &sName,
		XmlNode *pParent=NULL
		);
	
	/**
	 * Delete the node and cleanup all memory.
	 */
	virtual ~XmlNode();

	/**
	 * Change the name of the node.
	 *@param sName The new name of the node.
	 */
	//void setName( const char *sName );

	/**
	 * Construct a new node and add it as a child to this node, also return a
	 * pointer to the newly constructed node.
	 *@param sName The name of the new node.
	 *@param sContent The initial content of the new node.
	 *@returns A pointer to the newly created child node.
	 */
	XmlNode *addChild( const Bu::FString &sName );

	/**
	 * Add an already created XmlNode as a child to this node.  The new child
	 * XmlNode's parent will be changed appropriately and the parent XmlNode
	 * will take ownership of the child.
	 *@param pChild The child XmlNode to add to this XmlNode.
	 *@returns A pointer to the child node that was just added.
	 */
	XmlNode *addChild( XmlNode *pChild );

	/**
	 * Add a new property to the XmlNode.  Properties are name/value pairs.
	 *@param sName The name of the property.  Specifying a name that's already
	 * in use will overwrite that property.
	 *@param sValue The textual value of the property.
	 */
	void addProperty( const Bu::FString &sName, const Bu::FString &sValue );

	/**
	 * Get a pointer to the parent node, if any.
	 *@returns A pointer to the node's parent, or NULL if there isn't one.
	 */
	XmlNode *getParent();

	/**
	 * Tells you if this node has children.
	 *@returns True if this node has at least one child, false otherwise.
	 */
	bool hasChildren();

	/**
	 * Tells you how many children this node has.
	 *@returns The number of children this node has.
	 */
	int getNumChildren();

	/**
	 * Get a child with the specified name, and possibly skip value.  For an
	 * explination of skip values see the HashTable.
	 *@param sName The name of the child to find.
	 *@param nSkip The number of nodes with that name to skip.
	 *@returns A pointer to the child, or NULL if no child with that name was
	 * found.
	 */
	XmlNode *getChild( const Bu::FString &sName, int nSkip=0 );

	/**
	 * Get a pointer to the name of this node.  Do not change this, use setName
	 * instead.
	 *@returns A pointer to the name of this node.
	 */
	Bu::FString getName();

	/**
	 * Set the content of this node, optionally at a specific index.  Using the
	 * default of -1 will set the content after the last added node.
	 *@param sContent The content string to use.
	 *@param nIndex The index of the content.
	 */
	//void setContent( const char *sContent, int nIndex=-1 );

	/**
	 * Get the number of properties in this node.
	 *@returns The number of properties in this node.
	 */
	int getNumProperties();

	/**
	 * Get a propery's value by name.
	 *@param sName The name of the property to examine.
	 *@returns A pointer to the value of the property specified, or NULL if none
	 * found.
	 */
	Bu::FString getProperty( const Bu::FString &sName );

	/**
	 * Delete a child node, possibly replacing it with some text.  This actually
	 * fixes all content strings around the newly deleted child node.
	 *@param nIndex The index of the node to delete.
	 *@param sReplacementText The optional text to replace the node with.
	 *@returns True of the node was found, and deleted, false if it wasn't
	 * found.
	 */
	//void deleteNode( int nIndex, const char *sReplacementText = NULL );

	/**
	 * Delete a given node, but move all of it's children and content up to
	 * replace the deleted node.  All of the content of the child node is
	 * spliced seamlessly into place with the parent node's content.
	 *@param nIndex The node to delete.
	 *@returns True if the node was found and deleted, false if it wasn't.
	 */
	//void deleteNodeKeepChildren( int nIndex );

	/**
	 * Detatch a given child node from this node.  This effectively works just
	 * like a deleteNode, except that instead of deleting the node it is removed
	 * and returned, and all ownership is given up.
	 *@param nIndex The index of the node to detatch.
	 *@param sReplacementText The optional text to replace the detatched node
	 * with.
	 *@returns A pointer to the newly detatched node, which then passes
	 * ownership to the caller.
	 */
	//XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL );

	/**
	 * Replace a given node with a different node that is not currently owned by
	 * this XmlNode or any ancestor.
	 *@param nIndex The index of the node to replace.
	 *@param pNewNode The new node to replace the old node with.
	 *@returns True if the node was found and replaced, false if it wasn't.
	 */
	//void replaceNode( int nIndex, XmlNode *pNewNode );

	/**
	 * Replace a given node with the children and content of a given node.
	 *@param nIndex The index of the node to replace.
	 *@param pNewNode The node that contains the children and content that will
	 * replace the node specified by nIndex.
	 *@returns True if the node was found and replaced, false if it wasn't.
	 */
	//void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode );

	/**
	 * Get a copy of this node and all children.  getCopy is recursive, so
	 * beware copying large trees of xml.
	 *@returns A newly created copy of this node and all of it's children.
	 */
	//XmlNode *getCopy();
	
	enum ChildType
	{
		typeNode,
		typeContent
	};

private:
	typedef struct
	{
		uint8_t nType;
		union {
			XmlNode *pNode;
			Bu::FString *pContent;
		};
	} Child;
	Bu::FString sName;	/**< The name of the node. */
	Bu::List<Child> lChildren;	/**< The children. */
	Bu::Hash<Bu::FString, Bu::FString> hProperties;	/**< Property hashtable. */
	Bu::Hash<Bu::FString, Bu::List<XmlNode *> > hChildren;	/**< Children hashtable. */
	XmlNode *pParent;	/**< A pointer to the parent of this node. */
	int nCurContent;	/**< The current content we're on, for using the -1 on
						 	 setContent. */
};

#endif