Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5725 | serge | 1 | /* |
2 | www.sourceforge.net/projects/tinyxml |
||
3 | Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) |
||
4 | |||
5 | This software is provided 'as-is', without any express or implied |
||
6 | warranty. In no event will the authors be held liable for any |
||
7 | damages arising from the use of this software. |
||
8 | |||
9 | Permission is granted to anyone to use this software for any |
||
10 | purpose, including commercial applications, and to alter it and |
||
11 | redistribute it freely, subject to the following restrictions: |
||
12 | |||
13 | 1. The origin of this software must not be misrepresented; you must |
||
14 | not claim that you wrote the original software. If you use this |
||
15 | software in a product, an acknowledgment in the product documentation |
||
16 | would be appreciated but is not required. |
||
17 | |||
18 | 2. Altered source versions must be plainly marked as such, and |
||
19 | must not be misrepresented as being the original software. |
||
20 | |||
21 | 3. This notice may not be removed or altered from any source |
||
22 | distribution. |
||
23 | */ |
||
24 | |||
25 | #ifdef TIXML_USE_STL |
||
26 | #include |
||
27 | #include |
||
28 | #endif |
||
29 | |||
30 | #include "tinyxml.h" |
||
31 | |||
32 | |||
33 | bool TiXmlBase::condenseWhiteSpace = true; |
||
34 | |||
35 | // Microsoft compiler security |
||
36 | FILE* TiXmlFOpen( const char* filename, const char* mode ) |
||
37 | { |
||
38 | #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) |
||
39 | FILE* fp = 0; |
||
40 | errno_t err = fopen_s( &fp, filename, mode ); |
||
41 | if ( !err && fp ) |
||
42 | return fp; |
||
43 | return 0; |
||
44 | #else |
||
45 | return fopen( filename, mode ); |
||
46 | #endif |
||
47 | } |
||
48 | |||
49 | void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) |
||
50 | { |
||
51 | int i=0; |
||
52 | |||
53 | while( i<(int)str.length() ) |
||
54 | { |
||
55 | unsigned char c = (unsigned char) str[i]; |
||
56 | |||
57 | if ( c == '&' |
||
58 | && i < ( (int)str.length() - 2 ) |
||
59 | && str[i+1] == '#' |
||
60 | && str[i+2] == 'x' ) |
||
61 | { |
||
62 | // Hexadecimal character reference. |
||
63 | // Pass through unchanged. |
||
64 | // © -- copyright symbol, for example. |
||
65 | // |
||
66 | // The -1 is a bug fix from Rob Laveaux. It keeps |
||
67 | // an overflow from happening if there is no ';'. |
||
68 | // There are actually 2 ways to exit this loop - |
||
69 | // while fails (error case) and break (semicolon found). |
||
70 | // However, there is no mechanism (currently) for |
||
71 | // this function to return an error. |
||
72 | while ( i<(int)str.length()-1 ) |
||
73 | { |
||
74 | outString->append( str.c_str() + i, 1 ); |
||
75 | ++i; |
||
76 | if ( str[i] == ';' ) |
||
77 | break; |
||
78 | } |
||
79 | } |
||
80 | else if ( c == '&' ) |
||
81 | { |
||
82 | outString->append( entity[0].str, entity[0].strLength ); |
||
83 | ++i; |
||
84 | } |
||
85 | else if ( c == '<' ) |
||
86 | { |
||
87 | outString->append( entity[1].str, entity[1].strLength ); |
||
88 | ++i; |
||
89 | } |
||
90 | else if ( c == '>' ) |
||
91 | { |
||
92 | outString->append( entity[2].str, entity[2].strLength ); |
||
93 | ++i; |
||
94 | } |
||
95 | else if ( c == '\"' ) |
||
96 | { |
||
97 | outString->append( entity[3].str, entity[3].strLength ); |
||
98 | ++i; |
||
99 | } |
||
100 | else if ( c == '\'' ) |
||
101 | { |
||
102 | outString->append( entity[4].str, entity[4].strLength ); |
||
103 | ++i; |
||
104 | } |
||
105 | else if ( c < 32 ) |
||
106 | { |
||
107 | // Easy pass at non-alpha/numeric/symbol |
||
108 | // Below 32 is symbolic. |
||
109 | char buf[ 32 ]; |
||
110 | |||
111 | #if defined(TIXML_SNPRINTF) |
||
112 | TIXML_SNPRINTF( buf, sizeof(buf), "%02X;", (unsigned) ( c & 0xff ) ); |
||
113 | #else |
||
114 | sprintf( buf, "%02X;", (unsigned) ( c & 0xff ) ); |
||
115 | #endif |
||
116 | |||
117 | //*ME: warning C4267: convert 'size_t' to 'int' |
||
118 | //*ME: Int-Cast to make compiler happy ... |
||
119 | outString->append( buf, (int)strlen( buf ) ); |
||
120 | ++i; |
||
121 | } |
||
122 | else |
||
123 | { |
||
124 | //char realc = (char) c; |
||
125 | //outString->append( &realc, 1 ); |
||
126 | *outString += (char) c; // somewhat more efficient function call. |
||
127 | ++i; |
||
128 | } |
||
129 | } |
||
130 | } |
||
131 | |||
132 | |||
133 | TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() |
||
134 | { |
||
135 | parent = 0; |
||
136 | type = _type; |
||
137 | firstChild = 0; |
||
138 | lastChild = 0; |
||
139 | prev = 0; |
||
140 | next = 0; |
||
141 | } |
||
142 | |||
143 | |||
144 | TiXmlNode::~TiXmlNode() |
||
145 | { |
||
146 | TiXmlNode* node = firstChild; |
||
147 | TiXmlNode* temp = 0; |
||
148 | |||
149 | while ( node ) |
||
150 | { |
||
151 | temp = node; |
||
152 | node = node->next; |
||
153 | delete temp; |
||
154 | } |
||
155 | } |
||
156 | |||
157 | |||
158 | void TiXmlNode::CopyTo( TiXmlNode* target ) const |
||
159 | { |
||
160 | target->SetValue (value.c_str() ); |
||
161 | target->userData = userData; |
||
162 | } |
||
163 | |||
164 | |||
165 | void TiXmlNode::Clear() |
||
166 | { |
||
167 | TiXmlNode* node = firstChild; |
||
168 | TiXmlNode* temp = 0; |
||
169 | |||
170 | while ( node ) |
||
171 | { |
||
172 | temp = node; |
||
173 | node = node->next; |
||
174 | delete temp; |
||
175 | } |
||
176 | |||
177 | firstChild = 0; |
||
178 | lastChild = 0; |
||
179 | } |
||
180 | |||
181 | |||
182 | TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) |
||
183 | { |
||
184 | assert( node->parent == 0 || node->parent == this ); |
||
185 | assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); |
||
186 | |||
187 | if ( node->Type() == TiXmlNode::DOCUMENT ) |
||
188 | { |
||
189 | delete node; |
||
190 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
191 | return 0; |
||
192 | } |
||
193 | |||
194 | node->parent = this; |
||
195 | |||
196 | node->prev = lastChild; |
||
197 | node->next = 0; |
||
198 | |||
199 | if ( lastChild ) |
||
200 | lastChild->next = node; |
||
201 | else |
||
202 | firstChild = node; // it was an empty list. |
||
203 | |||
204 | lastChild = node; |
||
205 | return node; |
||
206 | } |
||
207 | |||
208 | |||
209 | TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) |
||
210 | { |
||
211 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) |
||
212 | { |
||
213 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
214 | return 0; |
||
215 | } |
||
216 | TiXmlNode* node = addThis.Clone(); |
||
217 | if ( !node ) |
||
218 | return 0; |
||
219 | |||
220 | return LinkEndChild( node ); |
||
221 | } |
||
222 | |||
223 | |||
224 | TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) |
||
225 | { |
||
226 | if ( !beforeThis || beforeThis->parent != this ) { |
||
227 | return 0; |
||
228 | } |
||
229 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) |
||
230 | { |
||
231 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
232 | return 0; |
||
233 | } |
||
234 | |||
235 | TiXmlNode* node = addThis.Clone(); |
||
236 | if ( !node ) |
||
237 | return 0; |
||
238 | node->parent = this; |
||
239 | |||
240 | node->next = beforeThis; |
||
241 | node->prev = beforeThis->prev; |
||
242 | if ( beforeThis->prev ) |
||
243 | { |
||
244 | beforeThis->prev->next = node; |
||
245 | } |
||
246 | else |
||
247 | { |
||
248 | assert( firstChild == beforeThis ); |
||
249 | firstChild = node; |
||
250 | } |
||
251 | beforeThis->prev = node; |
||
252 | return node; |
||
253 | } |
||
254 | |||
255 | |||
256 | TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) |
||
257 | { |
||
258 | if ( !afterThis || afterThis->parent != this ) { |
||
259 | return 0; |
||
260 | } |
||
261 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) |
||
262 | { |
||
263 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
264 | return 0; |
||
265 | } |
||
266 | |||
267 | TiXmlNode* node = addThis.Clone(); |
||
268 | if ( !node ) |
||
269 | return 0; |
||
270 | node->parent = this; |
||
271 | |||
272 | node->prev = afterThis; |
||
273 | node->next = afterThis->next; |
||
274 | if ( afterThis->next ) |
||
275 | { |
||
276 | afterThis->next->prev = node; |
||
277 | } |
||
278 | else |
||
279 | { |
||
280 | assert( lastChild == afterThis ); |
||
281 | lastChild = node; |
||
282 | } |
||
283 | afterThis->next = node; |
||
284 | return node; |
||
285 | } |
||
286 | |||
287 | |||
288 | TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) |
||
289 | { |
||
290 | if ( replaceThis->parent != this ) |
||
291 | return 0; |
||
292 | |||
293 | TiXmlNode* node = withThis.Clone(); |
||
294 | if ( !node ) |
||
295 | return 0; |
||
296 | |||
297 | node->next = replaceThis->next; |
||
298 | node->prev = replaceThis->prev; |
||
299 | |||
300 | if ( replaceThis->next ) |
||
301 | replaceThis->next->prev = node; |
||
302 | else |
||
303 | lastChild = node; |
||
304 | |||
305 | if ( replaceThis->prev ) |
||
306 | replaceThis->prev->next = node; |
||
307 | else |
||
308 | firstChild = node; |
||
309 | |||
310 | delete replaceThis; |
||
311 | node->parent = this; |
||
312 | return node; |
||
313 | } |
||
314 | |||
315 | |||
316 | bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) |
||
317 | { |
||
318 | if ( removeThis->parent != this ) |
||
319 | { |
||
320 | assert( 0 ); |
||
321 | return false; |
||
322 | } |
||
323 | |||
324 | if ( removeThis->next ) |
||
325 | removeThis->next->prev = removeThis->prev; |
||
326 | else |
||
327 | lastChild = removeThis->prev; |
||
328 | |||
329 | if ( removeThis->prev ) |
||
330 | removeThis->prev->next = removeThis->next; |
||
331 | else |
||
332 | firstChild = removeThis->next; |
||
333 | |||
334 | delete removeThis; |
||
335 | return true; |
||
336 | } |
||
337 | |||
338 | const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const |
||
339 | { |
||
340 | const TiXmlNode* node; |
||
341 | for ( node = firstChild; node; node = node->next ) |
||
342 | { |
||
343 | if ( strcmp( node->Value(), _value ) == 0 ) |
||
344 | return node; |
||
345 | } |
||
346 | return 0; |
||
347 | } |
||
348 | |||
349 | |||
350 | const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const |
||
351 | { |
||
352 | const TiXmlNode* node; |
||
353 | for ( node = lastChild; node; node = node->prev ) |
||
354 | { |
||
355 | if ( strcmp( node->Value(), _value ) == 0 ) |
||
356 | return node; |
||
357 | } |
||
358 | return 0; |
||
359 | } |
||
360 | |||
361 | |||
362 | const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const |
||
363 | { |
||
364 | if ( !previous ) |
||
365 | { |
||
366 | return FirstChild(); |
||
367 | } |
||
368 | else |
||
369 | { |
||
370 | assert( previous->parent == this ); |
||
371 | return previous->NextSibling(); |
||
372 | } |
||
373 | } |
||
374 | |||
375 | |||
376 | const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const |
||
377 | { |
||
378 | if ( !previous ) |
||
379 | { |
||
380 | return FirstChild( val ); |
||
381 | } |
||
382 | else |
||
383 | { |
||
384 | assert( previous->parent == this ); |
||
385 | return previous->NextSibling( val ); |
||
386 | } |
||
387 | } |
||
388 | |||
389 | |||
390 | const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const |
||
391 | { |
||
392 | const TiXmlNode* node; |
||
393 | for ( node = next; node; node = node->next ) |
||
394 | { |
||
395 | if ( strcmp( node->Value(), _value ) == 0 ) |
||
396 | return node; |
||
397 | } |
||
398 | return 0; |
||
399 | } |
||
400 | |||
401 | |||
402 | const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const |
||
403 | { |
||
404 | const TiXmlNode* node; |
||
405 | for ( node = prev; node; node = node->prev ) |
||
406 | { |
||
407 | if ( strcmp( node->Value(), _value ) == 0 ) |
||
408 | return node; |
||
409 | } |
||
410 | return 0; |
||
411 | } |
||
412 | |||
413 | |||
414 | void TiXmlElement::RemoveAttribute( const char * name ) |
||
415 | { |
||
416 | #ifdef TIXML_USE_STL |
||
417 | TIXML_STRING str( name ); |
||
418 | TiXmlAttribute* node = attributeSet.Find( str ); |
||
419 | #else |
||
420 | TiXmlAttribute* node = attributeSet.Find( name ); |
||
421 | #endif |
||
422 | if ( node ) |
||
423 | { |
||
424 | attributeSet.Remove( node ); |
||
425 | delete node; |
||
426 | } |
||
427 | } |
||
428 | |||
429 | const TiXmlElement* TiXmlNode::FirstChildElement() const |
||
430 | { |
||
431 | const TiXmlNode* node; |
||
432 | |||
433 | for ( node = FirstChild(); |
||
434 | node; |
||
435 | node = node->NextSibling() ) |
||
436 | { |
||
437 | if ( node->ToElement() ) |
||
438 | return node->ToElement(); |
||
439 | } |
||
440 | return 0; |
||
441 | } |
||
442 | |||
443 | |||
444 | const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const |
||
445 | { |
||
446 | const TiXmlNode* node; |
||
447 | |||
448 | for ( node = FirstChild( _value ); |
||
449 | node; |
||
450 | node = node->NextSibling( _value ) ) |
||
451 | { |
||
452 | if ( node->ToElement() ) |
||
453 | return node->ToElement(); |
||
454 | } |
||
455 | return 0; |
||
456 | } |
||
457 | |||
458 | |||
459 | const TiXmlElement* TiXmlNode::NextSiblingElement() const |
||
460 | { |
||
461 | const TiXmlNode* node; |
||
462 | |||
463 | for ( node = NextSibling(); |
||
464 | node; |
||
465 | node = node->NextSibling() ) |
||
466 | { |
||
467 | if ( node->ToElement() ) |
||
468 | return node->ToElement(); |
||
469 | } |
||
470 | return 0; |
||
471 | } |
||
472 | |||
473 | |||
474 | const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const |
||
475 | { |
||
476 | const TiXmlNode* node; |
||
477 | |||
478 | for ( node = NextSibling( _value ); |
||
479 | node; |
||
480 | node = node->NextSibling( _value ) ) |
||
481 | { |
||
482 | if ( node->ToElement() ) |
||
483 | return node->ToElement(); |
||
484 | } |
||
485 | return 0; |
||
486 | } |
||
487 | |||
488 | |||
489 | const TiXmlDocument* TiXmlNode::GetDocument() const |
||
490 | { |
||
491 | const TiXmlNode* node; |
||
492 | |||
493 | for( node = this; node; node = node->parent ) |
||
494 | { |
||
495 | if ( node->ToDocument() ) |
||
496 | return node->ToDocument(); |
||
497 | } |
||
498 | return 0; |
||
499 | } |
||
500 | |||
501 | |||
502 | TiXmlElement::TiXmlElement (const char * _value) |
||
503 | : TiXmlNode( TiXmlNode::ELEMENT ) |
||
504 | { |
||
505 | firstChild = lastChild = 0; |
||
506 | value = _value; |
||
507 | } |
||
508 | |||
509 | |||
510 | #ifdef TIXML_USE_STL |
||
511 | TiXmlElement::TiXmlElement( const std::string& _value ) |
||
512 | : TiXmlNode( TiXmlNode::ELEMENT ) |
||
513 | { |
||
514 | firstChild = lastChild = 0; |
||
515 | value = _value; |
||
516 | } |
||
517 | #endif |
||
518 | |||
519 | |||
520 | TiXmlElement::TiXmlElement( const TiXmlElement& copy) |
||
521 | : TiXmlNode( TiXmlNode::ELEMENT ) |
||
522 | { |
||
523 | firstChild = lastChild = 0; |
||
524 | copy.CopyTo( this ); |
||
525 | } |
||
526 | |||
527 | |||
528 | void TiXmlElement::operator=( const TiXmlElement& base ) |
||
529 | { |
||
530 | ClearThis(); |
||
531 | base.CopyTo( this ); |
||
532 | } |
||
533 | |||
534 | |||
535 | TiXmlElement::~TiXmlElement() |
||
536 | { |
||
537 | ClearThis(); |
||
538 | } |
||
539 | |||
540 | |||
541 | void TiXmlElement::ClearThis() |
||
542 | { |
||
543 | Clear(); |
||
544 | while( attributeSet.First() ) |
||
545 | { |
||
546 | TiXmlAttribute* node = attributeSet.First(); |
||
547 | attributeSet.Remove( node ); |
||
548 | delete node; |
||
549 | } |
||
550 | } |
||
551 | |||
552 | |||
553 | const char* TiXmlElement::Attribute( const char* name ) const |
||
554 | { |
||
555 | const TiXmlAttribute* node = attributeSet.Find( name ); |
||
556 | if ( node ) |
||
557 | return node->Value(); |
||
558 | return 0; |
||
559 | } |
||
560 | |||
561 | |||
562 | #ifdef TIXML_USE_STL |
||
563 | const std::string* TiXmlElement::Attribute( const std::string& name ) const |
||
564 | { |
||
565 | const TiXmlAttribute* node = attributeSet.Find( name ); |
||
566 | if ( node ) |
||
567 | return &node->ValueStr(); |
||
568 | return 0; |
||
569 | } |
||
570 | #endif |
||
571 | |||
572 | |||
573 | const char* TiXmlElement::Attribute( const char* name, int* i ) const |
||
574 | { |
||
575 | const char* s = Attribute( name ); |
||
576 | if ( i ) |
||
577 | { |
||
578 | if ( s ) { |
||
579 | *i = atoi( s ); |
||
580 | } |
||
581 | else { |
||
582 | *i = 0; |
||
583 | } |
||
584 | } |
||
585 | return s; |
||
586 | } |
||
587 | |||
588 | |||
589 | #ifdef TIXML_USE_STL |
||
590 | const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const |
||
591 | { |
||
592 | const std::string* s = Attribute( name ); |
||
593 | if ( i ) |
||
594 | { |
||
595 | if ( s ) { |
||
596 | *i = atoi( s->c_str() ); |
||
597 | } |
||
598 | else { |
||
599 | *i = 0; |
||
600 | } |
||
601 | } |
||
602 | return s; |
||
603 | } |
||
604 | #endif |
||
605 | |||
606 | |||
607 | const char* TiXmlElement::Attribute( const char* name, double* d ) const |
||
608 | { |
||
609 | const char* s = Attribute( name ); |
||
610 | if ( d ) |
||
611 | { |
||
612 | if ( s ) { |
||
613 | *d = atof( s ); |
||
614 | } |
||
615 | else { |
||
616 | *d = 0; |
||
617 | } |
||
618 | } |
||
619 | return s; |
||
620 | } |
||
621 | |||
622 | |||
623 | #ifdef TIXML_USE_STL |
||
624 | const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const |
||
625 | { |
||
626 | const std::string* s = Attribute( name ); |
||
627 | if ( d ) |
||
628 | { |
||
629 | if ( s ) { |
||
630 | *d = atof( s->c_str() ); |
||
631 | } |
||
632 | else { |
||
633 | *d = 0; |
||
634 | } |
||
635 | } |
||
636 | return s; |
||
637 | } |
||
638 | #endif |
||
639 | |||
640 | |||
641 | int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const |
||
642 | { |
||
643 | const TiXmlAttribute* node = attributeSet.Find( name ); |
||
644 | if ( !node ) |
||
645 | return TIXML_NO_ATTRIBUTE; |
||
646 | return node->QueryIntValue( ival ); |
||
647 | } |
||
648 | |||
649 | |||
650 | #ifdef TIXML_USE_STL |
||
651 | int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const |
||
652 | { |
||
653 | const TiXmlAttribute* node = attributeSet.Find( name ); |
||
654 | if ( !node ) |
||
655 | return TIXML_NO_ATTRIBUTE; |
||
656 | return node->QueryIntValue( ival ); |
||
657 | } |
||
658 | #endif |
||
659 | |||
660 | |||
661 | int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const |
||
662 | { |
||
663 | const TiXmlAttribute* node = attributeSet.Find( name ); |
||
664 | if ( !node ) |
||
665 | return TIXML_NO_ATTRIBUTE; |
||
666 | return node->QueryDoubleValue( dval ); |
||
667 | } |
||
668 | |||
669 | |||
670 | #ifdef TIXML_USE_STL |
||
671 | int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const |
||
672 | { |
||
673 | const TiXmlAttribute* node = attributeSet.Find( name ); |
||
674 | if ( !node ) |
||
675 | return TIXML_NO_ATTRIBUTE; |
||
676 | return node->QueryDoubleValue( dval ); |
||
677 | } |
||
678 | #endif |
||
679 | |||
680 | |||
681 | void TiXmlElement::SetAttribute( const char * name, int val ) |
||
682 | { |
||
683 | char buf[64]; |
||
684 | #if defined(TIXML_SNPRINTF) |
||
685 | TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); |
||
686 | #else |
||
687 | sprintf( buf, "%d", val ); |
||
688 | #endif |
||
689 | SetAttribute( name, buf ); |
||
690 | } |
||
691 | |||
692 | |||
693 | #ifdef TIXML_USE_STL |
||
694 | void TiXmlElement::SetAttribute( const std::string& name, int val ) |
||
695 | { |
||
696 | std::ostringstream oss; |
||
697 | oss << val; |
||
698 | SetAttribute( name, oss.str() ); |
||
699 | } |
||
700 | #endif |
||
701 | |||
702 | |||
703 | void TiXmlElement::SetDoubleAttribute( const char * name, double val ) |
||
704 | { |
||
705 | char buf[256]; |
||
706 | #if defined(TIXML_SNPRINTF) |
||
707 | TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); |
||
708 | #else |
||
709 | sprintf( buf, "%f", val ); |
||
710 | #endif |
||
711 | SetAttribute( name, buf ); |
||
712 | } |
||
713 | |||
714 | |||
715 | void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) |
||
716 | { |
||
717 | #ifdef TIXML_USE_STL |
||
718 | TIXML_STRING _name( cname ); |
||
719 | TIXML_STRING _value( cvalue ); |
||
720 | #else |
||
721 | const char* _name = cname; |
||
722 | const char* _value = cvalue; |
||
723 | #endif |
||
724 | |||
725 | TiXmlAttribute* node = attributeSet.Find( _name ); |
||
726 | if ( node ) |
||
727 | { |
||
728 | node->SetValue( _value ); |
||
729 | return; |
||
730 | } |
||
731 | |||
732 | TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); |
||
733 | if ( attrib ) |
||
734 | { |
||
735 | attributeSet.Add( attrib ); |
||
736 | } |
||
737 | else |
||
738 | { |
||
739 | TiXmlDocument* document = GetDocument(); |
||
740 | if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
741 | } |
||
742 | } |
||
743 | |||
744 | |||
745 | #ifdef TIXML_USE_STL |
||
746 | void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) |
||
747 | { |
||
748 | TiXmlAttribute* node = attributeSet.Find( name ); |
||
749 | if ( node ) |
||
750 | { |
||
751 | node->SetValue( _value ); |
||
752 | return; |
||
753 | } |
||
754 | |||
755 | TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); |
||
756 | if ( attrib ) |
||
757 | { |
||
758 | attributeSet.Add( attrib ); |
||
759 | } |
||
760 | else |
||
761 | { |
||
762 | TiXmlDocument* document = GetDocument(); |
||
763 | if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
764 | } |
||
765 | } |
||
766 | #endif |
||
767 | |||
768 | |||
769 | void TiXmlElement::Print( FILE* cfile, int depth ) const |
||
770 | { |
||
771 | int i; |
||
772 | assert( cfile ); |
||
773 | for ( i=0; i |
||
774 | fprintf( cfile, " " ); |
||
775 | } |
||
776 | |||
777 | fprintf( cfile, "<%s", value.c_str() ); |
||
778 | |||
779 | const TiXmlAttribute* attrib; |
||
780 | for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) |
||
781 | { |
||
782 | fprintf( cfile, " " ); |
||
783 | attrib->Print( cfile, depth ); |
||
784 | } |
||
785 | |||
786 | // There are 3 different formatting approaches: |
||
787 | // 1) An element without children is printed as a |
||
788 | // 2) An element with only a text child is printed as |
||
789 | // 3) An element with children is printed on multiple lines. |
||
790 | TiXmlNode* node; |
||
791 | if ( !firstChild ) |
||
792 | { |
||
793 | fprintf( cfile, " />" ); |
||
794 | } |
||
795 | else if ( firstChild == lastChild && firstChild->ToText() ) |
||
796 | { |
||
797 | fprintf( cfile, ">" ); |
||
798 | firstChild->Print( cfile, depth + 1 ); |
||
799 | fprintf( cfile, "%s>", value.c_str() ); |
||
800 | } |
||
801 | else |
||
802 | { |
||
803 | fprintf( cfile, ">" ); |
||
804 | |||
805 | for ( node = firstChild; node; node=node->NextSibling() ) |
||
806 | { |
||
807 | if ( !node->ToText() ) |
||
808 | { |
||
809 | fprintf( cfile, "\n" ); |
||
810 | } |
||
811 | node->Print( cfile, depth+1 ); |
||
812 | } |
||
813 | fprintf( cfile, "\n" ); |
||
814 | for( i=0; i |
||
815 | fprintf( cfile, " " ); |
||
816 | } |
||
817 | fprintf( cfile, "%s>", value.c_str() ); |
||
818 | } |
||
819 | } |
||
820 | |||
821 | |||
822 | void TiXmlElement::CopyTo( TiXmlElement* target ) const |
||
823 | { |
||
824 | // superclass: |
||
825 | TiXmlNode::CopyTo( target ); |
||
826 | |||
827 | // Element class: |
||
828 | // Clone the attributes, then clone the children. |
||
829 | const TiXmlAttribute* attribute = 0; |
||
830 | for( attribute = attributeSet.First(); |
||
831 | attribute; |
||
832 | attribute = attribute->Next() ) |
||
833 | { |
||
834 | target->SetAttribute( attribute->Name(), attribute->Value() ); |
||
835 | } |
||
836 | |||
837 | TiXmlNode* node = 0; |
||
838 | for ( node = firstChild; node; node = node->NextSibling() ) |
||
839 | { |
||
840 | target->LinkEndChild( node->Clone() ); |
||
841 | } |
||
842 | } |
||
843 | |||
844 | bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const |
||
845 | { |
||
846 | if ( visitor->VisitEnter( *this, attributeSet.First() ) ) |
||
847 | { |
||
848 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) |
||
849 | { |
||
850 | if ( !node->Accept( visitor ) ) |
||
851 | break; |
||
852 | } |
||
853 | } |
||
854 | return visitor->VisitExit( *this ); |
||
855 | } |
||
856 | |||
857 | |||
858 | TiXmlNode* TiXmlElement::Clone() const |
||
859 | { |
||
860 | TiXmlElement* clone = new TiXmlElement( Value() ); |
||
861 | if ( !clone ) |
||
862 | return 0; |
||
863 | |||
864 | CopyTo( clone ); |
||
865 | return clone; |
||
866 | } |
||
867 | |||
868 | |||
869 | const char* TiXmlElement::GetText() const |
||
870 | { |
||
871 | const TiXmlNode* child = this->FirstChild(); |
||
872 | if ( child ) { |
||
873 | const TiXmlText* childText = child->ToText(); |
||
874 | if ( childText ) { |
||
875 | return childText->Value(); |
||
876 | } |
||
877 | } |
||
878 | return 0; |
||
879 | } |
||
880 | |||
881 | |||
882 | TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) |
||
883 | { |
||
884 | tabsize = 4; |
||
885 | useMicrosoftBOM = false; |
||
886 | ClearError(); |
||
887 | } |
||
888 | |||
889 | TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) |
||
890 | { |
||
891 | tabsize = 4; |
||
892 | useMicrosoftBOM = false; |
||
893 | value = documentName; |
||
894 | ClearError(); |
||
895 | } |
||
896 | |||
897 | |||
898 | #ifdef TIXML_USE_STL |
||
899 | TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) |
||
900 | { |
||
901 | tabsize = 4; |
||
902 | useMicrosoftBOM = false; |
||
903 | value = documentName; |
||
904 | ClearError(); |
||
905 | } |
||
906 | #endif |
||
907 | |||
908 | |||
909 | TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) |
||
910 | { |
||
911 | copy.CopyTo( this ); |
||
912 | } |
||
913 | |||
914 | |||
915 | void TiXmlDocument::operator=( const TiXmlDocument& copy ) |
||
916 | { |
||
917 | Clear(); |
||
918 | copy.CopyTo( this ); |
||
919 | } |
||
920 | |||
921 | |||
922 | bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) |
||
923 | { |
||
924 | // See STL_STRING_BUG below. |
||
925 | //StringToBuffer buf( value ); |
||
926 | |||
927 | return LoadFile( Value(), encoding ); |
||
928 | } |
||
929 | |||
930 | |||
931 | bool TiXmlDocument::SaveFile() const |
||
932 | { |
||
933 | // See STL_STRING_BUG below. |
||
934 | // StringToBuffer buf( value ); |
||
935 | // |
||
936 | // if ( buf.buffer && SaveFile( buf.buffer ) ) |
||
937 | // return true; |
||
938 | // |
||
939 | // return false; |
||
940 | return SaveFile( Value() ); |
||
941 | } |
||
942 | |||
943 | bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) |
||
944 | { |
||
945 | // There was a really terrifying little bug here. The code: |
||
946 | // value = filename |
||
947 | // in the STL case, cause the assignment method of the std::string to |
||
948 | // be called. What is strange, is that the std::string had the same |
||
949 | // address as it's c_str() method, and so bad things happen. Looks |
||
950 | // like a bug in the Microsoft STL implementation. |
||
951 | // Add an extra string to avoid the crash. |
||
952 | TIXML_STRING filename( _filename ); |
||
953 | value = filename; |
||
954 | |||
955 | // reading in binary mode so that tinyxml can normalize the EOL |
||
956 | FILE* file = TiXmlFOpen( value.c_str (), "rb" ); |
||
957 | |||
958 | if ( file ) |
||
959 | { |
||
960 | bool result = LoadFile( file, encoding ); |
||
961 | fclose( file ); |
||
962 | return result; |
||
963 | } |
||
964 | else |
||
965 | { |
||
966 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
967 | return false; |
||
968 | } |
||
969 | } |
||
970 | |||
971 | bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) |
||
972 | { |
||
973 | if ( !file ) |
||
974 | { |
||
975 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
976 | return false; |
||
977 | } |
||
978 | |||
979 | // Delete the existing data: |
||
980 | Clear(); |
||
981 | location.Clear(); |
||
982 | |||
983 | // Get the file size, so we can pre-allocate the string. HUGE speed impact. |
||
984 | long length = 0; |
||
985 | fseek( file, 0, SEEK_END ); |
||
986 | length = ftell( file ); |
||
987 | fseek( file, 0, SEEK_SET ); |
||
988 | |||
989 | // Strange case, but good to handle up front. |
||
990 | if ( length <= 0 ) |
||
991 | { |
||
992 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
993 | return false; |
||
994 | } |
||
995 | |||
996 | // If we have a file, assume it is all one big XML file, and read it in. |
||
997 | // The document parser may decide the document ends sooner than the entire file, however. |
||
998 | TIXML_STRING data; |
||
999 | data.reserve( length ); |
||
1000 | |||
1001 | // Subtle bug here. TinyXml did use fgets. But from the XML spec: |
||
1002 | // 2.11 End-of-Line Handling |
||
1003 | // |
||
1004 | // |
||
1005 | // ...the XML processor MUST behave as if it normalized all line breaks in external |
||
1006 | // parsed entities (including the document entity) on input, before parsing, by translating |
||
1007 | // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to |
||
1008 | // a single #xA character. |
||
1009 | // |
||
1010 | // |
||
1011 | // It is not clear fgets does that, and certainly isn't clear it works cross platform. |
||
1012 | // Generally, you expect fgets to translate from the convention of the OS to the c/unix |
||
1013 | // convention, and not work generally. |
||
1014 | |||
1015 | /* |
||
1016 | while( fgets( buf, sizeof(buf), file ) ) |
||
1017 | { |
||
1018 | data += buf; |
||
1019 | } |
||
1020 | */ |
||
1021 | |||
1022 | char* buf = new char[ length+1 ]; |
||
1023 | buf[0] = 0; |
||
1024 | |||
1025 | if ( fread( buf, length, 1, file ) != 1 ) { |
||
1026 | delete [] buf; |
||
1027 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); |
||
1028 | return false; |
||
1029 | } |
||
1030 | |||
1031 | const char* lastPos = buf; |
||
1032 | const char* p = buf; |
||
1033 | |||
1034 | buf[length] = 0; |
||
1035 | while( *p ) { |
||
1036 | assert( p < (buf+length) ); |
||
1037 | if ( *p == 0xa ) { |
||
1038 | // Newline character. No special rules for this. Append all the characters |
||
1039 | // since the last string, and include the newline. |
||
1040 | data.append( lastPos, (p-lastPos+1) ); // append, include the newline |
||
1041 | ++p; // move past the newline |
||
1042 | lastPos = p; // and point to the new buffer (may be 0) |
||
1043 | assert( p <= (buf+length) ); |
||
1044 | } |
||
1045 | else if ( *p == 0xd ) { |
||
1046 | // Carriage return. Append what we have so far, then |
||
1047 | // handle moving forward in the buffer. |
||
1048 | if ( (p-lastPos) > 0 ) { |
||
1049 | data.append( lastPos, p-lastPos ); // do not add the CR |
||
1050 | } |
||
1051 | data += (char)0xa; // a proper newline |
||
1052 | |||
1053 | if ( *(p+1) == 0xa ) { |
||
1054 | // Carriage return - new line sequence |
||
1055 | p += 2; |
||
1056 | lastPos = p; |
||
1057 | assert( p <= (buf+length) ); |
||
1058 | } |
||
1059 | else { |
||
1060 | // it was followed by something else...that is presumably characters again. |
||
1061 | ++p; |
||
1062 | lastPos = p; |
||
1063 | assert( p <= (buf+length) ); |
||
1064 | } |
||
1065 | } |
||
1066 | else { |
||
1067 | ++p; |
||
1068 | } |
||
1069 | } |
||
1070 | // Handle any left over characters. |
||
1071 | if ( p-lastPos ) { |
||
1072 | data.append( lastPos, p-lastPos ); |
||
1073 | } |
||
1074 | delete [] buf; |
||
1075 | buf = 0; |
||
1076 | |||
1077 | Parse( data.c_str(), 0, encoding ); |
||
1078 | |||
1079 | if ( Error() ) |
||
1080 | return false; |
||
1081 | else |
||
1082 | return true; |
||
1083 | } |
||
1084 | |||
1085 | |||
1086 | bool TiXmlDocument::SaveFile( const char * filename ) const |
||
1087 | { |
||
1088 | // The old c stuff lives on... |
||
1089 | FILE* fp = TiXmlFOpen( filename, "w" ); |
||
1090 | if ( fp ) |
||
1091 | { |
||
1092 | bool result = SaveFile( fp ); |
||
1093 | fclose( fp ); |
||
1094 | return result; |
||
1095 | } |
||
1096 | return false; |
||
1097 | } |
||
1098 | |||
1099 | |||
1100 | bool TiXmlDocument::SaveFile( FILE* fp ) const |
||
1101 | { |
||
1102 | if ( useMicrosoftBOM ) |
||
1103 | { |
||
1104 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; |
||
1105 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; |
||
1106 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; |
||
1107 | |||
1108 | fputc( TIXML_UTF_LEAD_0, fp ); |
||
1109 | fputc( TIXML_UTF_LEAD_1, fp ); |
||
1110 | fputc( TIXML_UTF_LEAD_2, fp ); |
||
1111 | } |
||
1112 | Print( fp, 0 ); |
||
1113 | return (ferror(fp) == 0); |
||
1114 | } |
||
1115 | |||
1116 | |||
1117 | void TiXmlDocument::CopyTo( TiXmlDocument* target ) const |
||
1118 | { |
||
1119 | TiXmlNode::CopyTo( target ); |
||
1120 | |||
1121 | target->error = error; |
||
1122 | target->errorId = errorId; |
||
1123 | target->errorDesc = errorDesc; |
||
1124 | target->tabsize = tabsize; |
||
1125 | target->errorLocation = errorLocation; |
||
1126 | target->useMicrosoftBOM = useMicrosoftBOM; |
||
1127 | |||
1128 | TiXmlNode* node = 0; |
||
1129 | for ( node = firstChild; node; node = node->NextSibling() ) |
||
1130 | { |
||
1131 | target->LinkEndChild( node->Clone() ); |
||
1132 | } |
||
1133 | } |
||
1134 | |||
1135 | |||
1136 | TiXmlNode* TiXmlDocument::Clone() const |
||
1137 | { |
||
1138 | TiXmlDocument* clone = new TiXmlDocument(); |
||
1139 | if ( !clone ) |
||
1140 | return 0; |
||
1141 | |||
1142 | CopyTo( clone ); |
||
1143 | return clone; |
||
1144 | } |
||
1145 | |||
1146 | |||
1147 | void TiXmlDocument::Print( FILE* cfile, int depth ) const |
||
1148 | { |
||
1149 | assert( cfile ); |
||
1150 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) |
||
1151 | { |
||
1152 | node->Print( cfile, depth ); |
||
1153 | fprintf( cfile, "\n" ); |
||
1154 | } |
||
1155 | } |
||
1156 | |||
1157 | |||
1158 | bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const |
||
1159 | { |
||
1160 | if ( visitor->VisitEnter( *this ) ) |
||
1161 | { |
||
1162 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) |
||
1163 | { |
||
1164 | if ( !node->Accept( visitor ) ) |
||
1165 | break; |
||
1166 | } |
||
1167 | } |
||
1168 | return visitor->VisitExit( *this ); |
||
1169 | } |
||
1170 | |||
1171 | |||
1172 | const TiXmlAttribute* TiXmlAttribute::Next() const |
||
1173 | { |
||
1174 | // We are using knowledge of the sentinel. The sentinel |
||
1175 | // have a value or name. |
||
1176 | if ( next->value.empty() && next->name.empty() ) |
||
1177 | return 0; |
||
1178 | return next; |
||
1179 | } |
||
1180 | |||
1181 | /* |
||
1182 | TiXmlAttribute* TiXmlAttribute::Next() |
||
1183 | { |
||
1184 | // We are using knowledge of the sentinel. The sentinel |
||
1185 | // have a value or name. |
||
1186 | if ( next->value.empty() && next->name.empty() ) |
||
1187 | return 0; |
||
1188 | return next; |
||
1189 | } |
||
1190 | */ |
||
1191 | |||
1192 | const TiXmlAttribute* TiXmlAttribute::Previous() const |
||
1193 | { |
||
1194 | // We are using knowledge of the sentinel. The sentinel |
||
1195 | // have a value or name. |
||
1196 | if ( prev->value.empty() && prev->name.empty() ) |
||
1197 | return 0; |
||
1198 | return prev; |
||
1199 | } |
||
1200 | |||
1201 | /* |
||
1202 | TiXmlAttribute* TiXmlAttribute::Previous() |
||
1203 | { |
||
1204 | // We are using knowledge of the sentinel. The sentinel |
||
1205 | // have a value or name. |
||
1206 | if ( prev->value.empty() && prev->name.empty() ) |
||
1207 | return 0; |
||
1208 | return prev; |
||
1209 | } |
||
1210 | */ |
||
1211 | |||
1212 | void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const |
||
1213 | { |
||
1214 | TIXML_STRING n, v; |
||
1215 | |||
1216 | EncodeString( name, &n ); |
||
1217 | EncodeString( value, &v ); |
||
1218 | |||
1219 | if (value.find ('\"') == TIXML_STRING::npos) { |
||
1220 | if ( cfile ) { |
||
1221 | fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); |
||
1222 | } |
||
1223 | if ( str ) { |
||
1224 | (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; |
||
1225 | } |
||
1226 | } |
||
1227 | else { |
||
1228 | if ( cfile ) { |
||
1229 | fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); |
||
1230 | } |
||
1231 | if ( str ) { |
||
1232 | (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; |
||
1233 | } |
||
1234 | } |
||
1235 | } |
||
1236 | |||
1237 | |||
1238 | int TiXmlAttribute::QueryIntValue( int* ival ) const |
||
1239 | { |
||
1240 | if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) |
||
1241 | return TIXML_SUCCESS; |
||
1242 | return TIXML_WRONG_TYPE; |
||
1243 | } |
||
1244 | |||
1245 | int TiXmlAttribute::QueryDoubleValue( double* dval ) const |
||
1246 | { |
||
1247 | if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) |
||
1248 | return TIXML_SUCCESS; |
||
1249 | return TIXML_WRONG_TYPE; |
||
1250 | } |
||
1251 | |||
1252 | void TiXmlAttribute::SetIntValue( int _value ) |
||
1253 | { |
||
1254 | char buf [64]; |
||
1255 | #if defined(TIXML_SNPRINTF) |
||
1256 | TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); |
||
1257 | #else |
||
1258 | sprintf (buf, "%d", _value); |
||
1259 | #endif |
||
1260 | SetValue (buf); |
||
1261 | } |
||
1262 | |||
1263 | void TiXmlAttribute::SetDoubleValue( double _value ) |
||
1264 | { |
||
1265 | char buf [256]; |
||
1266 | #if defined(TIXML_SNPRINTF) |
||
1267 | TIXML_SNPRINTF( buf, sizeof(buf), "%f", _value); |
||
1268 | #else |
||
1269 | sprintf (buf, "%f", _value); |
||
1270 | #endif |
||
1271 | SetValue (buf); |
||
1272 | } |
||
1273 | |||
1274 | int TiXmlAttribute::IntValue() const |
||
1275 | { |
||
1276 | return atoi (value.c_str ()); |
||
1277 | } |
||
1278 | |||
1279 | double TiXmlAttribute::DoubleValue() const |
||
1280 | { |
||
1281 | return atof (value.c_str ()); |
||
1282 | } |
||
1283 | |||
1284 | |||
1285 | TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) |
||
1286 | { |
||
1287 | copy.CopyTo( this ); |
||
1288 | } |
||
1289 | |||
1290 | |||
1291 | void TiXmlComment::operator=( const TiXmlComment& base ) |
||
1292 | { |
||
1293 | Clear(); |
||
1294 | base.CopyTo( this ); |
||
1295 | } |
||
1296 | |||
1297 | |||
1298 | void TiXmlComment::Print( FILE* cfile, int depth ) const |
||
1299 | { |
||
1300 | assert( cfile ); |
||
1301 | for ( int i=0; i |
||
1302 | { |
||
1303 | fprintf( cfile, " " ); |
||
1304 | } |
||
1305 | fprintf( cfile, "", value.c_str() ); |
||
1306 | } |
||
1307 | |||
1308 | |||
1309 | void TiXmlComment::CopyTo( TiXmlComment* target ) const |
||
1310 | { |
||
1311 | TiXmlNode::CopyTo( target ); |
||
1312 | } |
||
1313 | |||
1314 | |||
1315 | bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const |
||
1316 | { |
||
1317 | return visitor->Visit( *this ); |
||
1318 | } |
||
1319 | |||
1320 | |||
1321 | TiXmlNode* TiXmlComment::Clone() const |
||
1322 | { |
||
1323 | TiXmlComment* clone = new TiXmlComment(); |
||
1324 | |||
1325 | if ( !clone ) |
||
1326 | return 0; |
||
1327 | |||
1328 | CopyTo( clone ); |
||
1329 | return clone; |
||
1330 | } |
||
1331 | |||
1332 | |||
1333 | void TiXmlText::Print( FILE* cfile, int depth ) const |
||
1334 | { |
||
1335 | assert( cfile ); |
||
1336 | if ( cdata ) |
||
1337 | { |
||
1338 | int i; |
||
1339 | fprintf( cfile, "\n" ); |
||
1340 | for ( i=0; i |
||
1341 | fprintf( cfile, " " ); |
||
1342 | } |
||
1343 | fprintf( cfile, "\n", value.c_str() ); // unformatted output |
||
1344 | } |
||
1345 | else |
||
1346 | { |
||
1347 | TIXML_STRING buffer; |
||
1348 | EncodeString( value, &buffer ); |
||
1349 | fprintf( cfile, "%s", buffer.c_str() ); |
||
1350 | } |
||
1351 | } |
||
1352 | |||
1353 | |||
1354 | void TiXmlText::CopyTo( TiXmlText* target ) const |
||
1355 | { |
||
1356 | TiXmlNode::CopyTo( target ); |
||
1357 | target->cdata = cdata; |
||
1358 | } |
||
1359 | |||
1360 | |||
1361 | bool TiXmlText::Accept( TiXmlVisitor* visitor ) const |
||
1362 | { |
||
1363 | return visitor->Visit( *this ); |
||
1364 | } |
||
1365 | |||
1366 | |||
1367 | TiXmlNode* TiXmlText::Clone() const |
||
1368 | { |
||
1369 | TiXmlText* clone = 0; |
||
1370 | clone = new TiXmlText( "" ); |
||
1371 | |||
1372 | if ( !clone ) |
||
1373 | return 0; |
||
1374 | |||
1375 | CopyTo( clone ); |
||
1376 | return clone; |
||
1377 | } |
||
1378 | |||
1379 | |||
1380 | TiXmlDeclaration::TiXmlDeclaration( const char * _version, |
||
1381 | const char * _encoding, |
||
1382 | const char * _standalone ) |
||
1383 | : TiXmlNode( TiXmlNode::DECLARATION ) |
||
1384 | { |
||
1385 | version = _version; |
||
1386 | encoding = _encoding; |
||
1387 | standalone = _standalone; |
||
1388 | } |
||
1389 | |||
1390 | |||
1391 | #ifdef TIXML_USE_STL |
||
1392 | TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, |
||
1393 | const std::string& _encoding, |
||
1394 | const std::string& _standalone ) |
||
1395 | : TiXmlNode( TiXmlNode::DECLARATION ) |
||
1396 | { |
||
1397 | version = _version; |
||
1398 | encoding = _encoding; |
||
1399 | standalone = _standalone; |
||
1400 | } |
||
1401 | #endif |
||
1402 | |||
1403 | |||
1404 | TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) |
||
1405 | : TiXmlNode( TiXmlNode::DECLARATION ) |
||
1406 | { |
||
1407 | copy.CopyTo( this ); |
||
1408 | } |
||
1409 | |||
1410 | |||
1411 | void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) |
||
1412 | { |
||
1413 | Clear(); |
||
1414 | copy.CopyTo( this ); |
||
1415 | } |
||
1416 | |||
1417 | |||
1418 | void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const |
||
1419 | { |
||
1420 | if ( cfile ) fprintf( cfile, " |
||
1421 | if ( str ) (*str) += " |
||
1422 | |||
1423 | if ( !version.empty() ) { |
||
1424 | if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); |
||
1425 | if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; } |
||
1426 | } |
||
1427 | if ( !encoding.empty() ) { |
||
1428 | if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); |
||
1429 | if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; } |
||
1430 | } |
||
1431 | if ( !standalone.empty() ) { |
||
1432 | if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); |
||
1433 | if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; } |
||
1434 | } |
||
1435 | if ( cfile ) fprintf( cfile, "?>" ); |
||
1436 | if ( str ) (*str) += "?>"; |
||
1437 | } |
||
1438 | |||
1439 | |||
1440 | void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const |
||
1441 | { |
||
1442 | TiXmlNode::CopyTo( target ); |
||
1443 | |||
1444 | target->version = version; |
||
1445 | target->encoding = encoding; |
||
1446 | target->standalone = standalone; |
||
1447 | } |
||
1448 | |||
1449 | |||
1450 | bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const |
||
1451 | { |
||
1452 | return visitor->Visit( *this ); |
||
1453 | } |
||
1454 | |||
1455 | |||
1456 | TiXmlNode* TiXmlDeclaration::Clone() const |
||
1457 | { |
||
1458 | TiXmlDeclaration* clone = new TiXmlDeclaration(); |
||
1459 | |||
1460 | if ( !clone ) |
||
1461 | return 0; |
||
1462 | |||
1463 | CopyTo( clone ); |
||
1464 | return clone; |
||
1465 | } |
||
1466 | |||
1467 | |||
1468 | void TiXmlUnknown::Print( FILE* cfile, int depth ) const |
||
1469 | { |
||
1470 | for ( int i=0; i |
||
1471 | fprintf( cfile, " " ); |
||
1472 | fprintf( cfile, "<%s>", value.c_str() ); |
||
1473 | } |
||
1474 | |||
1475 | |||
1476 | void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const |
||
1477 | { |
||
1478 | TiXmlNode::CopyTo( target ); |
||
1479 | } |
||
1480 | |||
1481 | |||
1482 | bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const |
||
1483 | { |
||
1484 | return visitor->Visit( *this ); |
||
1485 | } |
||
1486 | |||
1487 | |||
1488 | TiXmlNode* TiXmlUnknown::Clone() const |
||
1489 | { |
||
1490 | TiXmlUnknown* clone = new TiXmlUnknown(); |
||
1491 | |||
1492 | if ( !clone ) |
||
1493 | return 0; |
||
1494 | |||
1495 | CopyTo( clone ); |
||
1496 | return clone; |
||
1497 | } |
||
1498 | |||
1499 | |||
1500 | TiXmlAttributeSet::TiXmlAttributeSet() |
||
1501 | { |
||
1502 | sentinel.next = &sentinel; |
||
1503 | sentinel.prev = &sentinel; |
||
1504 | } |
||
1505 | |||
1506 | |||
1507 | TiXmlAttributeSet::~TiXmlAttributeSet() |
||
1508 | { |
||
1509 | assert( sentinel.next == &sentinel ); |
||
1510 | assert( sentinel.prev == &sentinel ); |
||
1511 | } |
||
1512 | |||
1513 | |||
1514 | void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) |
||
1515 | { |
||
1516 | #ifdef TIXML_USE_STL |
||
1517 | assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. |
||
1518 | #else |
||
1519 | assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. |
||
1520 | #endif |
||
1521 | |||
1522 | addMe->next = &sentinel; |
||
1523 | addMe->prev = sentinel.prev; |
||
1524 | |||
1525 | sentinel.prev->next = addMe; |
||
1526 | sentinel.prev = addMe; |
||
1527 | } |
||
1528 | |||
1529 | void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) |
||
1530 | { |
||
1531 | TiXmlAttribute* node; |
||
1532 | |||
1533 | for( node = sentinel.next; node != &sentinel; node = node->next ) |
||
1534 | { |
||
1535 | if ( node == removeMe ) |
||
1536 | { |
||
1537 | node->prev->next = node->next; |
||
1538 | node->next->prev = node->prev; |
||
1539 | node->next = 0; |
||
1540 | node->prev = 0; |
||
1541 | return; |
||
1542 | } |
||
1543 | } |
||
1544 | assert( 0 ); // we tried to remove a non-linked attribute. |
||
1545 | } |
||
1546 | |||
1547 | |||
1548 | #ifdef TIXML_USE_STL |
||
1549 | const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const |
||
1550 | { |
||
1551 | for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) |
||
1552 | { |
||
1553 | if ( node->name == name ) |
||
1554 | return node; |
||
1555 | } |
||
1556 | return 0; |
||
1557 | } |
||
1558 | |||
1559 | /* |
||
1560 | TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) |
||
1561 | { |
||
1562 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) |
||
1563 | { |
||
1564 | if ( node->name == name ) |
||
1565 | return node; |
||
1566 | } |
||
1567 | return 0; |
||
1568 | } |
||
1569 | */ |
||
1570 | #endif |
||
1571 | |||
1572 | |||
1573 | const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const |
||
1574 | { |
||
1575 | for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) |
||
1576 | { |
||
1577 | if ( strcmp( node->name.c_str(), name ) == 0 ) |
||
1578 | return node; |
||
1579 | } |
||
1580 | return 0; |
||
1581 | } |
||
1582 | |||
1583 | /* |
||
1584 | TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) |
||
1585 | { |
||
1586 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) |
||
1587 | { |
||
1588 | if ( strcmp( node->name.c_str(), name ) == 0 ) |
||
1589 | return node; |
||
1590 | } |
||
1591 | return 0; |
||
1592 | } |
||
1593 | */ |
||
1594 | |||
1595 | #ifdef TIXML_USE_STL |
||
1596 | std::istream& operator>> (std::istream & in, TiXmlNode & base) |
||
1597 | { |
||
1598 | TIXML_STRING tag; |
||
1599 | tag.reserve( 8 * 1000 ); |
||
1600 | base.StreamIn( &in, &tag ); |
||
1601 | |||
1602 | base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); |
||
1603 | return in; |
||
1604 | } |
||
1605 | #endif |
||
1606 | |||
1607 | |||
1608 | #ifdef TIXML_USE_STL |
||
1609 | std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) |
||
1610 | { |
||
1611 | TiXmlPrinter printer; |
||
1612 | printer.SetStreamPrinting(); |
||
1613 | base.Accept( &printer ); |
||
1614 | out << printer.Str(); |
||
1615 | |||
1616 | return out; |
||
1617 | } |
||
1618 | |||
1619 | |||
1620 | std::string& operator<< (std::string& out, const TiXmlNode& base ) |
||
1621 | { |
||
1622 | TiXmlPrinter printer; |
||
1623 | printer.SetStreamPrinting(); |
||
1624 | base.Accept( &printer ); |
||
1625 | out.append( printer.Str() ); |
||
1626 | |||
1627 | return out; |
||
1628 | } |
||
1629 | #endif |
||
1630 | |||
1631 | |||
1632 | TiXmlHandle TiXmlHandle::FirstChild() const |
||
1633 | { |
||
1634 | if ( node ) |
||
1635 | { |
||
1636 | TiXmlNode* child = node->FirstChild(); |
||
1637 | if ( child ) |
||
1638 | return TiXmlHandle( child ); |
||
1639 | } |
||
1640 | return TiXmlHandle( 0 ); |
||
1641 | } |
||
1642 | |||
1643 | |||
1644 | TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const |
||
1645 | { |
||
1646 | if ( node ) |
||
1647 | { |
||
1648 | TiXmlNode* child = node->FirstChild( value ); |
||
1649 | if ( child ) |
||
1650 | return TiXmlHandle( child ); |
||
1651 | } |
||
1652 | return TiXmlHandle( 0 ); |
||
1653 | } |
||
1654 | |||
1655 | |||
1656 | TiXmlHandle TiXmlHandle::FirstChildElement() const |
||
1657 | { |
||
1658 | if ( node ) |
||
1659 | { |
||
1660 | TiXmlElement* child = node->FirstChildElement(); |
||
1661 | if ( child ) |
||
1662 | return TiXmlHandle( child ); |
||
1663 | } |
||
1664 | return TiXmlHandle( 0 ); |
||
1665 | } |
||
1666 | |||
1667 | |||
1668 | TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const |
||
1669 | { |
||
1670 | if ( node ) |
||
1671 | { |
||
1672 | TiXmlElement* child = node->FirstChildElement( value ); |
||
1673 | if ( child ) |
||
1674 | return TiXmlHandle( child ); |
||
1675 | } |
||
1676 | return TiXmlHandle( 0 ); |
||
1677 | } |
||
1678 | |||
1679 | |||
1680 | TiXmlHandle TiXmlHandle::Child( int count ) const |
||
1681 | { |
||
1682 | if ( node ) |
||
1683 | { |
||
1684 | int i; |
||
1685 | TiXmlNode* child = node->FirstChild(); |
||
1686 | for ( i=0; |
||
1687 | child && i |
||
1688 | child = child->NextSibling(), ++i ) |
||
1689 | { |
||
1690 | // nothing |
||
1691 | } |
||
1692 | if ( child ) |
||
1693 | return TiXmlHandle( child ); |
||
1694 | } |
||
1695 | return TiXmlHandle( 0 ); |
||
1696 | } |
||
1697 | |||
1698 | |||
1699 | TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const |
||
1700 | { |
||
1701 | if ( node ) |
||
1702 | { |
||
1703 | int i; |
||
1704 | TiXmlNode* child = node->FirstChild( value ); |
||
1705 | for ( i=0; |
||
1706 | child && i |
||
1707 | child = child->NextSibling( value ), ++i ) |
||
1708 | { |
||
1709 | // nothing |
||
1710 | } |
||
1711 | if ( child ) |
||
1712 | return TiXmlHandle( child ); |
||
1713 | } |
||
1714 | return TiXmlHandle( 0 ); |
||
1715 | } |
||
1716 | |||
1717 | |||
1718 | TiXmlHandle TiXmlHandle::ChildElement( int count ) const |
||
1719 | { |
||
1720 | if ( node ) |
||
1721 | { |
||
1722 | int i; |
||
1723 | TiXmlElement* child = node->FirstChildElement(); |
||
1724 | for ( i=0; |
||
1725 | child && i |
||
1726 | child = child->NextSiblingElement(), ++i ) |
||
1727 | { |
||
1728 | // nothing |
||
1729 | } |
||
1730 | if ( child ) |
||
1731 | return TiXmlHandle( child ); |
||
1732 | } |
||
1733 | return TiXmlHandle( 0 ); |
||
1734 | } |
||
1735 | |||
1736 | |||
1737 | TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const |
||
1738 | { |
||
1739 | if ( node ) |
||
1740 | { |
||
1741 | int i; |
||
1742 | TiXmlElement* child = node->FirstChildElement( value ); |
||
1743 | for ( i=0; |
||
1744 | child && i |
||
1745 | child = child->NextSiblingElement( value ), ++i ) |
||
1746 | { |
||
1747 | // nothing |
||
1748 | } |
||
1749 | if ( child ) |
||
1750 | return TiXmlHandle( child ); |
||
1751 | } |
||
1752 | return TiXmlHandle( 0 ); |
||
1753 | } |
||
1754 | |||
1755 | |||
1756 | bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) |
||
1757 | { |
||
1758 | return true; |
||
1759 | } |
||
1760 | |||
1761 | bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) |
||
1762 | { |
||
1763 | return true; |
||
1764 | } |
||
1765 | |||
1766 | bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) |
||
1767 | { |
||
1768 | DoIndent(); |
||
1769 | buffer += "<"; |
||
1770 | buffer += element.Value(); |
||
1771 | |||
1772 | for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) |
||
1773 | { |
||
1774 | buffer += " "; |
||
1775 | attrib->Print( 0, 0, &buffer ); |
||
1776 | } |
||
1777 | |||
1778 | if ( !element.FirstChild() ) |
||
1779 | { |
||
1780 | buffer += " />"; |
||
1781 | DoLineBreak(); |
||
1782 | } |
||
1783 | else |
||
1784 | { |
||
1785 | buffer += ">"; |
||
1786 | if ( element.FirstChild()->ToText() |
||
1787 | && element.LastChild() == element.FirstChild() |
||
1788 | && element.FirstChild()->ToText()->CDATA() == false ) |
||
1789 | { |
||
1790 | simpleTextPrint = true; |
||
1791 | // no DoLineBreak()! |
||
1792 | } |
||
1793 | else |
||
1794 | { |
||
1795 | DoLineBreak(); |
||
1796 | } |
||
1797 | } |
||
1798 | ++depth; |
||
1799 | return true; |
||
1800 | } |
||
1801 | |||
1802 | |||
1803 | bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) |
||
1804 | { |
||
1805 | --depth; |
||
1806 | if ( !element.FirstChild() ) |
||
1807 | { |
||
1808 | // nothing. |
||
1809 | } |
||
1810 | else |
||
1811 | { |
||
1812 | if ( simpleTextPrint ) |
||
1813 | { |
||
1814 | simpleTextPrint = false; |
||
1815 | } |
||
1816 | else |
||
1817 | { |
||
1818 | DoIndent(); |
||
1819 | } |
||
1820 | buffer += ""; |
||
1821 | buffer += element.Value(); |
||
1822 | buffer += ">"; |
||
1823 | DoLineBreak(); |
||
1824 | } |
||
1825 | return true; |
||
1826 | } |
||
1827 | |||
1828 | |||
1829 | bool TiXmlPrinter::Visit( const TiXmlText& text ) |
||
1830 | { |
||
1831 | if ( text.CDATA() ) |
||
1832 | { |
||
1833 | DoIndent(); |
||
1834 | buffer += " |
||
1835 | buffer += text.Value(); |
||
1836 | buffer += "]]>"; |
||
1837 | DoLineBreak(); |
||
1838 | } |
||
1839 | else if ( simpleTextPrint ) |
||
1840 | { |
||
1841 | TIXML_STRING str; |
||
1842 | TiXmlBase::EncodeString( text.ValueTStr(), &str ); |
||
1843 | buffer += str; |
||
1844 | } |
||
1845 | else |
||
1846 | { |
||
1847 | DoIndent(); |
||
1848 | TIXML_STRING str; |
||
1849 | TiXmlBase::EncodeString( text.ValueTStr(), &str ); |
||
1850 | buffer += str; |
||
1851 | DoLineBreak(); |
||
1852 | } |
||
1853 | return true; |
||
1854 | } |
||
1855 | |||
1856 | |||
1857 | bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) |
||
1858 | { |
||
1859 | DoIndent(); |
||
1860 | declaration.Print( 0, 0, &buffer ); |
||
1861 | DoLineBreak(); |
||
1862 | return true; |
||
1863 | } |
||
1864 | |||
1865 | |||
1866 | bool TiXmlPrinter::Visit( const TiXmlComment& comment ) |
||
1867 | { |
||
1868 | DoIndent(); |
||
1869 | buffer += ""; |
||
1872 | DoLineBreak(); |
||
1873 | return true; |
||
1874 | } |
||
1875 | |||
1876 | |||
1877 | bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) |
||
1878 | { |
||
1879 | DoIndent(); |
||
1880 | buffer += "<"; |
||
1881 | buffer += unknown.Value(); |
||
1882 | buffer += ">"; |
||
1883 | DoLineBreak(); |
||
1884 | return true; |
||
1885 | }"; |
||
1886 |