diff options
author | Mike Buland <eichlan@xagasoft.com> | 2006-05-01 17:11:04 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2006-05-01 17:11:04 +0000 |
commit | f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54 (patch) | |
tree | 53cec4864776e07950e3c72f2a990a1017d08045 /src/xmlnode.cpp | |
download | libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.gz libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.bz2 libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.tar.xz libbu++-f7a9549bd6ad83f2e0bceec9cddacfa5e3f84a54.zip |
libbu++ is finally laid out the way it should be, trunk, branches, and tags.
Diffstat (limited to 'src/xmlnode.cpp')
-rw-r--r-- | src/xmlnode.cpp | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/src/xmlnode.cpp b/src/xmlnode.cpp new file mode 100644 index 0000000..e5c77e2 --- /dev/null +++ b/src/xmlnode.cpp | |||
@@ -0,0 +1,454 @@ | |||
1 | #include "xmlnode.h" | ||
2 | #include "hashfunctionstring.h" | ||
3 | |||
4 | XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : | ||
5 | hProperties( new HashFunctionString(), 53, false ), | ||
6 | hChildren( new HashFunctionString(), 53, true ) | ||
7 | { | ||
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 | } | ||
23 | |||
24 | XmlNode::~XmlNode() | ||
25 | { | ||
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 | } | ||
50 | |||
51 | void XmlNode::setName( const char *sName ) | ||
52 | { | ||
53 | if( pParent ) | ||
54 | { | ||
55 | if( this->sName.size() == 0 ) | ||
56 | { | ||
57 | // We're not in the hash yet, so add us | ||
58 | this->sName = sName; | ||
59 | pParent->hChildren.insert( this->sName.c_str(), this ); | ||
60 | } | ||
61 | else | ||
62 | { | ||
63 | // Slightly more tricky, delete us, then add us... | ||
64 | pParent->hChildren.del( this->sName.c_str() ); | ||
65 | this->sName = sName; | ||
66 | pParent->hChildren.insert( this->sName.c_str(), this ); | ||
67 | } | ||
68 | } | ||
69 | else | ||
70 | { | ||
71 | // If we have no parent, then just set the name string, we don't need | ||
72 | // to worry about hashing. | ||
73 | this->sName = sName; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void XmlNode::setContent( const char *sContent, int nIndex ) | ||
78 | { | ||
79 | if( nIndex == -1 ) | ||
80 | { | ||
81 | nIndex = nCurContent; | ||
82 | } | ||
83 | if( nIndex == 0 ) | ||
84 | { | ||
85 | if( this->sPreContent ) | ||
86 | { | ||
87 | delete this->sPreContent; | ||
88 | } | ||
89 | |||
90 | this->sPreContent = new std::string( sContent ); | ||
91 | } | ||
92 | else | ||
93 | { | ||
94 | nIndex--; | ||
95 | if( lPostContent[nIndex] ) | ||
96 | { | ||
97 | delete (std::string *)lPostContent[nIndex]; | ||
98 | } | ||
99 | |||
100 | lPostContent.setAt( nIndex, new std::string( sContent ) ); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | const char *XmlNode::getContent( int nIndex ) | ||
105 | { | ||
106 | if( nIndex == 0 ) | ||
107 | { | ||
108 | if( sPreContent ) | ||
109 | { | ||
110 | return sPreContent->c_str(); | ||
111 | } | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | nIndex--; | ||
116 | if( lPostContent[nIndex] ) | ||
117 | { | ||
118 | return ((std::string *)lPostContent[nIndex])->c_str(); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) | ||
126 | { | ||
127 | return addChild( new XmlNode( sName, this, sContent ) ); | ||
128 | } | ||
129 | |||
130 | XmlNode *XmlNode::addChild( XmlNode *pNode ) | ||
131 | { | ||
132 | lChildren.append( pNode ); | ||
133 | lPostContent.append( NULL ); | ||
134 | nCurContent++; | ||
135 | pNode->pParent = this; | ||
136 | |||
137 | return pNode; | ||
138 | } | ||
139 | |||
140 | XmlNode *XmlNode::getParent() | ||
141 | { | ||
142 | return pParent; | ||
143 | } | ||
144 | |||
145 | void XmlNode::addProperty( const char *sName, const char *sValue ) | ||
146 | { | ||
147 | std::string *pName = new std::string( sName ); | ||
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 | } | ||
154 | |||
155 | int XmlNode::getNumProperties() | ||
156 | { | ||
157 | return lPropNames.getSize(); | ||
158 | } | ||
159 | |||
160 | const char *XmlNode::getPropertyName( int nIndex ) | ||
161 | { | ||
162 | std::string *tmp = ((std::string *)lPropNames[nIndex]); | ||
163 | if( tmp == NULL ) | ||
164 | return NULL; | ||
165 | return tmp->c_str(); | ||
166 | } | ||
167 | |||
168 | const char *XmlNode::getProperty( int nIndex ) | ||
169 | { | ||
170 | std::string *tmp = ((std::string *)lPropValues[nIndex]); | ||
171 | if( tmp == NULL ) | ||
172 | return NULL; | ||
173 | return tmp->c_str(); | ||
174 | } | ||
175 | |||
176 | const char *XmlNode::getProperty( const char *sName ) | ||
177 | { | ||
178 | const char *tmp = (const char *)hProperties[sName]; | ||
179 | if( tmp == NULL ) | ||
180 | return NULL; | ||
181 | return tmp; | ||
182 | } | ||
183 | |||
184 | bool XmlNode::deleteProperty( int nIndex ) | ||
185 | { | ||
186 | hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); | ||
187 | |||
188 | delete (std::string *)lPropNames[nIndex]; | ||
189 | delete (std::string *)lPropValues[nIndex]; | ||
190 | |||
191 | lPropNames.deleteAt( nIndex ); | ||
192 | lPropValues.deleteAt( nIndex ); | ||
193 | } | ||
194 | |||
195 | bool XmlNode::hasChildren() | ||
196 | { | ||
197 | return lChildren.getSize()>0; | ||
198 | } | ||
199 | |||
200 | int XmlNode::getNumChildren() | ||
201 | { | ||
202 | return lChildren.getSize(); | ||
203 | } | ||
204 | |||
205 | XmlNode *XmlNode::getChild( int nIndex ) | ||
206 | { | ||
207 | return (XmlNode *)lChildren[nIndex]; | ||
208 | } | ||
209 | |||
210 | XmlNode *XmlNode::getChild( const char *sName, int nSkip ) | ||
211 | { | ||
212 | return (XmlNode *)hChildren.get( sName, nSkip ); | ||
213 | } | ||
214 | |||
215 | const char *XmlNode::getName() | ||
216 | { | ||
217 | return sName.c_str(); | ||
218 | } | ||
219 | |||
220 | bool XmlNode::deleteNode( int nIndex, const char *sReplacementText ) | ||
221 | { | ||
222 | XmlNode *xRet = detatchNode( nIndex, sReplacementText ); | ||
223 | |||
224 | if( xRet == NULL ) | ||
225 | { | ||
226 | return false; | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | delete xRet; | ||
231 | return true; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | XmlNode *XmlNode::detatchNode( int nIndex, const char *sReplacementText ) | ||
236 | { | ||
237 | if( nIndex < 0 || nIndex >= lChildren.getSize() ) | ||
238 | return NULL; | ||
239 | |||
240 | // The real trick when deleteing a node isn't actually deleting it, it's | ||
241 | // reforming the content around the node that's now missing...hmmm... | ||
242 | |||
243 | if( nIndex == 0 ) | ||
244 | { | ||
245 | // If the index is zero we have to deal with the pre-content | ||
246 | if( sReplacementText ) | ||
247 | { | ||
248 | if( sPreContent == NULL ) | ||
249 | { | ||
250 | sPreContent = new std::string( sReplacementText ); | ||
251 | } | ||
252 | else | ||
253 | { | ||
254 | *sPreContent += sReplacementText; | ||
255 | } | ||
256 | } | ||
257 | if( lPostContent.getSize() > 0 ) | ||
258 | { | ||
259 | if( lPostContent[0] != NULL ) | ||
260 | { | ||
261 | if( sPreContent == NULL ) | ||
262 | { | ||
263 | sPreContent = new std::string( | ||
264 | ((std::string *)lPostContent[0])->c_str() | ||
265 | ); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | *sPreContent += | ||
270 | ((std::string *)lPostContent[0])->c_str(); | ||
271 | } | ||
272 | } | ||
273 | delete (std::string *)lPostContent[0]; | ||
274 | lPostContent.deleteAt( 0 ); | ||
275 | } | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | int nCont = nIndex-1; | ||
280 | // If it's above zero we deal with the post-content only | ||
281 | if( sReplacementText ) | ||
282 | { | ||
283 | if( lPostContent[nCont] == NULL ) | ||
284 | { | ||
285 | lPostContent.setAt( nCont, new std::string( sReplacementText ) ); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | *((std::string *)lPostContent[nCont]) += sReplacementText; | ||
290 | } | ||
291 | } | ||
292 | if( lPostContent.getSize() > nIndex ) | ||
293 | { | ||
294 | if( lPostContent[nIndex] != NULL ) | ||
295 | { | ||
296 | if( lPostContent[nCont] == NULL ) | ||
297 | { | ||
298 | lPostContent.setAt( nCont, new std::string( | ||
299 | ((std::string *)lPostContent[nIndex])->c_str() | ||
300 | ) ); | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | *((std::string *)lPostContent[nCont]) += | ||
305 | ((std::string *)lPostContent[nIndex])->c_str(); | ||
306 | } | ||
307 | } | ||
308 | delete (std::string *)lPostContent[nIndex]; | ||
309 | lPostContent.deleteAt( nIndex ); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | XmlNode *xRet = (XmlNode *)lChildren[nIndex]; | ||
314 | hChildren.del( ((XmlNode *)lChildren[nIndex])->getName() ); | ||
315 | lChildren.deleteAt( nIndex ); | ||
316 | |||
317 | return xRet; | ||
318 | } | ||
319 | |||
320 | bool XmlNode::replaceNode( int nIndex, XmlNode *pNewNode ) | ||
321 | { | ||
322 | if( nIndex < 0 || nIndex >= lChildren.getSize() ) | ||
323 | return false; | ||
324 | |||
325 | delete (XmlNode *)lChildren[nIndex]; | ||
326 | lChildren.setAt( nIndex, pNewNode ); | ||
327 | pNewNode->pParent = this; | ||
328 | |||
329 | return true; | ||
330 | } | ||
331 | |||
332 | XmlNode *XmlNode::getCopy() | ||
333 | { | ||
334 | XmlNode *pNew = new XmlNode(); | ||
335 | |||
336 | pNew->sName = sName; | ||
337 | if( sPreContent ) | ||
338 | { | ||
339 | pNew->sPreContent = new std::string( sPreContent->c_str() ); | ||
340 | } | ||
341 | else | ||
342 | { | ||
343 | pNew->sPreContent = NULL; | ||
344 | } | ||
345 | pNew->nCurContent = 0; | ||
346 | |||
347 | int nSize = lPostContent.getSize(); | ||
348 | pNew->lPostContent.setSize( nSize ); | ||
349 | for( int j = 0; j < nSize; j++ ) | ||
350 | { | ||
351 | if( lPostContent[j] ) | ||
352 | { | ||
353 | pNew->lPostContent.setAt( | ||
354 | j, new std::string( | ||
355 | ((std::string *)lPostContent[j])->c_str() | ||
356 | ) | ||
357 | ); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | pNew->lPostContent.setAt( j, NULL ); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | nSize = lChildren.getSize(); | ||
366 | pNew->lChildren.setSize( nSize ); | ||
367 | for( int j = 0; j < nSize; j++ ) | ||
368 | { | ||
369 | XmlNode *pChild = ((XmlNode *)lChildren[j])->getCopy(); | ||
370 | pNew->lChildren.setAt( j, pChild ); | ||
371 | pChild->pParent = this; | ||
372 | hChildren.insert( pChild->getName(), pChild ); | ||
373 | } | ||
374 | |||
375 | nSize = lPropNames.getSize(); | ||
376 | pNew->lPropNames.setSize( nSize ); | ||
377 | pNew->lPropValues.setSize( nSize ); | ||
378 | for( int j = 0; j < nSize; j++ ) | ||
379 | { | ||
380 | std::string *pProp = new std::string( ((std::string *)lPropNames[j])->c_str() ); | ||
381 | std::string *pVal = new std::string( ((std::string *)lPropValues[j])->c_str() ); | ||
382 | pNew->lPropNames.setAt( j, pProp ); | ||
383 | pNew->lPropValues.setAt( j, pVal ); | ||
384 | pNew->hProperties.insert( pProp->c_str(), pVal->c_str() ); | ||
385 | pNew->nCurContent++; | ||
386 | } | ||
387 | |||
388 | return pNew; | ||
389 | } | ||
390 | |||
391 | bool XmlNode::deleteNodeKeepChildren( int nIndex ) | ||
392 | { | ||
393 | // This is a tricky one...we need to do some patching to keep things all | ||
394 | // even... | ||
395 | XmlNode *xRet = (XmlNode *)lChildren[nIndex]; | ||
396 | |||
397 | if( xRet == NULL ) | ||
398 | { | ||
399 | return false; | ||
400 | } | ||
401 | else | ||
402 | { | ||
403 | if( getContent( nIndex ) ) | ||
404 | { | ||
405 | std::string sBuf( getContent( nIndex ) ); | ||
406 | sBuf += xRet->getContent( 0 ); | ||
407 | setContent( sBuf.c_str(), nIndex ); | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | setContent( xRet->getContent( 0 ), nIndex ); | ||
412 | } | ||
413 | |||
414 | int nSize = xRet->lChildren.getSize(); | ||
415 | for( int j = 0; j < nSize; j++ ) | ||
416 | { | ||
417 | XmlNode *pCopy = ((XmlNode *)xRet->lChildren[j])->getCopy(); | ||
418 | pCopy->pParent = this; | ||
419 | lChildren.insertBefore( pCopy, nIndex+j ); | ||
420 | |||
421 | if( xRet->lPostContent[j] ) | ||
422 | { | ||
423 | lPostContent.insertBefore( | ||
424 | new std::string( ((std::string *)xRet->lPostContent[j])->c_str() ), | ||
425 | nIndex+j | ||
426 | ); | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | lPostContent.insertBefore( NULL, nIndex+j ); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | if( getContent( nIndex+nSize ) ) | ||
435 | { | ||
436 | //SString sBuf( getContent( nIndex+nSize ) ); | ||
437 | //sBuf.catfrom( xRet->getContent( nSize ) ); | ||
438 | //setContent( sBuf, nIndex+nSize ); | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | setContent( xRet->getContent( nSize ), nIndex+nSize ); | ||
443 | } | ||
444 | |||
445 | deleteNode( nIndex+nSize ); | ||
446 | return true; | ||
447 | } | ||
448 | |||
449 | } | ||
450 | |||
451 | bool XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) | ||
452 | { | ||
453 | } | ||
454 | |||