summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fstring.h14
-rw-r--r--src/list.cpp2
-rw-r--r--src/list.h176
-rw-r--r--src/tests/list.cpp22
-rw-r--r--src/tests/xml.cpp6
-rw-r--r--src/xmldocument.cpp20
-rw-r--r--src/xmldocument.h8
-rw-r--r--src/xmlnode.cpp106
-rw-r--r--src/xmlnode.h101
-rw-r--r--src/xmlreader.cpp170
-rw-r--r--src/xmlreader.h31
-rw-r--r--src/xmlwriter.cpp62
-rw-r--r--src/xmlwriter.h16
13 files changed, 428 insertions, 306 deletions
diff --git a/src/fstring.h b/src/fstring.h
index 877e5a7..f738f63 100644
--- a/src/fstring.h
+++ b/src/fstring.h
@@ -28,7 +28,7 @@ namespace Bu
28 * data is actually copied. This also means that you never need to put any 28 * data is actually copied. This also means that you never need to put any
29 * FBasicString into a ref-counting container class. 29 * FBasicString into a ref-counting container class.
30 */ 30 */
31 template< typename chr, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > > 31 template< typename chr, int nMinSize=256, typename chralloc=std::allocator<chr>, typename chunkalloc=std::allocator<struct FStringChunk<chr> > >
32 class FBasicString : public Archival 32 class FBasicString : public Archival
33 { 33 {
34#ifndef VALTEST 34#ifndef VALTEST
@@ -36,7 +36,7 @@ namespace Bu
36#endif 36#endif
37 private: 37 private:
38 typedef struct FStringChunk<chr> Chunk; 38 typedef struct FStringChunk<chr> Chunk;
39 typedef struct FBasicString<chr, chralloc, chunkalloc> MyType; 39 typedef struct FBasicString<chr, nMinSize, chralloc, chunkalloc> MyType;
40 40
41 public: 41 public:
42 FBasicString() : 42 FBasicString() :
@@ -131,6 +131,11 @@ namespace Bu
131 appendChunk( pNew ); 131 appendChunk( pNew );
132 } 132 }
133 133
134 void append( const chr cData )
135 {
136 append( &cData, 1 );
137 }
138
134 void prepend( const chr *pData ) 139 void prepend( const chr *pData )
135 { 140 {
136 long nLen; 141 long nLen;
@@ -231,8 +236,7 @@ namespace Bu
231 236
232 MyType &operator +=( const chr pData ) 237 MyType &operator +=( const chr pData )
233 { 238 {
234 chr tmp[2] = { pData, (chr)0 }; 239 append( &pData, 1 );
235 append( tmp );
236 240
237 return (*this); 241 return (*this);
238 } 242 }
@@ -475,7 +479,7 @@ namespace Bu
475 } 479 }
476 } 480 }
477 481
478 void copyFrom( const FBasicString<chr, chralloc, chunkalloc> &rSrc ) 482 void copyFrom( const FBasicString<chr, nMinSize, chralloc, chunkalloc> &rSrc )
479 { 483 {
480 if( rSrc.pFirst == NULL ) 484 if( rSrc.pFirst == NULL )
481 return; 485 return;
diff --git a/src/list.cpp b/src/list.cpp
new file mode 100644
index 0000000..abe92ad
--- /dev/null
+++ b/src/list.cpp
@@ -0,0 +1,2 @@
1#include "bu/list.h"
2
diff --git a/src/list.h b/src/list.h
new file mode 100644
index 0000000..ec63496
--- /dev/null
+++ b/src/list.h
@@ -0,0 +1,176 @@
1#ifndef LIST_H
2#define LIST_H
3
4#include <memory>
5#include "bu/exceptionbase.h"
6
7namespace Bu
8{
9 template<typename value>
10 struct ListLink
11 {
12 value *pValue;
13 ListLink *pNext;
14 ListLink *pPrev;
15 };
16 template<typename value, typename valuealloc=std::allocator<value>, typename linkalloc=std::allocator<struct ListLink<value> > >
17 class List
18 {
19 private:
20 typedef struct ListLink<value> Link;
21 typedef class List<value, valuealloc, linkalloc> MyType;
22
23 public:
24 List() :
25 pFirst( NULL ),
26 pLast( NULL )
27 {
28 }
29
30 void append( value v )
31 {
32 Link *pNew = la.allocate( sizeof( Link ) );
33 pNew->pValue = va.allocate( sizeof( value ) );
34 va.construct( pNew->pValue, v );
35 if( pFirst == NULL )
36 {
37 // Empty list
38 pFirst = pLast = pNew;
39 pNew->pNext = pNew->pPrev = NULL;
40 }
41 else
42 {
43 pNew->pNext = NULL;
44 pNew->pPrev = pLast;
45 pLast->pNext = pNew;
46 pLast = pNew;
47 }
48 }
49
50 void prepend( value v )
51 {
52 Link *pNew = la.allocate( sizeof( Link ) );
53 pNew->pValue = va.allocate( sizeof( value ) );
54 va.construct( pNew->pValue, v );
55 if( pFirst == NULL )
56 {
57 // Empty list
58 pFirst = pLast = pNew;
59 pNew->pNext = pNew->pPrev = NULL;
60 }
61 else
62 {
63 pNew->pNext = pFirst;
64 pNew->pPrev = NULL;
65 pFirst->pPrev = pNew;
66 pFirst = pNew;
67 }
68 }
69
70 typedef struct iterator
71 {
72 friend class List<value, valuealloc, linkalloc>;
73 private:
74 Link *pLink;
75 iterator() :
76 pLink( NULL )
77 {
78 }
79
80 iterator( Link *pLink ) :
81 pLink( pLink )
82 {
83 }
84
85 public:
86 bool operator==( const iterator &oth )
87 {
88 return ( pLink == oth.pLink );
89 }
90
91 bool operator==( const Link *pOth )
92 {
93 return ( pLink == pOth );
94 }
95
96 bool operator!=( const iterator &oth )
97 {
98 return ( pLink != oth.pLink );
99 }
100
101 bool operator!=( const Link *pOth )
102 {
103 return ( pLink != pOth );
104 }
105
106 value &operator*()
107 {
108 return *(pLink->pValue);
109 }
110
111 value *operator->()
112 {
113 return pLink->pValue();
114 }
115
116 iterator operator++()
117 {
118 if( pLink != NULL )
119 pLink = pLink->pNext;
120 return *this;
121 }
122
123 iterator operator--()
124 {
125 if( pLink != NULL )
126 pLink = pLink->pPrev;
127 return *this;
128 }
129
130 iterator operator++( int )
131 {
132 if( pLink != NULL )
133 pLink = pLink->pNext;
134 return *this;
135 }
136
137 iterator operator--( int )
138 {
139 if( pLink != NULL )
140 pLink = pLink->pPrev;
141 return *this;
142 }
143
144 iterator operator=( const iterator &oth )
145 {
146 pLink = oth.pLink;
147 }
148 };
149
150 iterator begin()
151 {
152 return iterator( pFirst );
153 }
154
155 const Link *end()
156 {
157 return NULL;
158 }
159
160 int getSize()
161 {
162 int j = 0;
163 for( Link *pCur = pFirst; pCur; pCur = pCur->pNext )
164 j++;
165 return j;
166 }
167
168 private:
169 Link *pFirst;
170 Link *pLast;
171 linkalloc la;
172 valuealloc va;
173 };
174}
175
176#endif
diff --git a/src/tests/list.cpp b/src/tests/list.cpp
new file mode 100644
index 0000000..34ab656
--- /dev/null
+++ b/src/tests/list.cpp
@@ -0,0 +1,22 @@
1#include "bu/list.h"
2
3int main()
4{
5 Bu::List<int> l;
6
7 l.append( 0 );
8
9 for( int j = 3; j <= 21; j += 3 )
10 {
11 l.append( j );
12 l.prepend( -j );
13 }
14
15 for( Bu::List<int>::iterator i = l.begin(); i != l.end(); i++ )
16 {
17 printf("%d ", *i );
18 }
19
20 printf("\n\n");
21}
22
diff --git a/src/tests/xml.cpp b/src/tests/xml.cpp
index 9ef6a7e..9689a28 100644
--- a/src/tests/xml.cpp
+++ b/src/tests/xml.cpp
@@ -6,9 +6,9 @@
6int main() 6int main()
7{ 7{
8 Bu::File f("test.xml", "r"); 8 Bu::File f("test.xml", "r");
9 Bu::XmlReader xr( f ); 9 XmlReader xr( f );
10 10
11 xr.read(); 11 //xr.read();
12 12
13 return 0; 13 return 0;
14} 14}
diff --git a/src/xmldocument.cpp b/src/xmldocument.cpp
index d7867d5..95b9788 100644
--- a/src/xmldocument.cpp
+++ b/src/xmldocument.cpp
@@ -1,6 +1,6 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include "xmlwriter.h" 3#include "xmldocument.h"
4 4
5XmlDocument::XmlDocument( XmlNode *pRoot ) 5XmlDocument::XmlDocument( XmlNode *pRoot )
6{ 6{
@@ -17,28 +17,23 @@ XmlDocument::~XmlDocument()
17 } 17 }
18} 18}
19 19
20void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) 20void XmlDocument::addNode( const Bu::FString &sName )
21{ 21{
22 if( pRoot == NULL ) 22 if( pRoot == NULL )
23 { 23 {
24 // This is the first node, so ignore position and just insert it. 24 // This is the first node, so ignore position and just insert it.
25 pCurrent = pRoot = new XmlNode( sName, NULL, sContent ); 25 pCurrent = pRoot = new XmlNode( sName );
26 } 26 }
27 else 27 else
28 { 28 {
29 pCurrent = pCurrent->addChild( sName, sContent ); 29 pCurrent = pCurrent->addChild( sName );
30 }
31
32 if( bClose )
33 {
34 closeNode();
35 } 30 }
36} 31}
37 32/*
38void XmlDocument::setName( const char *sName ) 33void XmlDocument::setName( const char *sName )
39{ 34{
40 pCurrent->setName( sName ); 35 pCurrent->setName( sName );
41} 36}*/
42 37
43bool XmlDocument::isCompleted() 38bool XmlDocument::isCompleted()
44{ 39{
@@ -143,7 +138,8 @@ void XmlDocument::setContent( const char *sContent )
143{ 138{
144 if( pCurrent ) 139 if( pCurrent )
145 { 140 {
146 pCurrent->setContent( sContent ); 141 printf("XmlDocument::setContent: not yet implemented.\n");
142 //pCurrent->setContent( sContent );
147 } 143 }
148} 144}
149 145
diff --git a/src/xmldocument.h b/src/xmldocument.h
index 6671c41..e0c36eb 100644
--- a/src/xmldocument.h
+++ b/src/xmldocument.h
@@ -39,13 +39,7 @@ public:
39 * the node and setting the content and name. If this is set to true the 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. 40 * node is appended, but the context node doesn't change.
41 */ 41 */
42 void addNode( const char *sName=NULL, const char *sContent=NULL, bool bClose=false ); 42 void addNode( const Bu::FString &sName );
43
44 /**
45 * Set the name of the current node context.
46 *@param sName The new name of the node.
47 */
48 void setName( const char *sName );
49 43
50 /** 44 /**
51 * Close the current node context. This will move the current context to 45 * Close the current node context. This will move the current context to
diff --git a/src/xmlnode.cpp b/src/xmlnode.cpp
index b1ed9a9..96d5850 100644
--- a/src/xmlnode.cpp
+++ b/src/xmlnode.cpp
@@ -1,53 +1,15 @@
1#include "xmlnode.h" 1#include "xmlnode.h"
2#include "hashfunctionstring.h"
3 2
4XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : 3XmlNode::XmlNode( const Bu::FString &sName, XmlNode *pParent ) :
5 hProperties( new HashFunctionString(), 53, false ), 4 sName( sName ),
6 hChildren( new HashFunctionString(), 53, true ) 5 pParent( pParent )
7{ 6{
8 this->pParent = pParent;
9 if( sName != NULL )
10 {
11 setName( sName );
12 }
13 if( sContent != NULL )
14 {
15 this->sPreContent = new std::string( sContent );
16 }
17 else
18 {
19 this->sPreContent = NULL;
20 }
21 nCurContent = 0;
22} 7}
23 8
24XmlNode::~XmlNode() 9XmlNode::~XmlNode()
25{ 10{
26 for( int j = 0; j < lChildren.getSize(); j++ )
27 {
28 delete (XmlNode *)lChildren[j];
29 }
30 for( int j = 0; j < lPropNames.getSize(); j++ )
31 {
32 delete (std::string *)lPropNames[j];
33 }
34 for( int j = 0; j < lPropValues.getSize(); j++ )
35 {
36 delete (std::string *)lPropValues[j];
37 }
38 for( int j = 0; j < lPostContent.getSize(); j++ )
39 {
40 if( lPostContent[j] != NULL )
41 {
42 delete (std::string *)lPostContent[j];
43 }
44 }
45 if( sPreContent )
46 {
47 delete sPreContent;
48 }
49} 11}
50 12/*
51void XmlNode::setName( const char *sName ) 13void XmlNode::setName( const char *sName )
52{ 14{
53 if( pParent ) 15 if( pParent )
@@ -120,18 +82,18 @@ const char *XmlNode::getContent( int nIndex )
120 } 82 }
121 83
122 return NULL; 84 return NULL;
123} 85}*/
124 86
125XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) 87XmlNode *XmlNode::addChild( const Bu::FString &sName )
126{ 88{
127 return addChild( new XmlNode( sName, this, sContent ) ); 89 return addChild( new XmlNode( sName, this ) );
128} 90}
129 91
130XmlNode *XmlNode::addChild( XmlNode *pNode ) 92XmlNode *XmlNode::addChild( XmlNode *pNode )
131{ 93{
132 lChildren.append( pNode ); 94 Child c = { typeNode };
133 lPostContent.append( NULL ); 95 c.pNode = pNode;
134 nCurContent++; 96 lChildren.append( c );
135 pNode->pParent = this; 97 pNode->pParent = this;
136 98
137 return pNode; 99 return pNode;
@@ -142,21 +104,16 @@ XmlNode *XmlNode::getParent()
142 return pParent; 104 return pParent;
143} 105}
144 106
145void XmlNode::addProperty( const char *sName, const char *sValue ) 107void XmlNode::addProperty( const Bu::FString &sName, const Bu::FString &sValue )
146{ 108{
147 std::string *pName = new std::string( sName ); 109 hProperties.insert( sName, sValue );
148 std::string *pValue = new std::string( sValue );
149
150 hProperties.insert( pName->c_str(), pValue->c_str() );
151 lPropNames.append( pName );
152 lPropValues.append( pValue );
153} 110}
154 111
155int XmlNode::getNumProperties() 112int XmlNode::getNumProperties()
156{ 113{
157 return lPropNames.getSize(); 114 return hProperties.size();
158} 115}
159 116/*
160const char *XmlNode::getPropertyName( int nIndex ) 117const char *XmlNode::getPropertyName( int nIndex )
161{ 118{
162 std::string *tmp = ((std::string *)lPropNames[nIndex]); 119 std::string *tmp = ((std::string *)lPropNames[nIndex]);
@@ -172,15 +129,12 @@ const char *XmlNode::getProperty( int nIndex )
172 return NULL; 129 return NULL;
173 return tmp->c_str(); 130 return tmp->c_str();
174} 131}
175 132*/
176const char *XmlNode::getProperty( const char *sName ) 133Bu::FString XmlNode::getProperty( const Bu::FString &sName )
177{ 134{
178 const char *tmp = (const char *)hProperties[sName]; 135 return hProperties[sName];
179 if( tmp == NULL )
180 return NULL;
181 return tmp;
182} 136}
183 137/*
184void XmlNode::deleteProperty( int nIndex ) 138void XmlNode::deleteProperty( int nIndex )
185{ 139{
186 hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); 140 hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() );
@@ -194,29 +148,33 @@ void XmlNode::deleteProperty( int nIndex )
194 148
195bool XmlNode::hasChildren() 149bool XmlNode::hasChildren()
196{ 150{
197 return lChildren.getSize()>0; 151 return hChildren.getSize()>0;
198} 152}*/
199 153
200int XmlNode::getNumChildren() 154int XmlNode::getNumChildren()
201{ 155{
202 return lChildren.getSize(); 156 return lChildren.getSize();
203} 157}
204 158/*
205XmlNode *XmlNode::getChild( int nIndex ) 159XmlNode *XmlNode::getChild( int nIndex )
206{ 160{
207 return (XmlNode *)lChildren[nIndex]; 161 return (XmlNode *)lChildren[nIndex];
208} 162}
209 163*/
210XmlNode *XmlNode::getChild( const char *sName, int nSkip ) 164XmlNode *XmlNode::getChild( const Bu::FString &sName, int nSkip )
211{ 165{
212 return (XmlNode *)hChildren.get( sName, nSkip ); 166 if( !hChildren.has( sName ) )
167 return NULL;
168
169 Bu::List<XmlNode *>::iterator i = hChildren[sName]->begin();
170 return *i;
213} 171}
214 172
215const char *XmlNode::getName() 173Bu::FString XmlNode::getName()
216{ 174{
217 return sName.c_str(); 175 return sName;
218} 176}
219 177/*
220void XmlNode::deleteNode( int nIndex, const char *sReplacementText ) 178void XmlNode::deleteNode( int nIndex, const char *sReplacementText )
221{ 179{
222 XmlNode *xRet = detatchNode( nIndex, sReplacementText ); 180 XmlNode *xRet = detatchNode( nIndex, sReplacementText );
@@ -442,4 +400,4 @@ void XmlNode::deleteNodeKeepChildren( int nIndex )
442void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) 400void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode )
443{ 401{
444} 402}
445 403*/
diff --git a/src/xmlnode.h b/src/xmlnode.h
index 7525306..c895cd8 100644
--- a/src/xmlnode.h
+++ b/src/xmlnode.h
@@ -2,8 +2,9 @@
2#define XMLNODE 2#define XMLNODE
3 3
4#include <iostream> 4#include <iostream>
5#include "linkedlist.h" 5#include "bu/list.h"
6#include "hashtable.h" 6#include "bu/hash.h"
7#include "bu/fstring.h"
7 8
8/** 9/**
9 * Maintains all data pertient to an XML node, including sub-nodes and content. 10 * Maintains all data pertient to an XML node, including sub-nodes and content.
@@ -25,9 +26,8 @@ public:
25 *@param sContent The initial content string. 26 *@param sContent The initial content string.
26 */ 27 */
27 XmlNode( 28 XmlNode(
28 const char *sName=NULL, 29 const Bu::FString &sName,
29 XmlNode *pParent = NULL, 30 XmlNode *pParent=NULL
30 const char *sContent=NULL
31 ); 31 );
32 32
33 /** 33 /**
@@ -39,7 +39,7 @@ public:
39 * Change the name of the node. 39 * Change the name of the node.
40 *@param sName The new name of the node. 40 *@param sName The new name of the node.
41 */ 41 */
42 void setName( const char *sName ); 42 //void setName( const char *sName );
43 43
44 /** 44 /**
45 * Construct a new node and add it as a child to this node, also return a 45 * Construct a new node and add it as a child to this node, also return a
@@ -48,7 +48,7 @@ public:
48 *@param sContent The initial content of the new node. 48 *@param sContent The initial content of the new node.
49 *@returns A pointer to the newly created child node. 49 *@returns A pointer to the newly created child node.
50 */ 50 */
51 XmlNode *addChild( const char *sName, const char *sContent=NULL ); 51 XmlNode *addChild( const Bu::FString &sName );
52 52
53 /** 53 /**
54 * Add an already created XmlNode as a child to this node. The new child 54 * Add an already created XmlNode as a child to this node. The new child
@@ -65,7 +65,7 @@ public:
65 * in use will overwrite that property. 65 * in use will overwrite that property.
66 *@param sValue The textual value of the property. 66 *@param sValue The textual value of the property.
67 */ 67 */
68 void addProperty( const char *sName, const char *sValue ); 68 void addProperty( const Bu::FString &sName, const Bu::FString &sValue );
69 69
70 /** 70 /**
71 * Get a pointer to the parent node, if any. 71 * Get a pointer to the parent node, if any.
@@ -86,14 +86,6 @@ public:
86 int getNumChildren(); 86 int getNumChildren();
87 87
88 /** 88 /**
89 * Get a child node at a specific index.
90 *@param nIndex The zero-based index of the child to retreive.
91 *@returns A pointer to the child, or NULL if you requested an invalid
92 * index.
93 */
94 XmlNode *getChild( int nIndex );
95
96 /**
97 * Get a child with the specified name, and possibly skip value. For an 89 * Get a child with the specified name, and possibly skip value. For an
98 * explination of skip values see the HashTable. 90 * explination of skip values see the HashTable.
99 *@param sName The name of the child to find. 91 *@param sName The name of the child to find.
@@ -101,14 +93,14 @@ public:
101 *@returns A pointer to the child, or NULL if no child with that name was 93 *@returns A pointer to the child, or NULL if no child with that name was
102 * found. 94 * found.
103 */ 95 */
104 XmlNode *getChild( const char *sName, int nSkip=0 ); 96 XmlNode *getChild( const Bu::FString &sName, int nSkip=0 );
105 97
106 /** 98 /**
107 * Get a pointer to the name of this node. Do not change this, use setName 99 * Get a pointer to the name of this node. Do not change this, use setName
108 * instead. 100 * instead.
109 *@returns A pointer to the name of this node. 101 *@returns A pointer to the name of this node.
110 */ 102 */
111 const char *getName(); 103 Bu::FString getName();
112 104
113 /** 105 /**
114 * Set the content of this node, optionally at a specific index. Using the 106 * Set the content of this node, optionally at a specific index. Using the
@@ -116,14 +108,7 @@ public:
116 *@param sContent The content string to use. 108 *@param sContent The content string to use.
117 *@param nIndex The index of the content. 109 *@param nIndex The index of the content.
118 */ 110 */
119 void setContent( const char *sContent, int nIndex=-1 ); 111 //void setContent( const char *sContent, int nIndex=-1 );
120
121 /**
122 * Get the content string at a given index, or zero for initial content.
123 *@param nIndex The index of the content.
124 *@returns A pointer to the content at that location.
125 */
126 const char *getContent( int nIndex = 0 );
127 112
128 /** 113 /**
129 * Get the number of properties in this node. 114 * Get the number of properties in this node.
@@ -132,36 +117,12 @@ public:
132 int getNumProperties(); 117 int getNumProperties();
133 118
134 /** 119 /**
135 * Get a property's name by index.
136 *@param nIndex The index of the property to examine.
137 *@returns A pointer to the name of the property specified, or NULL if none
138 * found.
139 */
140 const char *getPropertyName( int nIndex );
141
142 /**
143 * Get a proprty's value by index.
144 *@param nIndex The index of the property to examine.
145 *@returns A pointer to the value of the property specified, or NULL if none
146 * found.
147 */
148 const char *getProperty( int nIndex );
149
150 /**
151 * Get a propery's value by name. 120 * Get a propery's value by name.
152 *@param sName The name of the property to examine. 121 *@param sName The name of the property to examine.
153 *@returns A pointer to the value of the property specified, or NULL if none 122 *@returns A pointer to the value of the property specified, or NULL if none
154 * found. 123 * found.
155 */ 124 */
156 const char *getProperty( const char *sName ); 125 Bu::FString getProperty( const Bu::FString &sName );
157
158 /**
159 * Delete a property by index.
160 *@param nIndex The index of the property to delete.
161 *@returns True if the property was found and deleted, false if it wasn't
162 * found.
163 */
164 void deleteProperty( int nIndex );
165 126
166 /** 127 /**
167 * Delete a child node, possibly replacing it with some text. This actually 128 * Delete a child node, possibly replacing it with some text. This actually
@@ -171,7 +132,7 @@ public:
171 *@returns True of the node was found, and deleted, false if it wasn't 132 *@returns True of the node was found, and deleted, false if it wasn't
172 * found. 133 * found.
173 */ 134 */
174 void deleteNode( int nIndex, const char *sReplacementText = NULL ); 135 //void deleteNode( int nIndex, const char *sReplacementText = NULL );
175 136
176 /** 137 /**
177 * Delete a given node, but move all of it's children and content up to 138 * Delete a given node, but move all of it's children and content up to
@@ -180,7 +141,7 @@ public:
180 *@param nIndex The node to delete. 141 *@param nIndex The node to delete.
181 *@returns True if the node was found and deleted, false if it wasn't. 142 *@returns True if the node was found and deleted, false if it wasn't.
182 */ 143 */
183 void deleteNodeKeepChildren( int nIndex ); 144 //void deleteNodeKeepChildren( int nIndex );
184 145
185 /** 146 /**
186 * Detatch a given child node from this node. This effectively works just 147 * Detatch a given child node from this node. This effectively works just
@@ -192,7 +153,7 @@ public:
192 *@returns A pointer to the newly detatched node, which then passes 153 *@returns A pointer to the newly detatched node, which then passes
193 * ownership to the caller. 154 * ownership to the caller.
194 */ 155 */
195 XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); 156 //XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL );
196 157
197 /** 158 /**
198 * Replace a given node with a different node that is not currently owned by 159 * Replace a given node with a different node that is not currently owned by
@@ -201,7 +162,7 @@ public:
201 *@param pNewNode The new node to replace the old node with. 162 *@param pNewNode The new node to replace the old node with.
202 *@returns True if the node was found and replaced, false if it wasn't. 163 *@returns True if the node was found and replaced, false if it wasn't.
203 */ 164 */
204 void replaceNode( int nIndex, XmlNode *pNewNode ); 165 //void replaceNode( int nIndex, XmlNode *pNewNode );
205 166
206 /** 167 /**
207 * Replace a given node with the children and content of a given node. 168 * Replace a given node with the children and content of a given node.
@@ -210,24 +171,34 @@ public:
210 * replace the node specified by nIndex. 171 * replace the node specified by nIndex.
211 *@returns True if the node was found and replaced, false if it wasn't. 172 *@returns True if the node was found and replaced, false if it wasn't.
212 */ 173 */
213 void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); 174 //void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode );
214 175
215 /** 176 /**
216 * Get a copy of this node and all children. getCopy is recursive, so 177 * Get a copy of this node and all children. getCopy is recursive, so
217 * beware copying large trees of xml. 178 * beware copying large trees of xml.
218 *@returns A newly created copy of this node and all of it's children. 179 *@returns A newly created copy of this node and all of it's children.
219 */ 180 */
220 XmlNode *getCopy(); 181 //XmlNode *getCopy();
182
183 enum ChildType
184 {
185 typeNode,
186 typeContent
187 };
221 188
222private: 189private:
223 std::string sName; /**< The name of the node. */ 190 typedef struct
224 std::string *sPreContent; /**< The content that goes before any node. */ 191 {
225 LinkedList lChildren; /**< The children. */ 192 uint8_t nType;
226 LinkedList lPostContent; /**< The content that comes after children. */ 193 union {
227 HashTable hProperties; /**< Property hashtable. */ 194 XmlNode *pNode;
228 HashTable hChildren; /**< Children hashtable. */ 195 Bu::FString *pContent;
229 LinkedList lPropNames; /**< List of property names. */ 196 };
230 LinkedList lPropValues; /**< List of property values. */ 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. */
231 XmlNode *pParent; /**< A pointer to the parent of this node. */ 202 XmlNode *pParent; /**< A pointer to the parent of this node. */
232 int nCurContent; /**< The current content we're on, for using the -1 on 203 int nCurContent; /**< The current content we're on, for using the -1 on
233 setContent. */ 204 setContent. */
diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp
index 18df69c..38cad5f 100644
--- a/src/xmlreader.cpp
+++ b/src/xmlreader.cpp
@@ -1,32 +1,49 @@
1#include "xmlreader.h" 1#include "bu/xmlreader.h"
2#include "exceptions.h" 2#include "bu/exceptions.h"
3#include <string.h> 3#include <string.h>
4#include "hashfunctionstring.h"
5 4
6XmlReader::XmlReader( bool bStrip ) : 5XmlReader::XmlReader( Bu::Stream &sIn, bool bStrip ) :
7 bStrip( bStrip ), 6 sIn( sIn ),
8 htEntity( new HashFunctionString(), 11 ) 7 bStrip( bStrip )
9{ 8{
9 buildDoc();
10} 10}
11 11
12XmlReader::~XmlReader() 12XmlReader::~XmlReader()
13{ 13{
14 void *i = htEntity.getFirstItemPos(); 14}
15 while( (i = htEntity.getNextItemPos( i ) ) ) 15
16char XmlReader::getChar( int nIndex )
17{
18 if( sBuf.getSize() <= nIndex )
16 { 19 {
17 free( (char *)(htEntity.getItemID( i )) ); 20 int nInc = nIndex-sBuf.getSize()+1;
18 delete (StaticString *)htEntity.getItemData( i ); 21 char *buf = new char[nInc];
22 sIn.read( buf, nInc );
23 sBuf.append( buf, nInc );
24 delete[] buf;
19 } 25 }
26
27 return sBuf[nIndex];
20} 28}
21 29
22void XmlReader::addEntity( const char *name, const char *value ) 30void XmlReader::usedChar( int nAmnt )
23{ 31{
24 if( htEntity[name] ) return; 32 if( nAmnt >= sBuf.getSize() )
25 33 {
26 char *sName = strdup( name ); 34 sBuf.clear();
27 StaticString *sValue = new StaticString( value ); 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}
28 43
29 htEntity.insert( sName, sValue ); 44void XmlReader::addEntity( const Bu::FString &name, const Bu::FString &value )
45{
46 htEntity[name] = value;
30} 47}
31 48
32#define gcall( x ) if( x == false ) return false; 49#define gcall( x ) if( x == false ) return false;
@@ -99,7 +116,7 @@ void XmlReader::entity()
99 { 116 {
100 usedChar( 2 ); 117 usedChar( 2 );
101 ws(); 118 ws();
102 std::string buf; 119 Bu::FString buf;
103 for(;;) 120 for(;;)
104 { 121 {
105 char chr = getChar(); 122 char chr = getChar();
@@ -111,7 +128,7 @@ void XmlReader::entity()
111 if( strcmp( buf.c_str(), "ENTITY") == 0 ) 128 if( strcmp( buf.c_str(), "ENTITY") == 0 )
112 { 129 {
113 ws(); 130 ws();
114 std::string name; 131 Bu::FString name;
115 for(;;) 132 for(;;)
116 { 133 {
117 char chr = getChar(); 134 char chr = getChar();
@@ -124,21 +141,19 @@ void XmlReader::entity()
124 usedChar(); 141 usedChar();
125 if( quot != '\'' && quot != '\"' ) 142 if( quot != '\'' && quot != '\"' )
126 { 143 {
127 throw XmlException( 144 throw Bu::XmlException(
128 "Only quoted entity values are supported." 145 "Only quoted entity values are supported."
129 ); 146 );
130 } 147 }
131 std::string value; 148 Bu::FString value;
132 for(;;) 149 for(;;)
133 { 150 {
134 char chr = getChar(); 151 char chr = getChar();
135 usedChar(); 152 usedChar();
136 if( chr == '&' ) 153 if( chr == '&' )
137 { 154 {
138 StaticString *tmp = getEscape(); 155 Bu::FString tmp = getEscape();
139 if( tmp == NULL ) throw XmlException("Entity thing"); 156 value += tmp;
140 value += tmp->getString();
141 delete tmp;
142 } 157 }
143 else if( chr == quot ) 158 else if( chr == quot )
144 { 159 {
@@ -158,7 +173,7 @@ void XmlReader::entity()
158 } 173 }
159 else 174 else
160 { 175 {
161 throw XmlException( 176 throw Bu::XmlException(
162 "Malformed ENTITY: unexpected '%c' found.", 177 "Malformed ENTITY: unexpected '%c' found.",
163 getChar() 178 getChar()
164 ); 179 );
@@ -166,7 +181,7 @@ void XmlReader::entity()
166 } 181 }
167 else 182 else
168 { 183 {
169 throw XmlException( 184 throw Bu::XmlException(
170 "Unsupported header symbol: %s", 185 "Unsupported header symbol: %s",
171 buf.c_str() 186 buf.c_str()
172 ); 187 );
@@ -203,12 +218,12 @@ bool XmlReader::node()
203 } 218 }
204 else 219 else
205 { 220 {
206 throw XmlException("Close node in singleNode malformed!"); 221 throw Bu::XmlException("Close node in singleNode malformed!");
207 } 222 }
208 } 223 }
209 else 224 else
210 { 225 {
211 throw XmlException("Close node expected, but not found."); 226 throw Bu::XmlException("Close node expected, but not found.");
212 return false; 227 return false;
213 } 228 }
214 229
@@ -224,7 +239,7 @@ bool XmlReader::startNode()
224 if( getChar() == '/' ) 239 if( getChar() == '/' )
225 { 240 {
226 // Heh, it's actually a close node, go figure 241 // Heh, it's actually a close node, go figure
227 FlexBuf fbName; 242 Bu::FString sName;
228 usedChar(); 243 usedChar();
229 gcall( ws() ); 244 gcall( ws() );
230 245
@@ -235,19 +250,19 @@ bool XmlReader::startNode()
235 { 250 {
236 // Here we actually compare the name we got to the name 251 // Here we actually compare the name we got to the name
237 // we already set, they have to match exactly. 252 // we already set, they have to match exactly.
238 if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) 253 if( getCurrent()->getName() == sName )
239 { 254 {
240 closeNode(); 255 closeNode();
241 break; 256 break;
242 } 257 }
243 else 258 else
244 { 259 {
245 throw XmlException("Got a mismatched node close tag."); 260 throw Bu::XmlException("Got a mismatched node close tag.");
246 } 261 }
247 } 262 }
248 else 263 else
249 { 264 {
250 fbName.appendData( chr ); 265 sName += chr;
251 usedChar(); 266 usedChar();
252 } 267 }
253 } 268 }
@@ -260,13 +275,13 @@ bool XmlReader::startNode()
260 } 275 }
261 else 276 else
262 { 277 {
263 throw XmlException("Got extra junk data instead of node close tag."); 278 throw Bu::XmlException("Got extra junk data instead of node close tag.");
264 } 279 }
265 } 280 }
266 else 281 else
267 { 282 {
268 // We're good, format is consistant 283 // We're good, format is consistant
269 addNode(); 284 //addNode();
270 285
271 // Skip extra whitespace 286 // Skip extra whitespace
272 gcall( ws() ); 287 gcall( ws() );
@@ -278,7 +293,7 @@ bool XmlReader::startNode()
278 } 293 }
279 else 294 else
280 { 295 {
281 throw XmlException("Expected to find node opening char, '<'."); 296 throw Bu::XmlException("Expected to find node opening char, '<'.");
282 } 297 }
283 298
284 return true; 299 return true;
@@ -286,19 +301,19 @@ bool XmlReader::startNode()
286 301
287bool XmlReader::name() 302bool XmlReader::name()
288{ 303{
289 FlexBuf fbName; 304 Bu::FString sName;
290 305
291 while( true ) 306 while( true )
292 { 307 {
293 char chr = getChar(); 308 char chr = getChar();
294 if( isws( chr ) || chr == '>' || chr == '/' ) 309 if( isws( chr ) || chr == '>' || chr == '/' )
295 { 310 {
296 setName( fbName.getData() ); 311 addNode( sName );
297 return true; 312 return true;
298 } 313 }
299 else 314 else
300 { 315 {
301 fbName.appendData( chr ); 316 sName += chr;
302 usedChar(); 317 usedChar();
303 } 318 }
304 } 319 }
@@ -325,7 +340,7 @@ bool XmlReader::paramlist()
325 return true; 340 return true;
326} 341}
327 342
328StaticString *XmlReader::getEscape() 343Bu::FString XmlReader::getEscape()
329{ 344{
330 if( getChar( 1 ) == '#' ) 345 if( getChar( 1 ) == '#' )
331 { 346 {
@@ -349,12 +364,12 @@ StaticString *XmlReader::getEscape()
349 buf[0] = (char)strtol( buf, (char **)NULL, base ); 364 buf[0] = (char)strtol( buf, (char **)NULL, base );
350 buf[1] = '\0'; 365 buf[1] = '\0';
351 366
352 return new StaticString( buf ); 367 return buf;
353 } 368 }
354 else 369 else
355 { 370 {
356 // ...otherwise replace with the appropriate string... 371 // ...otherwise replace with the appropriate string...
357 std::string buf; 372 Bu::FString buf;
358 usedChar(); 373 usedChar();
359 for(;;) 374 for(;;)
360 { 375 {
@@ -364,18 +379,14 @@ StaticString *XmlReader::getEscape()
364 buf += cbuf; 379 buf += cbuf;
365 } 380 }
366 381
367 StaticString *tmp = (StaticString *)htEntity[buf.c_str()]; 382 return htEntity[buf];
368 if( tmp == NULL ) return NULL;
369
370 StaticString *ret = new StaticString( *tmp );
371 return ret;
372 } 383 }
373} 384}
374 385
375bool XmlReader::param() 386bool XmlReader::param()
376{ 387{
377 FlexBuf fbName; 388 Bu::FString sName;
378 FlexBuf fbValue; 389 Bu::FString sValue;
379 390
380 while( true ) 391 while( true )
381 { 392 {
@@ -386,7 +397,7 @@ bool XmlReader::param()
386 } 397 }
387 else 398 else
388 { 399 {
389 fbName.appendData( chr ); 400 sName.append( chr );
390 usedChar(); 401 usedChar();
391 } 402 }
392 } 403 }
@@ -411,21 +422,18 @@ bool XmlReader::param()
411 if( chr == '"' ) 422 if( chr == '"' )
412 { 423 {
413 usedChar(); 424 usedChar();
414 addProperty( fbName.getData(), fbValue.getData() ); 425 addProperty( sName.getStr(), sValue.getStr() );
415 return true; 426 return true;
416 } 427 }
417 else 428 else
418 { 429 {
419 if( chr == '&' ) 430 if( chr == '&' )
420 { 431 {
421 StaticString *tmp = getEscape(); 432 sValue += getEscape();
422 if( tmp == NULL ) return false;
423 fbValue.appendData( tmp->getString() );
424 delete tmp;
425 } 433 }
426 else 434 else
427 { 435 {
428 fbValue.appendData( chr ); 436 sValue += chr;
429 usedChar(); 437 usedChar();
430 } 438 }
431 } 439 }
@@ -439,21 +447,18 @@ bool XmlReader::param()
439 chr = getChar(); 447 chr = getChar();
440 if( isws( chr ) || chr == '/' || chr == '>' ) 448 if( isws( chr ) || chr == '/' || chr == '>' )
441 { 449 {
442 addProperty( fbName.getData(), fbValue.getData() ); 450 addProperty( sName.getStr(), sValue.getStr() );
443 return true; 451 return true;
444 } 452 }
445 else 453 else
446 { 454 {
447 if( chr == '&' ) 455 if( chr == '&' )
448 { 456 {
449 StaticString *tmp = getEscape(); 457 sValue += getEscape();
450 if( tmp == NULL ) return false;
451 fbValue.appendData( tmp->getString() );
452 delete tmp;
453 } 458 }
454 else 459 else
455 { 460 {
456 fbValue.appendData( chr ); 461 sValue += chr;
457 usedChar(); 462 usedChar();
458 } 463 }
459 } 464 }
@@ -462,7 +467,7 @@ bool XmlReader::param()
462 } 467 }
463 else 468 else
464 { 469 {
465 throw XmlException("Expected an equals to seperate the params."); 470 throw Bu::XmlException("Expected an equals to seperate the params.");
466 return false; 471 return false;
467 } 472 }
468 473
@@ -471,7 +476,7 @@ bool XmlReader::param()
471 476
472bool XmlReader::content() 477bool XmlReader::content()
473{ 478{
474 FlexBuf fbContent; 479 Bu::FString sContent;
475 480
476 if( bStrip ) gcall( ws() ); 481 if( bStrip ) gcall( ws() );
477 482
@@ -482,37 +487,37 @@ bool XmlReader::content()
482 { 487 {
483 if( getChar(1) == '/' ) 488 if( getChar(1) == '/' )
484 { 489 {
485 if( fbContent.getLength() > 0 ) 490 if( sContent.getSize() > 0 )
486 { 491 {
487 if( bStrip ) 492 if( bStrip )
488 { 493 {
489 int j; 494 int j;
490 for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); 495 for( j = sContent.getSize()-1; isws(sContent[j]); j-- );
491 ((char *)fbContent.getData())[j+1] = '\0'; 496 sContent[j+1] = '\0';
492 } 497 }
493 setContent( fbContent.getData() ); 498 setContent( sContent.getStr() );
494 } 499 }
495 usedChar( 2 ); 500 usedChar( 2 );
496 gcall( ws() ); 501 gcall( ws() );
497 FlexBuf fbName; 502 Bu::FString sName;
498 while( true ) 503 while( true )
499 { 504 {
500 chr = getChar(); 505 chr = getChar();
501 if( isws( chr ) || chr == '>' ) 506 if( isws( chr ) || chr == '>' )
502 { 507 {
503 if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) 508 if( !strcasecmp( getCurrent()->getName().getStr(), sName.getStr() ) )
504 { 509 {
505 closeNode(); 510 closeNode();
506 break; 511 break;
507 } 512 }
508 else 513 else
509 { 514 {
510 throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() ); 515 throw Bu::XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName().getStr(), sName.getStr() );
511 } 516 }
512 } 517 }
513 else 518 else
514 { 519 {
515 fbName.appendData( chr ); 520 sName += chr;
516 usedChar(); 521 usedChar();
517 } 522 }
518 } 523 }
@@ -524,7 +529,7 @@ bool XmlReader::content()
524 } 529 }
525 else 530 else
526 { 531 {
527 throw XmlException("Malformed close tag."); 532 throw Bu::XmlException("Malformed close tag.");
528 } 533 }
529 } 534 }
530 else if( getChar(1) == '!' ) 535 else if( getChar(1) == '!' )
@@ -534,7 +539,7 @@ bool XmlReader::content()
534 getChar(3) != '-' ) 539 getChar(3) != '-' )
535 { 540 {
536 // Not a valid XML comment 541 // Not a valid XML comment
537 throw XmlException("Malformed comment start tag found."); 542 throw Bu::XmlException("Malformed comment start tag found.");
538 } 543 }
539 544
540 usedChar( 4 ); 545 usedChar( 4 );
@@ -549,7 +554,7 @@ bool XmlReader::content()
549 // The next one has to be a '>' now 554 // The next one has to be a '>' now
550 if( getChar( 2 ) != '>' ) 555 if( getChar( 2 ) != '>' )
551 { 556 {
552 throw XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment."); 557 throw Bu::XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment.");
553 } 558 }
554 usedChar( 3 ); 559 usedChar( 3 );
555 break; 560 break;
@@ -569,16 +574,16 @@ bool XmlReader::content()
569 } 574 }
570 else 575 else
571 { 576 {
572 if( fbContent.getLength() > 0 ) 577 if( sContent.getSize() > 0 )
573 { 578 {
574 if( bStrip ) 579 if( bStrip )
575 { 580 {
576 int j; 581 int j;
577 for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); 582 for( j = sContent.getSize()-1; isws(sContent[j]); j-- );
578 ((char *)fbContent.getData())[j+1] = '\0'; 583 sContent[j+1] = '\0';
579 } 584 }
580 setContent( fbContent.getData() ); 585 setContent( sContent.getStr() );
581 fbContent.clearData(); 586 sContent.clear();
582 } 587 }
583 gcall( node() ); 588 gcall( node() );
584 } 589 }
@@ -587,14 +592,11 @@ bool XmlReader::content()
587 } 592 }
588 else if( chr == '&' ) 593 else if( chr == '&' )
589 { 594 {
590 StaticString *tmp = getEscape(); 595 sContent += getEscape();
591 if( tmp == NULL ) return false;
592 fbContent.appendData( tmp->getString() );
593 delete tmp;
594 } 596 }
595 else 597 else
596 { 598 {
597 fbContent.appendData( chr ); 599 sContent += chr;
598 usedChar(); 600 usedChar();
599 } 601 }
600 } 602 }
diff --git a/src/xmlreader.h b/src/xmlreader.h
index c8f7202..7c85ddb 100644
--- a/src/xmlreader.h
+++ b/src/xmlreader.h
@@ -2,10 +2,10 @@
2#define XMLREADER 2#define XMLREADER
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include "xmldocument.h" 5#include "bu/xmldocument.h"
6#include "flexbuf.h" 6#include "bu/hash.h"
7#include "hashtable.h" 7#include "bu/fstring.h"
8#include "staticstring.h" 8#include "bu/stream.h"
9 9
10/** 10/**
11 * Takes care of reading in xml formatted data from a file. This could/should 11 * Takes care of reading in xml formatted data from a file. This could/should
@@ -32,7 +32,7 @@ public:
32 * in content, a-la html. 32 * in content, a-la html.
33 *@param bStrip Strip out leading and trailing whitespace? 33 *@param bStrip Strip out leading and trailing whitespace?
34 */ 34 */
35 XmlReader( bool bStrip=false ); 35 XmlReader( Bu::Stream &sIn, bool bStrip=false );
36 36
37 /** 37 /**
38 * Destroy this XmlReader. 38 * Destroy this XmlReader.
@@ -54,12 +54,12 @@ private:
54 *@returns A single character at the requested position, or 0 for end of 54 *@returns A single character at the requested position, or 0 for end of
55 * stream. 55 * stream.
56 */ 56 */
57 virtual char getChar( int nIndex = 0 ) = 0; 57 virtual char getChar( int nIndex = 0 );
58 58
59 /** 59 /**
60 * Called to increment the current stream position by a single character. 60 * Called to increment the current stream position by a single character.
61 */ 61 */
62 virtual void usedChar( int nAmnt = 1) = 0; 62 virtual void usedChar( int nAmnt = 1 );
63 63
64 /** 64 /**
65 * Automoton function: is whitespace. 65 * Automoton function: is whitespace.
@@ -108,9 +108,9 @@ private:
108 *@param name The name of the entity 108 *@param name The name of the entity
109 *@param value The value of the entity 109 *@param value The value of the entity
110 */ 110 */
111 void addEntity( const char *name, const char *value ); 111 void addEntity( const Bu::FString &name, const Bu::FString &value );
112 112
113 StaticString *getEscape(); 113 Bu::FString getEscape();
114 114
115 /** 115 /**
116 * Automoton function: paramlist. Processes a list of node params. 116 * Automoton function: paramlist. Processes a list of node params.
@@ -130,12 +130,15 @@ private:
130 */ 130 */
131 bool content(); 131 bool content();
132 132
133 FlexBuf fbContent; /**< buffer for the current node's content. */ 133 Bu::FString sContent; /**< buffer for the current node's content. */
134 FlexBuf fbParamName; /**< buffer for the current param's name. */ 134 Bu::FString sParamName; /**< buffer for the current param's name. */
135 FlexBuf fbParamValue; /**< buffer for the current param's value. */ 135 Bu::FString sParamValue; /**< buffer for the current param's value. */
136 bool bStrip; /**< Are we stripping whitespace? */ 136 Bu::Stream &sIn;
137 bool bStrip; /**< Are we stripping whitespace? */
137 138
138 HashTable htEntity; /**< Entity type definitions. */ 139 Bu::Hash<Bu::FString,Bu::FString> htEntity; /**< Entity type definitions. */
140
141 Bu::FString sBuf;
139}; 142};
140 143
141#endif 144#endif
diff --git a/src/xmlwriter.cpp b/src/xmlwriter.cpp
index 56880b6..7dc6ca9 100644
--- a/src/xmlwriter.cpp
+++ b/src/xmlwriter.cpp
@@ -2,17 +2,10 @@
2#include <stdlib.h> 2#include <stdlib.h>
3#include "xmlwriter.h" 3#include "xmlwriter.h"
4 4
5XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : 5XmlWriter::XmlWriter( const Bu::FString &sIndent, XmlNode *pRoot ) :
6 XmlDocument( pRoot ) 6 XmlDocument( pRoot ),
7 sIndent( sIndent )
7{ 8{
8 if( sIndent == NULL )
9 {
10 this->sIndent = "";
11 }
12 else
13 {
14 this->sIndent = sIndent;
15 }
16} 9}
17 10
18XmlWriter::~XmlWriter() 11XmlWriter::~XmlWriter()
@@ -24,7 +17,7 @@ void XmlWriter::write()
24 write( getRoot(), sIndent.c_str() ); 17 write( getRoot(), sIndent.c_str() );
25} 18}
26 19
27void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) 20void XmlWriter::write( XmlNode *pRoot, const Bu::FString &sIndent )
28{ 21{
29 writeNode( pRoot, 0, sIndent ); 22 writeNode( pRoot, 0, sIndent );
30} 23}
@@ -39,7 +32,7 @@ void XmlWriter::closeNode()
39 } 32 }
40} 33}
41 34
42void XmlWriter::writeIndent( int nIndent, const char *sIndent ) 35void XmlWriter::writeIndent( int nIndent, const Bu::FString &sIndent )
43{ 36{
44 if( sIndent == NULL ) return; 37 if( sIndent == NULL ) return;
45 for( int j = 0; j < nIndent; j++ ) 38 for( int j = 0; j < nIndent; j++ )
@@ -48,26 +41,27 @@ void XmlWriter::writeIndent( int nIndent, const char *sIndent )
48 } 41 }
49} 42}
50 43
51std::string XmlWriter::escape( std::string sIn ) 44Bu::FString XmlWriter::escape( const Bu::FString &sIn )
52{ 45{
53 std::string sOut; 46 Bu::FString sOut;
54 47
55 std::string::const_iterator i; 48 int nMax = sIn.getSize();
56 for( i = sIn.begin(); i != sIn.end(); i++ ) 49 for( int j = 0; j < nMax; j++ )
57 { 50 {
58 if( ((*i >= ' ' && *i <= '9') || 51 char c = sIn[j];
59 (*i >= 'a' && *i <= 'z') || 52 if( ((c >= ' ' && c <= '9') ||
60 (*i >= 'A' && *i <= 'Z') ) && 53 (c >= 'a' && c <= 'z') ||
61 (*i != '\"' && *i != '\'' && *i != '&') 54 (c >= 'A' && c <= 'Z') ) &&
55 (c != '\"' && c != '\'' && c != '&')
62 ) 56 )
63 { 57 {
64 sOut += *i; 58 sOut += c;
65 } 59 }
66 else 60 else
67 { 61 {
68 sOut += "&#"; 62 sOut += "&#";
69 char buf[4]; 63 char buf[4];
70 sprintf( buf, "%u", (unsigned char)*i ); 64 sprintf( buf, "%u", (unsigned char)c );
71 sOut += buf; 65 sOut += buf;
72 sOut += ';'; 66 sOut += ';';
73 } 67 }
@@ -76,19 +70,19 @@ std::string XmlWriter::escape( std::string sIn )
76 return sOut; 70 return sOut;
77} 71}
78 72
79void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) 73void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const Bu::FString &sIndent )
80{ 74{
81 for( int j = 0; j < pNode->getNumProperties(); j++ ) 75 for( int j = 0; j < pNode->getNumProperties(); j++ )
82 { 76 {
83 writeString(" "); 77 writeString(" ");
84 writeString( pNode->getPropertyName( j ) ); 78 //writeString( pNode->getPropertyName( j ) );
85 writeString("=\""); 79 writeString("=\"");
86 writeString( escape( pNode->getProperty( j ) ).c_str() ); 80 //writeString( escape( pNode->getProperty( j ) ).c_str() );
87 writeString("\""); 81 writeString("\"");
88 } 82 }
89} 83}
90 84
91void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) 85void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const Bu::FString &sIndent )
92{ 86{
93 if( pNode->hasChildren() ) 87 if( pNode->hasChildren() )
94 { 88 {
@@ -96,15 +90,15 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent )
96 writeString("<"); 90 writeString("<");
97 writeString( pNode->getName() ); 91 writeString( pNode->getName() );
98 writeNodeProps( pNode, nIndent, sIndent ); 92 writeNodeProps( pNode, nIndent, sIndent );
99 if( sIndent ) 93 if( sIndent != "" )
100 writeString(">\n"); 94 writeString(">\n");
101 else 95 else
102 writeString(">"); 96 writeString(">");
103 97/*
104 if( pNode->getContent( 0 ) ) 98 if( pNode->getContent( 0 ) )
105 { 99 {
106 writeIndent( nIndent+1, sIndent ); 100 writeIndent( nIndent+1, sIndent );
107 if( sIndent ) 101 if( sIndent != "" )
108 { 102 {
109 writeString( pNode->getContent( 0 ) ); 103 writeString( pNode->getContent( 0 ) );
110 writeString("\n"); 104 writeString("\n");
@@ -129,9 +123,9 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent )
129 writeString( pNode->getContent( j+1 ) ); 123 writeString( pNode->getContent( j+1 ) );
130 } 124 }
131 } 125 }
132 126*/
133 writeIndent( nIndent, sIndent ); 127 writeIndent( nIndent, sIndent );
134 if( sIndent ) 128 if( sIndent != "" )
135 { 129 {
136 writeString("</"); 130 writeString("</");
137 writeString( pNode->getName() ); 131 writeString( pNode->getName() );
@@ -143,7 +137,7 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent )
143 writeString( pNode->getName() ); 137 writeString( pNode->getName() );
144 writeString(">"); 138 writeString(">");
145 } 139 }
146 } 140 }/*
147 else if( pNode->getContent() ) 141 else if( pNode->getContent() )
148 { 142 {
149 writeIndent( nIndent, sIndent ); 143 writeIndent( nIndent, sIndent );
@@ -157,14 +151,14 @@ void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent )
157 writeString(">"); 151 writeString(">");
158 if( sIndent ) 152 if( sIndent )
159 writeString("\n"); 153 writeString("\n");
160 } 154 }*/
161 else 155 else
162 { 156 {
163 writeIndent( nIndent, sIndent ); 157 writeIndent( nIndent, sIndent );
164 writeString("<"); 158 writeString("<");
165 writeString( pNode->getName() ); 159 writeString( pNode->getName() );
166 writeNodeProps( pNode, nIndent, sIndent ); 160 writeNodeProps( pNode, nIndent, sIndent );
167 if( sIndent ) 161 if( sIndent != "" )
168 writeString("/>\n"); 162 writeString("/>\n");
169 else 163 else
170 writeString("/>"); 164 writeString("/>");
diff --git a/src/xmlwriter.h b/src/xmlwriter.h
index c48e810..7e3c876 100644
--- a/src/xmlwriter.h
+++ b/src/xmlwriter.h
@@ -31,7 +31,7 @@ public:
31 * this to a tab or some spaces it will never effect the content of your 31 * this to a tab or some spaces it will never effect the content of your
32 * file. 32 * file.
33 */ 33 */
34 XmlWriter( const char *sIndent=NULL, XmlNode *pRoot=NULL ); 34 XmlWriter( const Bu::FString &sIndent="", XmlNode *pRoot=NULL );
35 35
36 /** 36 /**
37 * Destroy the writer. 37 * Destroy the writer.
@@ -49,16 +49,16 @@ public:
49 void write(); 49 void write();
50 50
51private: 51private:
52 std::string sIndent; /**< The indent string */ 52 Bu::FString sIndent; /**< The indent string */
53 53
54 std::string escape( std::string sIn ); 54 Bu::FString escape( const Bu::FString &sIn );
55 55
56 /** 56 /**
57 * Write the file. 57 * Write the file.
58 *@param pNode The root node 58 *@param pNode The root node
59 *@param sIndent The indent text. 59 *@param sIndent The indent text.
60 */ 60 */
61 void write( XmlNode *pNode, const char *sIndent=NULL ); 61 void write( XmlNode *pNode, const Bu::FString &sIndent );
62 62
63 /** 63 /**
64 * Write a node in the file, including children. 64 * Write a node in the file, including children.
@@ -66,7 +66,7 @@ private:
66 *@param nIndent The indent level (the number of times to include sIndent) 66 *@param nIndent The indent level (the number of times to include sIndent)
67 *@param sIndent The indent text. 67 *@param sIndent The indent text.
68 */ 68 */
69 void writeNode( XmlNode *pNode, int nIndent, const char *sIndent ); 69 void writeNode( XmlNode *pNode, int nIndent, const Bu::FString &sIndent );
70 70
71 /** 71 /**
72 * Write the properties of a node. 72 * Write the properties of a node.
@@ -74,14 +74,14 @@ private:
74 *@param nIndent The indent level of the containing node 74 *@param nIndent The indent level of the containing node
75 *@param sIndent The indent text. 75 *@param sIndent The indent text.
76 */ 76 */
77 void writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ); 77 void writeNodeProps( XmlNode *pNode, int nIndent, const Bu::FString &sIndent );
78 78
79 /** 79 /**
80 * Called to write the actual indent. 80 * Called to write the actual indent.
81 *@param nIndent The indent level. 81 *@param nIndent The indent level.
82 *@param sIndent The indent text. 82 *@param sIndent The indent text.
83 */ 83 */
84 void writeIndent( int nIndent, const char *sIndent ); 84 void writeIndent( int nIndent, const Bu::FString &sIndent );
85 85
86 /** 86 /**
87 * This is the function that must be overridden in order to use this class. 87 * This is the function that must be overridden in order to use this class.
@@ -90,7 +90,7 @@ private:
90 * will break the XML formatting. 90 * will break the XML formatting.
91 *@param sString The string data to write to the output. 91 *@param sString The string data to write to the output.
92 */ 92 */
93 virtual void writeString( const char *sString ) = 0; 93 virtual void writeString( const Bu::FString &sString ) = 0;
94}; 94};
95 95
96#endif 96#endif