diff options
author | Mike Buland <eichlan@xagasoft.com> | 2007-05-11 07:51:40 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2007-05-11 07:51:40 +0000 |
commit | 033c41ed57348abb3a418166b1fb39bfad3312de (patch) | |
tree | 72edbb0b7ff35ef35e4d533bca384b4f7c986942 /src | |
parent | ad92dc50b7cdf7cfe086f21d19442d03a90fd05d (diff) | |
download | libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.tar.gz libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.tar.bz2 libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.tar.xz libbu++-033c41ed57348abb3a418166b1fb39bfad3312de.zip |
Added a list template class, seems to work pretty well for now, I may have
forgotten proper cleanup in the deconstructor, but besides that you can do
almost everything you need. I'll make a slist/stack next, probably with the
same basic code, just a different structure (not doubley-linked).
The xml system from old-libbu++ is almost completely converted, I was going to
re-write it, but this seemed easier at first, it may not have been, we'll see.
It almost parses everything again, and almost outputs again, and it does use
streams now.
The FString is partway to doing minimum chunk allocations, so that adding
single-characters will be really fast up to the minimum chunk size. I also
figured out how to add this optimization without any extra variables taking
up space, and it's optional in the template, which is cool. You can specify
the size of the blocks (default 256 bytes), if it's 0 then they'll be like the
old FString, 1 chunk per operation.
The next FString update should be allowing efficient removal from the begining
of the string by faking it, and simply moving a secondary base pointer ahead,
and then optimizing appends after that fact to simply move the existing data
around if you shouldn't have to re-allocate (alla FlexBuf). The final fun
addition that I'm planning is a simple switch in the template (boolean) that
will switch an FString into a thread-safe mode without changing the interface
or anything that you can do with them at all. It may increasing memory usage,
but they should still be better than std::strings, and totally thread-safe.
The best part of that is that if it's done with a boolean template parameter and
if statements that only test that parameter controlling flow, the code that you
don't want (threadsafe/non-threadsafe) won't be included at all
post-optimization.
Diffstat (limited to '')
-rw-r--r-- | src/fstring.h | 14 | ||||
-rw-r--r-- | src/list.cpp | 2 | ||||
-rw-r--r-- | src/list.h | 176 | ||||
-rw-r--r-- | src/tests/list.cpp | 22 | ||||
-rw-r--r-- | src/tests/xml.cpp | 6 | ||||
-rw-r--r-- | src/xmldocument.cpp | 20 | ||||
-rw-r--r-- | src/xmldocument.h | 8 | ||||
-rw-r--r-- | src/xmlnode.cpp | 106 | ||||
-rw-r--r-- | src/xmlnode.h | 101 | ||||
-rw-r--r-- | src/xmlreader.cpp | 170 | ||||
-rw-r--r-- | src/xmlreader.h | 31 | ||||
-rw-r--r-- | src/xmlwriter.cpp | 62 | ||||
-rw-r--r-- | src/xmlwriter.h | 16 |
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 | |||
7 | namespace 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 | |||
3 | int 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 @@ | |||
6 | int main() | 6 | int 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 | ||
5 | XmlDocument::XmlDocument( XmlNode *pRoot ) | 5 | XmlDocument::XmlDocument( XmlNode *pRoot ) |
6 | { | 6 | { |
@@ -17,28 +17,23 @@ XmlDocument::~XmlDocument() | |||
17 | } | 17 | } |
18 | } | 18 | } |
19 | 19 | ||
20 | void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) | 20 | void 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 | /* | |
38 | void XmlDocument::setName( const char *sName ) | 33 | void XmlDocument::setName( const char *sName ) |
39 | { | 34 | { |
40 | pCurrent->setName( sName ); | 35 | pCurrent->setName( sName ); |
41 | } | 36 | }*/ |
42 | 37 | ||
43 | bool XmlDocument::isCompleted() | 38 | bool 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 | ||
4 | XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : | 3 | XmlNode::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 | ||
24 | XmlNode::~XmlNode() | 9 | XmlNode::~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 | /* | |
51 | void XmlNode::setName( const char *sName ) | 13 | void 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 | ||
125 | XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) | 87 | XmlNode *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 | ||
130 | XmlNode *XmlNode::addChild( XmlNode *pNode ) | 92 | XmlNode *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 | ||
145 | void XmlNode::addProperty( const char *sName, const char *sValue ) | 107 | void 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 | ||
155 | int XmlNode::getNumProperties() | 112 | int XmlNode::getNumProperties() |
156 | { | 113 | { |
157 | return lPropNames.getSize(); | 114 | return hProperties.size(); |
158 | } | 115 | } |
159 | 116 | /* | |
160 | const char *XmlNode::getPropertyName( int nIndex ) | 117 | const 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 | */ | |
176 | const char *XmlNode::getProperty( const char *sName ) | 133 | Bu::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 | /* | |
184 | void XmlNode::deleteProperty( int nIndex ) | 138 | void 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 | ||
195 | bool XmlNode::hasChildren() | 149 | bool XmlNode::hasChildren() |
196 | { | 150 | { |
197 | return lChildren.getSize()>0; | 151 | return hChildren.getSize()>0; |
198 | } | 152 | }*/ |
199 | 153 | ||
200 | int XmlNode::getNumChildren() | 154 | int XmlNode::getNumChildren() |
201 | { | 155 | { |
202 | return lChildren.getSize(); | 156 | return lChildren.getSize(); |
203 | } | 157 | } |
204 | 158 | /* | |
205 | XmlNode *XmlNode::getChild( int nIndex ) | 159 | XmlNode *XmlNode::getChild( int nIndex ) |
206 | { | 160 | { |
207 | return (XmlNode *)lChildren[nIndex]; | 161 | return (XmlNode *)lChildren[nIndex]; |
208 | } | 162 | } |
209 | 163 | */ | |
210 | XmlNode *XmlNode::getChild( const char *sName, int nSkip ) | 164 | XmlNode *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 | ||
215 | const char *XmlNode::getName() | 173 | Bu::FString XmlNode::getName() |
216 | { | 174 | { |
217 | return sName.c_str(); | 175 | return sName; |
218 | } | 176 | } |
219 | 177 | /* | |
220 | void XmlNode::deleteNode( int nIndex, const char *sReplacementText ) | 178 | void 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 ) | |||
442 | void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) | 400 | void 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 | ||
222 | private: | 189 | private: |
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 | ||
6 | XmlReader::XmlReader( bool bStrip ) : | 5 | XmlReader::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 | ||
12 | XmlReader::~XmlReader() | 12 | XmlReader::~XmlReader() |
13 | { | 13 | { |
14 | void *i = htEntity.getFirstItemPos(); | 14 | } |
15 | while( (i = htEntity.getNextItemPos( i ) ) ) | 15 | |
16 | char 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 | ||
22 | void XmlReader::addEntity( const char *name, const char *value ) | 30 | void 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 ); | 44 | void 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 | ||
287 | bool XmlReader::name() | 302 | bool 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 | ||
328 | StaticString *XmlReader::getEscape() | 343 | Bu::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 | ||
375 | bool XmlReader::param() | 386 | bool 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 | ||
472 | bool XmlReader::content() | 477 | bool 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 | ||
5 | XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : | 5 | XmlWriter::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 | ||
18 | XmlWriter::~XmlWriter() | 11 | XmlWriter::~XmlWriter() |
@@ -24,7 +17,7 @@ void XmlWriter::write() | |||
24 | write( getRoot(), sIndent.c_str() ); | 17 | write( getRoot(), sIndent.c_str() ); |
25 | } | 18 | } |
26 | 19 | ||
27 | void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) | 20 | void 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 | ||
42 | void XmlWriter::writeIndent( int nIndent, const char *sIndent ) | 35 | void 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 | ||
51 | std::string XmlWriter::escape( std::string sIn ) | 44 | Bu::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 | ||
79 | void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) | 73 | void 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 | ||
91 | void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) | 85 | void 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 | ||
51 | private: | 51 | private: |
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 |