summaryrefslogtreecommitdiff
path: root/src/old
diff options
context:
space:
mode:
Diffstat (limited to 'src/old')
-rw-r--r--src/old/xmldocument.cpp145
-rw-r--r--src/old/xmldocument.h165
-rw-r--r--src/old/xmlnode.cpp403
-rw-r--r--src/old/xmlnode.h207
-rw-r--r--src/old/xmlreader.cpp604
-rw-r--r--src/old/xmlreader.h144
-rw-r--r--src/old/xmlwriter.cpp167
-rw-r--r--src/old/xmlwriter.h96
8 files changed, 1931 insertions, 0 deletions
diff --git a/src/old/xmldocument.cpp b/src/old/xmldocument.cpp
new file mode 100644
index 0000000..95b9788
--- /dev/null
+++ b/src/old/xmldocument.cpp
@@ -0,0 +1,145 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include "xmldocument.h"
4
5XmlDocument::XmlDocument( XmlNode *pRoot )
6{
7 this->pRoot = pRoot;
8 pCurrent = NULL;
9 bCompleted = (pRoot!=NULL);
10}
11
12XmlDocument::~XmlDocument()
13{
14 if( pRoot )
15 {
16 delete pRoot;
17 }
18}
19
20void XmlDocument::addNode( const Bu::FString &sName )
21{
22 if( pRoot == NULL )
23 {
24 // This is the first node, so ignore position and just insert it.
25 pCurrent = pRoot = new XmlNode( sName );
26 }
27 else
28 {
29 pCurrent = pCurrent->addChild( sName );
30 }
31}
32/*
33void XmlDocument::setName( const char *sName )
34{
35 pCurrent->setName( sName );
36}*/
37
38bool XmlDocument::isCompleted()
39{
40 return bCompleted;
41}
42
43XmlNode *XmlDocument::getRoot()
44{
45 return pRoot;
46}
47
48XmlNode *XmlDocument::detatchRoot()
49{
50 XmlNode *pTemp = pRoot;
51 pRoot = NULL;
52 return pTemp;
53}
54
55XmlNode *XmlDocument::getCurrent()
56{
57 return pCurrent;
58}
59
60void XmlDocument::closeNode()
61{
62 if( pCurrent != NULL )
63 {
64 pCurrent = pCurrent->getParent();
65
66 if( pCurrent == NULL )
67 {
68 bCompleted = true;
69 }
70 }
71}
72
73void XmlDocument::addProperty( const char *sName, const char *sValue )
74{
75 if( pCurrent )
76 {
77 pCurrent->addProperty( sName, sValue );
78 }
79}
80
81void XmlDocument::addProperty( const char *sName, const unsigned char nValue )
82{
83 char buf[12];
84 sprintf( buf, "%hhi", nValue );
85 addProperty( sName, buf );
86}
87
88void XmlDocument::addProperty( const char *sName, const char nValue )
89{
90 char buf[12];
91 sprintf( buf, "%hhi", nValue );
92 addProperty( sName, buf );
93}
94
95void XmlDocument::addProperty( const char *sName, const unsigned short nValue )
96{
97 char buf[12];
98 sprintf( buf, "%hi", nValue );
99 addProperty( sName, buf );
100}
101
102void XmlDocument::addProperty( const char *sName, const short nValue )
103{
104 char buf[12];
105 sprintf( buf, "%hi", nValue );
106 addProperty( sName, buf );
107}
108
109void XmlDocument::addProperty( const char *sName, const int nValue )
110{
111 char buf[12];
112 sprintf( buf, "%d", nValue );
113 addProperty( sName, buf );
114}
115
116void XmlDocument::addProperty( const char *sName, const unsigned long nValue )
117{
118 char buf[12];
119 sprintf( buf, "%li", nValue );
120 addProperty( sName, buf );
121}
122
123void XmlDocument::addProperty( const char *sName, const long nValue )
124{
125 char buf[12];
126 sprintf( buf, "%li", nValue );
127 addProperty( sName, buf );
128}
129
130void XmlDocument::addProperty( const char *sName, const double dValue )
131{
132 char buf[40];
133 sprintf( buf, "%f", dValue );
134 addProperty( sName, buf );
135}
136
137void XmlDocument::setContent( const char *sContent )
138{
139 if( pCurrent )
140 {
141 printf("XmlDocument::setContent: not yet implemented.\n");
142 //pCurrent->setContent( sContent );
143 }
144}
145
diff --git a/src/old/xmldocument.h b/src/old/xmldocument.h
new file mode 100644
index 0000000..e0c36eb
--- /dev/null
+++ b/src/old/xmldocument.h
@@ -0,0 +1,165 @@
1#ifndef XMLDOCUMENT
2#define XMLDOCUMENT
3
4#include "xmlnode.h"
5
6/**
7 * Keeps track of an easily managed set of XmlNode information. Allows simple
8 * operations for logical writing to and reading from XML structures. Using
9 * already formed structures is simply done through the XmlNode structures,
10 * and the getRoot function here. Creation is performed through a simple set
11 * of operations that creates the data in a stream type format.
12 *@author Mike Buland
13 */
14class XmlDocument
15{
16public:
17 /**
18 * Construct either a blank XmlDocuemnt or construct a document around an
19 * existing XmlNode. Be careful, once an XmlNode is passed into a document
20 * the document takes over ownership and will delete it when the XmlDocument
21 * is deleted.
22 *@param pRoot The XmlNode to use as the root of this document, or NULL if
23 * you want to start a new document.
24 */
25 XmlDocument( XmlNode *pRoot=NULL );
26
27 /**
28 * Destroy all contained nodes.
29 */
30 virtual ~XmlDocument();
31
32 /**
33 * Add a new node to the document. The new node is appended to the end of
34 * the current context, i.e. XmlNode, and the new node, provided it isn't
35 * close as part of this operation, will become the current context.
36 *@param sName The name of the new node to add.
37 *@param sContent A content string to be placed inside of the new node.
38 *@param bClose Set this to true to close the node immediately after adding
39 * the node and setting the content and name. If this is set to true the
40 * node is appended, but the context node doesn't change.
41 */
42 void addNode( const Bu::FString &sName );
43
44 /**
45 * Close the current node context. This will move the current context to
46 * the parent node of the former current node. If the current node was the
47 * root then the "completed" flag is set and no more operations are allowed.
48 */
49 void closeNode();
50
51 /**
52 * Change the content of the current node at the current position between
53 * nodes.
54 *@param sContent The new content of the current node.
55 */
56 void setContent( const char *sContent );
57
58 /**
59 * Add a named property to the current context node.
60 *@param sName The name of the property to add.
61 *@param sValue The string value of the property.
62 */
63 void addProperty( const char *sName, const char *sValue );
64
65 /**
66 * Add a named property to the current context node, converting the
67 * numerical parameter to text using standrd printf style conversion.
68 *@param sName The name of the property to add.
69 *@param nValue The numerical value to add.
70 */
71 void addProperty( const char *sName, const unsigned char nValue );
72
73 /**
74 * Add a named property to the current context node, converting the
75 * numerical parameter to text using standrd printf style conversion.
76 *@param sName The name of the property to add.
77 *@param nValue The numerical value to add.
78 */
79 void addProperty( const char *sName, const char nValue );
80
81 /**
82 * Add a named property to the current context node, converting the
83 * numerical parameter to text using standrd printf style conversion.
84 *@param sName The name of the property to add.
85 *@param nValue The numerical value to add.
86 */
87 void addProperty( const char *sName, const unsigned short nValue );
88
89 /**
90 * Add a named property to the current context node, converting the
91 * numerical parameter to text using standrd printf style conversion.
92 *@param sName The name of the property to add.
93 *@param nValue The numerical value to add.
94 */
95 void addProperty( const char *sName, const short nValue );
96
97 /**
98 * Add a named property to the current context node, converting the
99 * numerical parameter to text using standrd printf style conversion.
100 *@param sName The name of the property to add.
101 *@param nValue The numerical value to add.
102 */
103 void addProperty( const char *sName, const unsigned long nValue );
104
105 /**
106 * Add a named property to the current context node, converting the
107 * numerical parameter to text using standrd printf style conversion.
108 *@param sName The name of the property to add.
109 *@param nValue The numerical value to add.
110 */
111 void addProperty( const char *sName, const long nValue );
112
113 /**
114 * Add a named property to the current context node, converting the
115 * numerical parameter to text using standrd printf style conversion.
116 *@param sName The name of the property to add.
117 *@param nValue The numerical value to add.
118 */
119 void addProperty( const char *sName, const int nValue );
120
121 /**
122 * Add a named property to the current context node, converting the
123 * numerical parameter to text using standrd printf style conversion.
124 *@param sName The name of the property to add.
125 *@param dValue The numerical value to add.
126 */
127 void addProperty( const char *sName, const double dValue );
128
129 /**
130 * The XmlDocuemnt is considered completed if the root node has been closed.
131 * Once an XmlDocument has been completed, you can no longer perform
132 * operations on it.
133 *@return True if completed, false if still in progress.
134 */
135 bool isCompleted();
136
137 /**
138 * Get a pointer to the root object of this XmlDocument.
139 *@returns A pointer to an internally owned XmlNode. Do not delete this
140 * XmlNode.
141 */
142 XmlNode *getRoot();
143
144 /**
145 * Get a pointer to the root object of this XmlDocument, and remove the
146 * ownership from this object.
147 *@returns A pointer to an internally owned XmlNode. Do not delete this
148 * XmlNode.
149 */
150 XmlNode *detatchRoot();
151
152 /**
153 * Get the current context node, which could be the same as the root node.
154 *@returns A pointer to an internally owned XmlNode. Do not delete this
155 * XmlNode.
156 */
157 XmlNode *getCurrent();
158
159private:
160 XmlNode *pRoot; /**< The root node. */
161 XmlNode *pCurrent; /**< The current node. */
162 bool bCompleted; /**< Is it completed? */
163};
164
165#endif
diff --git a/src/old/xmlnode.cpp b/src/old/xmlnode.cpp
new file mode 100644
index 0000000..96d5850
--- /dev/null
+++ b/src/old/xmlnode.cpp
@@ -0,0 +1,403 @@
1#include "xmlnode.h"
2
3XmlNode::XmlNode( const Bu::FString &sName, XmlNode *pParent ) :
4 sName( sName ),
5 pParent( pParent )
6{
7}
8
9XmlNode::~XmlNode()
10{
11}
12/*
13void XmlNode::setName( const char *sName )
14{
15 if( pParent )
16 {
17 if( this->sName.size() == 0 )
18 {
19 // We're not in the hash yet, so add us
20 this->sName = sName;
21 pParent->hChildren.insert( this->sName.c_str(), this );
22 }
23 else
24 {
25 // Slightly more tricky, delete us, then add us...
26 pParent->hChildren.del( this->sName.c_str() );
27 this->sName = sName;
28 pParent->hChildren.insert( this->sName.c_str(), this );
29 }
30 }
31 else
32 {
33 // If we have no parent, then just set the name string, we don't need
34 // to worry about hashing.
35 this->sName = sName;
36 }
37}
38
39void XmlNode::setContent( const char *sContent, int nIndex )
40{
41 if( nIndex == -1 )
42 {
43 nIndex = nCurContent;
44 }
45 if( nIndex == 0 )
46 {
47 if( this->sPreContent )
48 {
49 delete this->sPreContent;
50 }
51
52 this->sPreContent = new std::string( sContent );
53 }
54 else
55 {
56 nIndex--;
57 if( lPostContent[nIndex] )
58 {
59 delete (std::string *)lPostContent[nIndex];
60 }
61
62 lPostContent.setAt( nIndex, new std::string( sContent ) );
63 }
64}
65
66const char *XmlNode::getContent( int nIndex )
67{
68 if( nIndex == 0 )
69 {
70 if( sPreContent )
71 {
72 return sPreContent->c_str();
73 }
74 }
75 else
76 {
77 nIndex--;
78 if( lPostContent[nIndex] )
79 {
80 return ((std::string *)lPostContent[nIndex])->c_str();
81 }
82 }
83
84 return NULL;
85}*/
86
87XmlNode *XmlNode::addChild( const Bu::FString &sName )
88{
89 return addChild( new XmlNode( sName, this ) );
90}
91
92XmlNode *XmlNode::addChild( XmlNode *pNode )
93{
94 Child c = { typeNode };
95 c.pNode = pNode;
96 lChildren.append( c );
97 pNode->pParent = this;
98
99 return pNode;
100}
101
102XmlNode *XmlNode::getParent()
103{
104 return pParent;
105}
106
107void XmlNode::addProperty( const Bu::FString &sName, const Bu::FString &sValue )
108{
109 hProperties.insert( sName, sValue );
110}
111
112int XmlNode::getNumProperties()
113{
114 return hProperties.size();
115}
116/*
117const char *XmlNode::getPropertyName( int nIndex )
118{
119 std::string *tmp = ((std::string *)lPropNames[nIndex]);
120 if( tmp == NULL )
121 return NULL;
122 return tmp->c_str();
123}
124
125const char *XmlNode::getProperty( int nIndex )
126{
127 std::string *tmp = ((std::string *)lPropValues[nIndex]);
128 if( tmp == NULL )
129 return NULL;
130 return tmp->c_str();
131}
132*/
133Bu::FString XmlNode::getProperty( const Bu::FString &sName )
134{
135 return hProperties[sName];
136}
137/*
138void XmlNode::deleteProperty( int nIndex )
139{
140 hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() );
141
142 delete (std::string *)lPropNames[nIndex];
143 delete (std::string *)lPropValues[nIndex];
144
145 lPropNames.deleteAt( nIndex );
146 lPropValues.deleteAt( nIndex );
147}
148
149bool XmlNode::hasChildren()
150{
151 return hChildren.getSize()>0;
152}*/
153
154int XmlNode::getNumChildren()
155{
156 return lChildren.getSize();
157}
158/*
159XmlNode *XmlNode::getChild( int nIndex )
160{
161 return (XmlNode *)lChildren[nIndex];
162}
163*/
164XmlNode *XmlNode::getChild( const Bu::FString &sName, int nSkip )
165{
166 if( !hChildren.has( sName ) )
167 return NULL;
168
169 Bu::List<XmlNode *>::iterator i = hChildren[sName]->begin();
170 return *i;
171}
172
173Bu::FString XmlNode::getName()
174{
175 return sName;
176}
177/*
178void XmlNode::deleteNode( int nIndex, const char *sReplacementText )
179{
180 XmlNode *xRet = detatchNode( nIndex, sReplacementText );
181
182 if( xRet != NULL )
183 {
184 delete xRet;
185 }
186}
187
188XmlNode *XmlNode::detatchNode( int nIndex, const char *sReplacementText )
189{
190 if( nIndex < 0 || nIndex >= lChildren.getSize() )
191 return NULL;
192
193 // The real trick when deleteing a node isn't actually deleting it, it's
194 // reforming the content around the node that's now missing...hmmm...
195
196 if( nIndex == 0 )
197 {
198 // If the index is zero we have to deal with the pre-content
199 if( sReplacementText )
200 {
201 if( sPreContent == NULL )
202 {
203 sPreContent = new std::string( sReplacementText );
204 }
205 else
206 {
207 *sPreContent += sReplacementText;
208 }
209 }
210 if( lPostContent.getSize() > 0 )
211 {
212 if( lPostContent[0] != NULL )
213 {
214 if( sPreContent == NULL )
215 {
216 sPreContent = new std::string(
217 ((std::string *)lPostContent[0])->c_str()
218 );
219 }
220 else
221 {
222 *sPreContent +=
223 ((std::string *)lPostContent[0])->c_str();
224 }
225 }
226 delete (std::string *)lPostContent[0];
227 lPostContent.deleteAt( 0 );
228 }
229 }
230 else
231 {
232 int nCont = nIndex-1;
233 // If it's above zero we deal with the post-content only
234 if( sReplacementText )
235 {
236 if( lPostContent[nCont] == NULL )
237 {
238 lPostContent.setAt( nCont, new std::string( sReplacementText ) );
239 }
240 else
241 {
242 *((std::string *)lPostContent[nCont]) += sReplacementText;
243 }
244 }
245 if( lPostContent.getSize() > nIndex )
246 {
247 if( lPostContent[nIndex] != NULL )
248 {
249 if( lPostContent[nCont] == NULL )
250 {
251 lPostContent.setAt( nCont, new std::string(
252 ((std::string *)lPostContent[nIndex])->c_str()
253 ) );
254 }
255 else
256 {
257 *((std::string *)lPostContent[nCont]) +=
258 ((std::string *)lPostContent[nIndex])->c_str();
259 }
260 }
261 delete (std::string *)lPostContent[nIndex];
262 lPostContent.deleteAt( nIndex );
263 }
264 }
265
266 XmlNode *xRet = (XmlNode *)lChildren[nIndex];
267 hChildren.del( ((XmlNode *)lChildren[nIndex])->getName() );
268 lChildren.deleteAt( nIndex );
269
270 return xRet;
271}
272
273void XmlNode::replaceNode( int nIndex, XmlNode *pNewNode )
274{
275 if( nIndex < 0 || nIndex >= lChildren.getSize() )
276 return; //TODO: throw an exception
277
278 delete (XmlNode *)lChildren[nIndex];
279 lChildren.setAt( nIndex, pNewNode );
280 pNewNode->pParent = this;
281}
282
283XmlNode *XmlNode::getCopy()
284{
285 XmlNode *pNew = new XmlNode();
286
287 pNew->sName = sName;
288 if( sPreContent )
289 {
290 pNew->sPreContent = new std::string( sPreContent->c_str() );
291 }
292 else
293 {
294 pNew->sPreContent = NULL;
295 }
296 pNew->nCurContent = 0;
297
298 int nSize = lPostContent.getSize();
299 pNew->lPostContent.setSize( nSize );
300 for( int j = 0; j < nSize; j++ )
301 {
302 if( lPostContent[j] )
303 {
304 pNew->lPostContent.setAt(
305 j, new std::string(
306 ((std::string *)lPostContent[j])->c_str()
307 )
308 );
309 }
310 else
311 {
312 pNew->lPostContent.setAt( j, NULL );
313 }
314 }
315
316 nSize = lChildren.getSize();
317 pNew->lChildren.setSize( nSize );
318 for( int j = 0; j < nSize; j++ )
319 {
320 XmlNode *pChild = ((XmlNode *)lChildren[j])->getCopy();
321 pNew->lChildren.setAt( j, pChild );
322 pChild->pParent = pNew;
323 pNew->hChildren.insert( pChild->getName(), pChild );
324 }
325
326 nSize = lPropNames.getSize();
327 pNew->lPropNames.setSize( nSize );
328 pNew->lPropValues.setSize( nSize );
329 for( int j = 0; j < nSize; j++ )
330 {
331 std::string *pProp = new std::string( ((std::string *)lPropNames[j])->c_str() );
332 std::string *pVal = new std::string( ((std::string *)lPropValues[j])->c_str() );
333 pNew->lPropNames.setAt( j, pProp );
334 pNew->lPropValues.setAt( j, pVal );
335 pNew->hProperties.insert( pProp->c_str(), pVal->c_str() );
336 pNew->nCurContent++;
337 }
338
339 return pNew;
340}
341
342void XmlNode::deleteNodeKeepChildren( int nIndex )
343{
344 // This is a tricky one...we need to do some patching to keep things all
345 // even...
346 XmlNode *xRet = (XmlNode *)lChildren[nIndex];
347
348 if( xRet == NULL )
349 {
350 return;
351 }
352 else
353 {
354 if( getContent( nIndex ) )
355 {
356 std::string sBuf( getContent( nIndex ) );
357 sBuf += xRet->getContent( 0 );
358 setContent( sBuf.c_str(), nIndex );
359 }
360 else
361 {
362 setContent( xRet->getContent( 0 ), nIndex );
363 }
364
365 int nSize = xRet->lChildren.getSize();
366 for( int j = 0; j < nSize; j++ )
367 {
368 XmlNode *pCopy = ((XmlNode *)xRet->lChildren[j])->getCopy();
369 pCopy->pParent = this;
370 lChildren.insertBefore( pCopy, nIndex+j );
371
372 if( xRet->lPostContent[j] )
373 {
374 lPostContent.insertBefore(
375 new std::string( ((std::string *)xRet->lPostContent[j])->c_str() ),
376 nIndex+j
377 );
378 }
379 else
380 {
381 lPostContent.insertBefore( NULL, nIndex+j );
382 }
383 }
384
385 if( getContent( nIndex+nSize ) )
386 {
387 //SString sBuf( getContent( nIndex+nSize ) );
388 //sBuf.catfrom( xRet->getContent( nSize ) );
389 //setContent( sBuf, nIndex+nSize );
390 }
391 else
392 {
393 setContent( xRet->getContent( nSize ), nIndex+nSize );
394 }
395
396 deleteNode( nIndex+nSize );
397 }
398}
399
400void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode )
401{
402}
403*/
diff --git a/src/old/xmlnode.h b/src/old/xmlnode.h
new file mode 100644
index 0000000..c895cd8
--- /dev/null
+++ b/src/old/xmlnode.h
@@ -0,0 +1,207 @@
1#ifndef XMLNODE
2#define XMLNODE
3
4#include <iostream>
5#include "bu/list.h"
6#include "bu/hash.h"
7#include "bu/fstring.h"
8
9/**
10 * Maintains all data pertient to an XML node, including sub-nodes and content.
11 * All child nodes can be accessed through index and through name via a hash
12 * table. This makes it very easy to gain simple and fast access to all of
13 * your data. For most applications, the memory footprint is also rather
14 * small. While XmlNode objects can be used directly to create XML structures
15 * it is highly reccomended that all operations be performed through the
16 * XmlDocument class.
17 *@author Mike Buland
18 */
19class XmlNode
20{
21public:
22 /**
23 * Construct a new XmlNode.
24 *@param sName The name of the node.
25 *@param pParent The parent node.
26 *@param sContent The initial content string.
27 */
28 XmlNode(
29 const Bu::FString &sName,
30 XmlNode *pParent=NULL
31 );
32
33 /**
34 * Delete the node and cleanup all memory.
35 */
36 virtual ~XmlNode();
37
38 /**
39 * Change the name of the node.
40 *@param sName The new name of the node.
41 */
42 //void setName( const char *sName );
43
44 /**
45 * Construct a new node and add it as a child to this node, also return a
46 * pointer to the newly constructed node.
47 *@param sName The name of the new node.
48 *@param sContent The initial content of the new node.
49 *@returns A pointer to the newly created child node.
50 */
51 XmlNode *addChild( const Bu::FString &sName );
52
53 /**
54 * Add an already created XmlNode as a child to this node. The new child
55 * XmlNode's parent will be changed appropriately and the parent XmlNode
56 * will take ownership of the child.
57 *@param pChild The child XmlNode to add to this XmlNode.
58 *@returns A pointer to the child node that was just added.
59 */
60 XmlNode *addChild( XmlNode *pChild );
61
62 /**
63 * Add a new property to the XmlNode. Properties are name/value pairs.
64 *@param sName The name of the property. Specifying a name that's already
65 * in use will overwrite that property.
66 *@param sValue The textual value of the property.
67 */
68 void addProperty( const Bu::FString &sName, const Bu::FString &sValue );
69
70 /**
71 * Get a pointer to the parent node, if any.
72 *@returns A pointer to the node's parent, or NULL if there isn't one.
73 */
74 XmlNode *getParent();
75
76 /**
77 * Tells you if this node has children.
78 *@returns True if this node has at least one child, false otherwise.
79 */
80 bool hasChildren();
81
82 /**
83 * Tells you how many children this node has.
84 *@returns The number of children this node has.
85 */
86 int getNumChildren();
87
88 /**
89 * Get a child with the specified name, and possibly skip value. For an
90 * explination of skip values see the HashTable.
91 *@param sName The name of the child to find.
92 *@param nSkip The number of nodes with that name to skip.
93 *@returns A pointer to the child, or NULL if no child with that name was
94 * found.
95 */
96 XmlNode *getChild( const Bu::FString &sName, int nSkip=0 );
97
98 /**
99 * Get a pointer to the name of this node. Do not change this, use setName
100 * instead.
101 *@returns A pointer to the name of this node.
102 */
103 Bu::FString getName();
104
105 /**
106 * Set the content of this node, optionally at a specific index. Using the
107 * default of -1 will set the content after the last added node.
108 *@param sContent The content string to use.
109 *@param nIndex The index of the content.
110 */
111 //void setContent( const char *sContent, int nIndex=-1 );
112
113 /**
114 * Get the number of properties in this node.
115 *@returns The number of properties in this node.
116 */
117 int getNumProperties();
118
119 /**
120 * Get a propery's value by name.
121 *@param sName The name of the property to examine.
122 *@returns A pointer to the value of the property specified, or NULL if none
123 * found.
124 */
125 Bu::FString getProperty( const Bu::FString &sName );
126
127 /**
128 * Delete a child node, possibly replacing it with some text. This actually
129 * fixes all content strings around the newly deleted child node.
130 *@param nIndex The index of the node to delete.
131 *@param sReplacementText The optional text to replace the node with.
132 *@returns True of the node was found, and deleted, false if it wasn't
133 * found.
134 */
135 //void deleteNode( int nIndex, const char *sReplacementText = NULL );
136
137 /**
138 * Delete a given node, but move all of it's children and content up to
139 * replace the deleted node. All of the content of the child node is
140 * spliced seamlessly into place with the parent node's content.
141 *@param nIndex The node to delete.
142 *@returns True if the node was found and deleted, false if it wasn't.
143 */
144 //void deleteNodeKeepChildren( int nIndex );
145
146 /**
147 * Detatch a given child node from this node. This effectively works just
148 * like a deleteNode, except that instead of deleting the node it is removed
149 * and returned, and all ownership is given up.
150 *@param nIndex The index of the node to detatch.
151 *@param sReplacementText The optional text to replace the detatched node
152 * with.
153 *@returns A pointer to the newly detatched node, which then passes
154 * ownership to the caller.
155 */
156 //XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL );
157
158 /**
159 * Replace a given node with a different node that is not currently owned by
160 * this XmlNode or any ancestor.
161 *@param nIndex The index of the node to replace.
162 *@param pNewNode The new node to replace the old node with.
163 *@returns True if the node was found and replaced, false if it wasn't.
164 */
165 //void replaceNode( int nIndex, XmlNode *pNewNode );
166
167 /**
168 * Replace a given node with the children and content of a given node.
169 *@param nIndex The index of the node to replace.
170 *@param pNewNode The node that contains the children and content that will
171 * replace the node specified by nIndex.
172 *@returns True if the node was found and replaced, false if it wasn't.
173 */
174 //void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode );
175
176 /**
177 * Get a copy of this node and all children. getCopy is recursive, so
178 * beware copying large trees of xml.
179 *@returns A newly created copy of this node and all of it's children.
180 */
181 //XmlNode *getCopy();
182
183 enum ChildType
184 {
185 typeNode,
186 typeContent
187 };
188
189private:
190 typedef struct
191 {
192 uint8_t nType;
193 union {
194 XmlNode *pNode;
195 Bu::FString *pContent;
196 };
197 } Child;
198 Bu::FString sName; /**< The name of the node. */
199 Bu::List<Child> lChildren; /**< The children. */
200 Bu::Hash<Bu::FString, Bu::FString> hProperties; /**< Property hashtable. */
201 Bu::Hash<Bu::FString, Bu::List<XmlNode *> > hChildren; /**< Children hashtable. */
202 XmlNode *pParent; /**< A pointer to the parent of this node. */
203 int nCurContent; /**< The current content we're on, for using the -1 on
204 setContent. */
205};
206
207#endif
diff --git a/src/old/xmlreader.cpp b/src/old/xmlreader.cpp
new file mode 100644
index 0000000..38cad5f
--- /dev/null
+++ b/src/old/xmlreader.cpp
@@ -0,0 +1,604 @@
1#include "bu/xmlreader.h"
2#include "bu/exceptions.h"
3#include <string.h>
4
5XmlReader::XmlReader( Bu::Stream &sIn, bool bStrip ) :
6 sIn( sIn ),
7 bStrip( bStrip )
8{
9 buildDoc();
10}
11
12XmlReader::~XmlReader()
13{
14}
15
16char XmlReader::getChar( int nIndex )
17{
18 if( sBuf.getSize() <= nIndex )
19 {
20 int nInc = nIndex-sBuf.getSize()+1;
21 char *buf = new char[nInc];
22 sIn.read( buf, nInc );
23 sBuf.append( buf, nInc );
24 delete[] buf;
25 }
26
27 return sBuf[nIndex];
28}
29
30void XmlReader::usedChar( int nAmnt )
31{
32 if( nAmnt >= sBuf.getSize() )
33 {
34 sBuf.clear();
35 }
36 else
37 {
38 char *s = sBuf.getStr();
39 memcpy( s, s+nAmnt, sBuf.getSize()-nAmnt );
40 sBuf.resize( sBuf.getSize()-nAmnt );
41 }
42}
43
44void XmlReader::addEntity( const Bu::FString &name, const Bu::FString &value )
45{
46 htEntity[name] = value;
47}
48
49#define gcall( x ) if( x == false ) return false;
50
51bool XmlReader::isws( char chr )
52{
53 return ( chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' );
54}
55
56bool XmlReader::ws()
57{
58 while( true )
59 {
60 char chr = getChar();
61 if( isws( chr ) )
62 {
63 usedChar();
64 }
65 else
66 {
67 return true;
68 }
69 }
70 return true;
71}
72
73bool XmlReader::buildDoc()
74{
75 // take care of initial whitespace
76 gcall( ws() );
77 textDecl();
78 entity();
79 addEntity("gt", ">");
80 addEntity("lt", "<");
81 addEntity("amp", "&");
82 addEntity("apos", "\'");
83 addEntity("quot", "\"");
84 gcall( node() );
85
86 return true;
87}
88
89void XmlReader::textDecl()
90{
91 if( getChar() == '<' && getChar( 1 ) == '?' )
92 {
93 usedChar( 2 );
94 for(;;)
95 {
96 if( getChar() == '?' )
97 {
98 if( getChar( 1 ) == '>' )
99 {
100 usedChar( 2 );
101 return;
102 }
103 }
104 usedChar();
105 }
106 }
107}
108
109void XmlReader::entity()
110{
111 for(;;)
112 {
113 ws();
114
115 if( getChar() == '<' && getChar( 1 ) == '!' )
116 {
117 usedChar( 2 );
118 ws();
119 Bu::FString buf;
120 for(;;)
121 {
122 char chr = getChar();
123 usedChar();
124 if( isws( chr ) ) break;
125 buf += chr;
126 }
127
128 if( strcmp( buf.c_str(), "ENTITY") == 0 )
129 {
130 ws();
131 Bu::FString name;
132 for(;;)
133 {
134 char chr = getChar();
135 usedChar();
136 if( isws( chr ) ) break;
137 name += chr;
138 }
139 ws();
140 char quot = getChar();
141 usedChar();
142 if( quot != '\'' && quot != '\"' )
143 {
144 throw Bu::XmlException(
145 "Only quoted entity values are supported."
146 );
147 }
148 Bu::FString value;
149 for(;;)
150 {
151 char chr = getChar();
152 usedChar();
153 if( chr == '&' )
154 {
155 Bu::FString tmp = getEscape();
156 value += tmp;
157 }
158 else if( chr == quot )
159 {
160 break;
161 }
162 else
163 {
164 value += chr;
165 }
166 }
167 ws();
168 if( getChar() == '>' )
169 {
170 usedChar();
171
172 addEntity( name.c_str(), value.c_str() );
173 }
174 else
175 {
176 throw Bu::XmlException(
177 "Malformed ENTITY: unexpected '%c' found.",
178 getChar()
179 );
180 }
181 }
182 else
183 {
184 throw Bu::XmlException(
185 "Unsupported header symbol: %s",
186 buf.c_str()
187 );
188 }
189 }
190 else
191 {
192 return;
193 }
194 }
195}
196
197bool XmlReader::node()
198{
199 gcall( startNode() )
200
201 // At this point, we are closing the startNode
202 char chr = getChar();
203 if( chr == '>' )
204 {
205 usedChar();
206
207 // Now we process the guts of the node.
208 gcall( content() );
209 }
210 else if( chr == '/' )
211 {
212 // This is the tricky one, one more validation, then we close the node.
213 usedChar();
214 if( getChar() == '>' )
215 {
216 closeNode();
217 usedChar();
218 }
219 else
220 {
221 throw Bu::XmlException("Close node in singleNode malformed!");
222 }
223 }
224 else
225 {
226 throw Bu::XmlException("Close node expected, but not found.");
227 return false;
228 }
229
230 return true;
231}
232
233bool XmlReader::startNode()
234{
235 if( getChar() == '<' )
236 {
237 usedChar();
238
239 if( getChar() == '/' )
240 {
241 // Heh, it's actually a close node, go figure
242 Bu::FString sName;
243 usedChar();
244 gcall( ws() );
245
246 while( true )
247 {
248 char chr = getChar();
249 if( isws( chr ) || chr == '>' )
250 {
251 // Here we actually compare the name we got to the name
252 // we already set, they have to match exactly.
253 if( getCurrent()->getName() == sName )
254 {
255 closeNode();
256 break;
257 }
258 else
259 {
260 throw Bu::XmlException("Got a mismatched node close tag.");
261 }
262 }
263 else
264 {
265 sName += chr;
266 usedChar();
267 }
268 }
269
270 gcall( ws() );
271 if( getChar() == '>' )
272 {
273 // Everything is cool.
274 usedChar();
275 }
276 else
277 {
278 throw Bu::XmlException("Got extra junk data instead of node close tag.");
279 }
280 }
281 else
282 {
283 // We're good, format is consistant
284 //addNode();
285
286 // Skip extra whitespace
287 gcall( ws() );
288 gcall( name() );
289 gcall( ws() );
290 gcall( paramlist() );
291 gcall( ws() );
292 }
293 }
294 else
295 {
296 throw Bu::XmlException("Expected to find node opening char, '<'.");
297 }
298
299 return true;
300}
301
302bool XmlReader::name()
303{
304 Bu::FString sName;
305
306 while( true )
307 {
308 char chr = getChar();
309 if( isws( chr ) || chr == '>' || chr == '/' )
310 {
311 addNode( sName );
312 return true;
313 }
314 else
315 {
316 sName += chr;
317 usedChar();
318 }
319 }
320
321 return true;
322}
323
324bool XmlReader::paramlist()
325{
326 while( true )
327 {
328 char chr = getChar();
329 if( chr == '/' || chr == '>' )
330 {
331 return true;
332 }
333 else
334 {
335 gcall( param() );
336 gcall( ws() );
337 }
338 }
339
340 return true;
341}
342
343Bu::FString XmlReader::getEscape()
344{
345 if( getChar( 1 ) == '#' )
346 {
347 // If the entity starts with a # it's a character escape code
348 int base = 10;
349 usedChar( 2 );
350 if( getChar() == 'x' )
351 {
352 base = 16;
353 usedChar();
354 }
355 char buf[4];
356 int j = 0;
357 for( j = 0; getChar() != ';'; j++ )
358 {
359 buf[j] = getChar();
360 usedChar();
361 }
362 usedChar();
363 buf[j] = '\0';
364 buf[0] = (char)strtol( buf, (char **)NULL, base );
365 buf[1] = '\0';
366
367 return buf;
368 }
369 else
370 {
371 // ...otherwise replace with the appropriate string...
372 Bu::FString buf;
373 usedChar();
374 for(;;)
375 {
376 char cbuf = getChar();
377 usedChar();
378 if( cbuf == ';' ) break;
379 buf += cbuf;
380 }
381
382 return htEntity[buf];
383 }
384}
385
386bool XmlReader::param()
387{
388 Bu::FString sName;
389 Bu::FString sValue;
390
391 while( true )
392 {
393 char chr = getChar();
394 if( isws( chr ) || chr == '=' )
395 {
396 break;
397 }
398 else
399 {
400 sName.append( chr );
401 usedChar();
402 }
403 }
404
405 gcall( ws() );
406
407 if( getChar() == '=' )
408 {
409 usedChar();
410
411 gcall( ws() );
412
413 char chr = getChar();
414 if( chr == '"' )
415 {
416 // Better quoted rhs
417 usedChar();
418
419 while( true )
420 {
421 chr = getChar();
422 if( chr == '"' )
423 {
424 usedChar();
425 addProperty( sName.getStr(), sValue.getStr() );
426 return true;
427 }
428 else
429 {
430 if( chr == '&' )
431 {
432 sValue += getEscape();
433 }
434 else
435 {
436 sValue += chr;
437 usedChar();
438 }
439 }
440 }
441 }
442 else
443 {
444 // Simple one-word rhs
445 while( true )
446 {
447 chr = getChar();
448 if( isws( chr ) || chr == '/' || chr == '>' )
449 {
450 addProperty( sName.getStr(), sValue.getStr() );
451 return true;
452 }
453 else
454 {
455 if( chr == '&' )
456 {
457 sValue += getEscape();
458 }
459 else
460 {
461 sValue += chr;
462 usedChar();
463 }
464 }
465 }
466 }
467 }
468 else
469 {
470 throw Bu::XmlException("Expected an equals to seperate the params.");
471 return false;
472 }
473
474 return true;
475}
476
477bool XmlReader::content()
478{
479 Bu::FString sContent;
480
481 if( bStrip ) gcall( ws() );
482
483 while( true )
484 {
485 char chr = getChar();
486 if( chr == '<' )
487 {
488 if( getChar(1) == '/' )
489 {
490 if( sContent.getSize() > 0 )
491 {
492 if( bStrip )
493 {
494 int j;
495 for( j = sContent.getSize()-1; isws(sContent[j]); j-- );
496 sContent[j+1] = '\0';
497 }
498 setContent( sContent.getStr() );
499 }
500 usedChar( 2 );
501 gcall( ws() );
502 Bu::FString sName;
503 while( true )
504 {
505 chr = getChar();
506 if( isws( chr ) || chr == '>' )
507 {
508 if( !strcasecmp( getCurrent()->getName().getStr(), sName.getStr() ) )
509 {
510 closeNode();
511 break;
512 }
513 else
514 {
515 throw Bu::XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName().getStr(), sName.getStr() );
516 }
517 }
518 else
519 {
520 sName += chr;
521 usedChar();
522 }
523 }
524 gcall( ws() );
525 if( getChar() == '>' )
526 {
527 usedChar();
528 return true;
529 }
530 else
531 {
532 throw Bu::XmlException("Malformed close tag.");
533 }
534 }
535 else if( getChar(1) == '!' )
536 {
537 // We know it's a comment, let's see if it's proper
538 if( getChar(2) != '-' ||
539 getChar(3) != '-' )
540 {
541 // Not a valid XML comment
542 throw Bu::XmlException("Malformed comment start tag found.");
543 }
544
545 usedChar( 4 );
546
547 // Now burn text until we find the close tag
548 for(;;)
549 {
550 if( getChar() == '-' )
551 {
552 if( getChar( 1 ) == '-' )
553 {
554 // The next one has to be a '>' now
555 if( getChar( 2 ) != '>' )
556 {
557 throw Bu::XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment.");
558 }
559 usedChar( 3 );
560 break;
561 }
562 else
563 {
564 // Found a dash followed by a non dash, that's ok...
565 usedChar( 2 );
566 }
567 }
568 else
569 {
570 // Burn comment chars
571 usedChar();
572 }
573 }
574 }
575 else
576 {
577 if( sContent.getSize() > 0 )
578 {
579 if( bStrip )
580 {
581 int j;
582 for( j = sContent.getSize()-1; isws(sContent[j]); j-- );
583 sContent[j+1] = '\0';
584 }
585 setContent( sContent.getStr() );
586 sContent.clear();
587 }
588 gcall( node() );
589 }
590
591 if( bStrip ) gcall( ws() );
592 }
593 else if( chr == '&' )
594 {
595 sContent += getEscape();
596 }
597 else
598 {
599 sContent += chr;
600 usedChar();
601 }
602 }
603}
604
diff --git a/src/old/xmlreader.h b/src/old/xmlreader.h
new file mode 100644
index 0000000..7c85ddb
--- /dev/null
+++ b/src/old/xmlreader.h
@@ -0,0 +1,144 @@
1#ifndef XMLREADER
2#define XMLREADER
3
4#include <stdio.h>
5#include "bu/xmldocument.h"
6#include "bu/hash.h"
7#include "bu/fstring.h"
8#include "bu/stream.h"
9
10/**
11 * Takes care of reading in xml formatted data from a file. This could/should
12 * be made more arbitrary in the future so that we can read the data from any
13 * source. This is actually made quite simple already since all data read in
14 * is handled by one single helper function and then palced into a FlexBuf for
15 * easy access by the other functions. The FlexBuf also allows for block
16 * reading from disk, which improves speed by a noticable amount.
17 * <br>
18 * There are also some extra features implemented that allow you to break the
19 * standard XML reader specs and eliminate leading and trailing whitespace in
20 * all read content. This is useful in situations where you allow additional
21 * whitespace in the files to make them easily human readable. The resturned
22 * content will be NULL in sitautions where all content between nodes was
23 * stripped.
24 *@author Mike Buland
25 */
26class XmlReader : public XmlDocument
27{
28public:
29 /**
30 * Create a standard XmlReader. The optional parameter bStrip allows you to
31 * create a reader that will strip out all leading and trailing whitespace
32 * in content, a-la html.
33 *@param bStrip Strip out leading and trailing whitespace?
34 */
35 XmlReader( Bu::Stream &sIn, bool bStrip=false );
36
37 /**
38 * Destroy this XmlReader.
39 */
40 virtual ~XmlReader();
41
42 /**
43 * Build a document based on some kind of input. This is called
44 * automatically by the constructor.
45 */
46 bool buildDoc();
47
48private:
49 /**
50 * This is called by the low level automoton in order to get the next
51 * character. This function should return a character at the current
52 * position plus nIndex, but does not increment the current character.
53 *@param nIndex The index of the character from the current stream position.
54 *@returns A single character at the requested position, or 0 for end of
55 * stream.
56 */
57 virtual char getChar( int nIndex = 0 );
58
59 /**
60 * Called to increment the current stream position by a single character.
61 */
62 virtual void usedChar( int nAmnt = 1 );
63
64 /**
65 * Automoton function: is whitespace.
66 *@param chr A character
67 *@returns True if chr is whitespace, false otherwise.
68 */
69 bool isws( char chr );
70
71 /**
72 * Automoton function: ws. Skips sections of whitespace.
73 *@returns True if everything was ok, False for end of stream.
74 */
75 bool ws();
76
77 /**
78 * Automoton function: node. Processes an XmlNode
79 *@returns True if everything was ok, False for end of stream.
80 */
81 bool node();
82
83 /**
84 * Automoton function: startNode. Processes the begining of a node.
85 *@returns True if everything was ok, False for end of stream.
86 */
87 bool startNode();
88
89 /**
90 * Automoton function: name. Processes the name of a node.
91 *@returns True if everything was ok, False for end of stream.
92 */
93 bool name();
94
95 /**
96 * Automoton function: textDecl. Processes the xml text decleration, if
97 * there is one.
98 */
99 void textDecl();
100
101 /**
102 * Automoton function: entity. Processes an entity from the header.
103 */
104 void entity();
105
106 /**
107 * Adds an entity to the list, if it doesn't already exist.
108 *@param name The name of the entity
109 *@param value The value of the entity
110 */
111 void addEntity( const Bu::FString &name, const Bu::FString &value );
112
113 Bu::FString getEscape();
114
115 /**
116 * Automoton function: paramlist. Processes a list of node params.
117 *@returns True if everything was ok, False for end of stream.
118 */
119 bool paramlist();
120
121 /**
122 * Automoton function: param. Processes a single parameter.
123 *@returns True if everything was ok, False for end of stream.
124 */
125 bool param();
126
127 /**
128 * Automoton function: content. Processes node content.
129 *@returns True if everything was ok, False for end of stream.
130 */
131 bool content();
132
133 Bu::FString sContent; /**< buffer for the current node's content. */
134 Bu::FString sParamName; /**< buffer for the current param's name. */
135 Bu::FString sParamValue; /**< buffer for the current param's value. */
136 Bu::Stream &sIn;
137 bool bStrip; /**< Are we stripping whitespace? */
138
139 Bu::Hash<Bu::FString,Bu::FString> htEntity; /**< Entity type definitions. */
140
141 Bu::FString sBuf;
142};
143
144#endif
diff --git a/src/old/xmlwriter.cpp b/src/old/xmlwriter.cpp
new file mode 100644
index 0000000..7dc6ca9
--- /dev/null
+++ b/src/old/xmlwriter.cpp
@@ -0,0 +1,167 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include "xmlwriter.h"
4
5XmlWriter::XmlWriter( const Bu::FString &sIndent, XmlNode *pRoot ) :
6 XmlDocument( pRoot ),
7 sIndent( sIndent )
8{
9}
10
11XmlWriter::~XmlWriter()
12{
13}
14
15void XmlWriter::write()
16{
17 write( getRoot(), sIndent.c_str() );
18}
19
20void XmlWriter::write( XmlNode *pRoot, const Bu::FString &sIndent )
21{
22 writeNode( pRoot, 0, sIndent );
23}
24
25void XmlWriter::closeNode()
26{
27 XmlDocument::closeNode();
28
29 if( isCompleted() )
30 {
31 write( getRoot(), sIndent.c_str() );
32 }
33}
34
35void XmlWriter::writeIndent( int nIndent, const Bu::FString &sIndent )
36{
37 if( sIndent == NULL ) return;
38 for( int j = 0; j < nIndent; j++ )
39 {
40 writeString( sIndent );
41 }
42}
43
44Bu::FString XmlWriter::escape( const Bu::FString &sIn )
45{
46 Bu::FString sOut;
47
48 int nMax = sIn.getSize();
49 for( int j = 0; j < nMax; j++ )
50 {
51 char c = sIn[j];
52 if( ((c >= ' ' && c <= '9') ||
53 (c >= 'a' && c <= 'z') ||
54 (c >= 'A' && c <= 'Z') ) &&
55 (c != '\"' && c != '\'' && c != '&')
56 )
57 {
58 sOut += c;
59 }
60 else
61 {
62 sOut += "&#";
63 char buf[4];
64 sprintf( buf, "%u", (unsigned char)c );
65 sOut += buf;
66 sOut += ';';
67 }
68 }
69
70 return sOut;
71}
72
73void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const Bu::FString &sIndent )
74{
75 for( int j = 0; j < pNode->getNumProperties(); j++ )
76 {
77 writeString(" ");
78 //writeString( pNode->getPropertyName( j ) );
79 writeString("=\"");
80 //writeString( escape( pNode->getProperty( j ) ).c_str() );
81 writeString("\"");
82 }
83}
84
85void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const Bu::FString &sIndent )
86{
87 if( pNode->hasChildren() )
88 {
89 writeIndent( nIndent, sIndent );
90 writeString("<");
91 writeString( pNode->getName() );
92 writeNodeProps( pNode, nIndent, sIndent );
93 if( sIndent != "" )
94 writeString(">\n");
95 else
96 writeString(">");
97/*
98 if( pNode->getContent( 0 ) )
99 {
100 writeIndent( nIndent+1, sIndent );
101 if( sIndent != "" )
102 {
103 writeString( pNode->getContent( 0 ) );
104 writeString("\n");
105 }
106 else
107 writeString( pNode->getContent( 0 ) );
108 }
109
110 int nNumChildren = pNode->getNumChildren();
111 for( int j = 0; j < nNumChildren; j++ )
112 {
113 writeNode( pNode->getChild( j ), nIndent+1, sIndent );
114 if( pNode->getContent( j+1 ) )
115 {
116 writeIndent( nIndent+1, sIndent );
117 if( sIndent )
118 {
119 writeString( pNode->getContent( j+1 ) );
120 writeString("\n");
121 }
122 else
123 writeString( pNode->getContent( j+1 ) );
124 }
125 }
126*/
127 writeIndent( nIndent, sIndent );
128 if( sIndent != "" )
129 {
130 writeString("</");
131 writeString( pNode->getName() );
132 writeString(">\n");
133 }
134 else
135 {
136 writeString("</");
137 writeString( pNode->getName() );
138 writeString(">");
139 }
140 }/*
141 else if( pNode->getContent() )
142 {
143 writeIndent( nIndent, sIndent );
144 writeString("<");
145 writeString( pNode->getName() );
146 writeNodeProps( pNode, nIndent, sIndent );
147 writeString(">");
148 writeString( pNode->getContent() );
149 writeString("</");
150 writeString( pNode->getName() );
151 writeString(">");
152 if( sIndent )
153 writeString("\n");
154 }*/
155 else
156 {
157 writeIndent( nIndent, sIndent );
158 writeString("<");
159 writeString( pNode->getName() );
160 writeNodeProps( pNode, nIndent, sIndent );
161 if( sIndent != "" )
162 writeString("/>\n");
163 else
164 writeString("/>");
165 }
166}
167
diff --git a/src/old/xmlwriter.h b/src/old/xmlwriter.h
new file mode 100644
index 0000000..7e3c876
--- /dev/null
+++ b/src/old/xmlwriter.h
@@ -0,0 +1,96 @@
1#ifndef XMLWRITER
2#define XMLWRITER
3
4#include "xmlnode.h"
5#include "xmldocument.h"
6
7/**
8 * Implements xml writing in the XML standard format. Also allows you to
9 * break that format and auto-indent your exported xml data for ease of
10 * reading. The auto-indenting will only be applied to sections that
11 * have no content of their own already. This means that except for
12 * whitespace all of your data will be preserved perfectly.
13 * You can create an XmlWriter object around a file, or access the static
14 * write function directly and just hand it a filename and a root XmlNode.
15 * When using an XmlWriter object the interface is identicle to that of
16 * the XmlDocument class, so reference that class for API info. However
17 * when the initial (or root) node is closed, and the document is finished
18 * the file will be created and written to automatically. The user can
19 * check to see if this is actually true by calling the isFinished
20 * function in the XmlDocument class.
21 *@author Mike Buland
22 */
23class XmlWriter : public XmlDocument
24{
25public:
26 /**
27 * Construct a standard XmlWriter.
28 *@param sIndent Set this to something other than NULL to include it as an
29 * indent before each node in the output that doesn't already have content.
30 * If you are using the whitespace stripping option in the XmlReader and set
31 * this to a tab or some spaces it will never effect the content of your
32 * file.
33 */
34 XmlWriter( const Bu::FString &sIndent="", XmlNode *pRoot=NULL );
35
36 /**
37 * Destroy the writer.
38 */
39 virtual ~XmlWriter();
40
41 /**
42 * This override of the parent class closeNode function calls the parent
43 * class, but also triggers a write operation when the final node is closed.
44 * This means that by checking the isCompleted() function the user may also
45 * check to see if their file has been written or not.
46 */
47 void closeNode();
48
49 void write();
50
51private:
52 Bu::FString sIndent; /**< The indent string */
53
54 Bu::FString escape( const Bu::FString &sIn );
55
56 /**
57 * Write the file.
58 *@param pNode The root node
59 *@param sIndent The indent text.
60 */
61 void write( XmlNode *pNode, const Bu::FString &sIndent );
62
63 /**
64 * Write a node in the file, including children.
65 *@param pNode The node to write.
66 *@param nIndent The indent level (the number of times to include sIndent)
67 *@param sIndent The indent text.
68 */
69 void writeNode( XmlNode *pNode, int nIndent, const Bu::FString &sIndent );
70
71 /**
72 * Write the properties of a node.
73 *@param pNode The node who's properties to write.
74 *@param nIndent The indent level of the containing node
75 *@param sIndent The indent text.
76 */
77 void writeNodeProps( XmlNode *pNode, int nIndent, const Bu::FString &sIndent );
78
79 /**
80 * Called to write the actual indent.
81 *@param nIndent The indent level.
82 *@param sIndent The indent text.
83 */
84 void writeIndent( int nIndent, const Bu::FString &sIndent );
85
86 /**
87 * This is the function that must be overridden in order to use this class.
88 * It must write the null-terminated string sString, minus the mull,
89 * verbatum to it's output device. Adding extra characters for any reason
90 * will break the XML formatting.
91 *@param sString The string data to write to the output.
92 */
93 virtual void writeString( const Bu::FString &sString ) = 0;
94};
95
96#endif