aboutsummaryrefslogtreecommitdiff
path: root/src/old
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2007-06-12 01:28:27 +0000
committerMike Buland <eichlan@xagasoft.com>2007-06-12 01:28:27 +0000
commit4cb166570a8e2e97216bf6c7aeb99b971ff58ad7 (patch)
treeb8d22af96957666ac761b6ca1b57da1eee2e56a5 /src/old
parentb6f50f249ba3b18c597531a2d5dbc45f7bfa3eaa (diff)
downloadlibbu++-4cb166570a8e2e97216bf6c7aeb99b971ff58ad7.tar.gz
libbu++-4cb166570a8e2e97216bf6c7aeb99b971ff58ad7.tar.bz2
libbu++-4cb166570a8e2e97216bf6c7aeb99b971ff58ad7.tar.xz
libbu++-4cb166570a8e2e97216bf6c7aeb99b971ff58ad7.zip
Moved out the xml system again. I think that if I am going to do it again,
I'm going to do it over from scratch, that was just painful. Also, started in again on the server system, it's looking pretty good, already got connections working, next up is managing data flow through clients and protocols!
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