1 /*
2 www.sourceforge.net/projects/tinyxml
3 Original code (2.0 and earlier )copyright (c) 2000-2002 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 
26 #ifndef TINYXML_INCLUDED
27 #define TINYXML_INCLUDED
28 
29 #ifdef _MSC_VER
30 #pragma warning( disable : 4530 )
31 #pragma warning( disable : 4786 )
32 #endif
33 
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <assert.h>
39 
40 #include "cal3d/platform.h"
41 
42 // Help out windows:
43 #if defined( _DEBUG ) && !defined( DEBUG )
44 #define DEBUG
45 #endif
46 
47 #if defined( DEBUG ) && defined( _MSC_VER )
48 #include <windows.h>
49 #define TIXML_LOG OutputDebugString
50 #else
51 #define TIXML_LOG printf
52 #endif
53 
54 #define TIXML_USE_STL
55 
56 #ifdef TIXML_USE_STL
57 	#include <string>
58  	#include <iostream>
59 	#define TIXML_STRING	std::string
60 	#define TIXML_ISTREAM	std::istream
61 	#define TIXML_OSTREAM	std::ostream
62 #else
63 	#include "tinystr.h"
64 	#define TIXML_STRING	TiXmlString
65 	#define TIXML_OSTREAM	TiXmlOutStream
66 #endif
67 
68 namespace cal3d
69 {
70 
71     class TiXmlDocument;
72     class TiXmlElement;
73     class TiXmlComment;
74     class TiXmlUnknown;
75     class TiXmlAttribute;
76     class TiXmlText;
77     class TiXmlDeclaration;
78 
79     class TiXmlParsingData;
80 
81     /*	Internal structure for tracking location of items
82 	    in the XML file.
83     */
84     struct CAL3D_API TiXmlCursor
85     {
TiXmlCursorTiXmlCursor86 	    TiXmlCursor()		{ Clear(); }
ClearTiXmlCursor87 	    void Clear()		{ row = col = -1; }
88 
89 	    int row;	// 0 based.
90 	    int col;	// 0 based.
91     };
92 
93 
94     // Only used by Attribute::Query functions
95     enum
96     {
97 	    TIXML_SUCCESS,
98 	    TIXML_NO_ATTRIBUTE,
99 	    TIXML_WRONG_TYPE
100     };
101 
102     /** TiXmlBase is a base class for every class in TinyXml.
103 	    It does little except to establish that TinyXml classes
104 	    can be printed and provide some utility functions.
105 
106 	    In XML, the document and elements can contain
107 	    other elements and other types of nodes.
108 
109 	    @verbatim
110 	    A Document can contain:	Element	(container or leaf)
111 							    Comment (leaf)
112 							    Unknown (leaf)
113 							    Declaration( leaf )
114 
115 	    An Element can contain:	Element (container or leaf)
116 							    Text	(leaf)
117 							    Attributes (not on tree)
118 							    Comment (leaf)
119 							    Unknown (leaf)
120 
121 	    A Decleration contains: Attributes (not on tree)
122 	    @endverbatim
123     */
124     class CAL3D_API TiXmlBase
125     {
126 	    friend class TiXmlNode;
127 	    friend class TiXmlElement;
128 	    friend class TiXmlDocument;
129 
130     public:
TiXmlBase()131 	    TiXmlBase()								{}
~TiXmlBase()132 	    virtual ~TiXmlBase()					{}
133 
134 	    /**	All TinyXml classes can print themselves to a filestream.
135 		    This is a formatted print, and will insert tabs and newlines.
136 
137 		    (For an unformatted stream, use the << operator.)
138 	    */
139 	    virtual void Print( FILE* cfile, int depth ) const = 0;
140 
141 	    /**	The world does not agree on whether white space should be kept or
142 		    not. In order to make everyone happy, these global, static functions
143 		    are provided to set whether or not TinyXml will condense all white space
144 		    into a single space or not. The default is to condense. Note changing this
145 		    values is not thread safe.
146 	    */
SetCondenseWhiteSpace(bool condense)147 	    static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }
148 
149 	    /// Return the current white space setting.
IsWhiteSpaceCondensed()150 	    static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }
151 
152 	    /** Return the position, in the original source file, of this node or attribute.
153 		    The row and column are 1-based. (That is the first row and first column is
154 		    1,1). If the returns values are 0 or less, then the parser does not have
155 		    a row and column value.
156 
157 		    Generally, the row and column value will be set when the TiXmlDocument::Load(),
158 		    TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
159 		    when the DOM was created from operator>>.
160 
161 		    The values reflect the initial load. Once the DOM is modified programmatically
162 		    (by adding or changing nodes and attributes) the new values will NOT update to
163 		    reflect changes in the document.
164 
165 		    There is a minor performance cost to computing the row and column. Computation
166 		    can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
167 
168 		    @sa TiXmlDocument::SetTabSize()
169 	    */
Row()170 	    int Row() const			{ return location.row + 1; }
Column()171 	    int Column() const		{ return location.col + 1; }	///< See Row()
172 
173     protected:
174 	    // See STL_STRING_BUG
175 	    // Utility class to overcome a bug.
176 	    class StringToBuffer
177 	    {
178 	    public:
179 		    StringToBuffer( const TIXML_STRING& str );
180 		    ~StringToBuffer();
181 		    char* buffer;
182 	    };
183 
184 	    static const char*	SkipWhiteSpace( const char* );
IsWhiteSpace(int c)185 	    inline static bool	IsWhiteSpace( int c )		{ return ( isspace( c ) || c == '\n' || c == '\r' ); }
186 
187 	    virtual void StreamOut (TIXML_OSTREAM *) const = 0;
188 
189 	    #ifdef TIXML_USE_STL
190 	        static bool	StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
191 	        static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
192 	    #endif
193 
194 	    /*	Reads an XML name into the string provided. Returns
195 		    a pointer just past the last character of the name,
196 		    or 0 if the function has an error.
197 	    */
198 	    static const char* ReadName( const char* p, TIXML_STRING* name );
199 
200 	    /*	Reads text. Returns a pointer past the given end tag.
201 		    Wickedly complex options, but it keeps the (sensitive) code in one place.
202 	    */
203 	    static const char* ReadText(	const char* in,				// where to start
204 									    TIXML_STRING* text,			// the string read
205 									    bool ignoreWhiteSpace,		// whether to keep the white space
206 									    const char* endTag,			// what ends this text
207 									    bool ignoreCase );			// whether to ignore case in the end tag
208 
209 	    virtual const char* Parse( const char* p, TiXmlParsingData* data ) = 0;
210 
211 	    // If an entity has been found, transform it into a character.
212 	    static const char* GetEntity( const char* in, char* value );
213 
214 	    // Get a character, while interpreting entities.
GetChar(const char * p,char * _value)215 	    inline static const char* GetChar( const char* p, char* _value )
216 	    {
217 		    assert( p );
218 		    if ( *p == '&' )
219 		    {
220 			    return GetEntity( p, _value );
221 		    }
222 		    else
223 		    {
224 			    *_value = *p;
225 			    return p+1;
226 		    }
227 	    }
228 
229 	    // Puts a string to a stream, expanding entities as it goes.
230 	    // Note this should not contian the '<', '>', etc, or they will be transformed into entities!
231 	    static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
232 
233 	    static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
234 
235 	    // Return true if the next characters in the stream are any of the endTag sequences.
236 	    static bool StringEqual(	const char* p,
237 								    const char* endTag,
238 								    bool ignoreCase );
239 
240 
241 	    enum
242 	    {
243 		    TIXML_NO_ERROR = 0,
244 		    TIXML_ERROR,
245 		    TIXML_ERROR_OPENING_FILE,
246 		    TIXML_ERROR_OUT_OF_MEMORY,
247 		    TIXML_ERROR_PARSING_ELEMENT,
248 		    TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
249 		    TIXML_ERROR_READING_ELEMENT_VALUE,
250 		    TIXML_ERROR_READING_ATTRIBUTES,
251 		    TIXML_ERROR_PARSING_EMPTY,
252 		    TIXML_ERROR_READING_END_TAG,
253 		    TIXML_ERROR_PARSING_UNKNOWN,
254 		    TIXML_ERROR_PARSING_COMMENT,
255 		    TIXML_ERROR_PARSING_DECLARATION,
256 		    TIXML_ERROR_DOCUMENT_EMPTY,
257 
258 		    TIXML_ERROR_STRING_COUNT
259 	    };
260 	    static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
261 
262 	    TiXmlCursor location;
263 
264     private:
265 	    struct Entity
266 	    {
267 		    const char*     str;
268 		    unsigned int	strLength;
269 		    char		    chr;
270 	    };
271 	    enum
272 	    {
273 		    NUM_ENTITY = 5,
274 		    MAX_ENTITY_LENGTH = 6
275 
276 	    };
277 	    static Entity entity[ NUM_ENTITY ];
278 	    static bool condenseWhiteSpace;
279     };
280 
281 
282     /** The parent class for everything in the Document Object Model.
283 	    (Except for attributes).
284 	    Nodes have siblings, a parent, and children. A node can be
285 	    in a document, or stand on its own. The type of a TiXmlNode
286 	    can be queried, and it can be cast to its more defined type.
287     */
288     class CAL3D_API TiXmlNode : public TiXmlBase
289     {
290 	    friend class TiXmlDocument;
291 	    friend class TiXmlElement;
292 
293     public:
294 	    #ifdef TIXML_USE_STL
295 
296 	        /** An input stream operator, for every class. Tolerant of newlines and
297 		        formatting, but doesn't expect them.
298 	        */
299 	        friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
300 
301 	        /** An output stream operator, for every class. Note that this outputs
302 		        without any newlines or formatting, as opposed to Print(), which
303 		        includes tabs and new lines.
304 
305 		        The operator<< and operator>> are not completely symmetric. Writing
306 		        a node to a stream is very well defined. You'll get a nice stream
307 		        of output, without any extra whitespace or newlines.
308 
309 		        But reading is not as well defined. (As it always is.) If you create
310 		        a TiXmlElement (for example) and read that from an input stream,
311 		        the text needs to define an element or junk will result. This is
312 		        true of all input streams, but it's worth keeping in mind.
313 
314 		        A TiXmlDocument will read nodes until it reads a root element, and
315 			    all the children of that root element.
316 	        */
317 	        friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
318 
319 		    /// Appends the XML node or attribute to a std::string.
320 		    friend std::string& operator<< (std::string& out, const TiXmlNode& base );
321 
322 	    #else
323 	        // Used internally, not part of the public API.
324 	        friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
325 	    #endif
326 
327 	    /** The types of XML nodes supported by TinyXml. (All the
328 			    unsupported types are picked up by UNKNOWN.)
329 	    */
330 	    enum NodeType
331 	    {
332 		    DOCUMENT,
333 		    ELEMENT,
334 		    COMMENT,
335 		    UNKNOWN,
336 		    TEXT,
337 		    DECLARATION,
338 		    TYPECOUNT
339 	    };
340 
341 	    virtual ~TiXmlNode();
342 
343 	    /** The meaning of 'value' changes for the specific type of
344 		    TiXmlNode.
345 		    @verbatim
346 		    Document:	filename of the xml file
347 		    Element:	name of the element
348 		    Comment:	the comment text
349 		    Unknown:	the tag contents
350 		    Text:		the text string
351 		    @endverbatim
352 
353 		    The subclasses will wrap this function.
354 	    */
Value()355 	    const char * Value() const { return value.c_str (); }
356 
357 	    /** Changes the value of the node. Defined as:
358 		    @verbatim
359 		    Document:	filename of the xml file
360 		    Element:	name of the element
361 		    Comment:	the comment text
362 		    Unknown:	the tag contents
363 		    Text:		the text string
364 		    @endverbatim
365 	    */
SetValue(const char * _value)366 	    void SetValue(const char * _value) { value = _value;}
367 
368         #ifdef TIXML_USE_STL
369 	    /// STL std::string form.
SetValue(const std::string & _value)370 	    void SetValue( const std::string& _value )
371 	    {
372 		    StringToBuffer buf( _value );
373 		    SetValue( buf.buffer ? buf.buffer : "" );
374 	    }
375 	    #endif
376 
377 	    /// Delete all the children of this node. Does not affect 'this'.
378 	    void Clear();
379 
380 	    /// One step up the DOM.
Parent()381 	    TiXmlNode* Parent() const					{ return parent; }
382 
FirstChild()383 	    TiXmlNode* FirstChild()	const	{ return firstChild; }		///< The first child of this node. Will be null if there are no children.
384 	    TiXmlNode* FirstChild( const char * value ) const;			///< The first child of this node with the matching 'value'. Will be null if none found.
385 
LastChild()386 	    TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
387 	    TiXmlNode* LastChild( const char * value ) const;			/// The last child of this node matching 'value'. Will be null if there are no children.
388 
389         #ifdef TIXML_USE_STL
FirstChild(const std::string & _value)390 	    TiXmlNode* FirstChild( const std::string& _value ) const	{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
LastChild(const std::string & _value)391 	    TiXmlNode* LastChild( const std::string& _value ) const		{	return LastChild (_value.c_str ());	}	///< STL std::string form.
392 	    #endif
393 
394 	    /** An alternate way to walk the children of a node.
395 		    One way to iterate over nodes is:
396 		    @verbatim
397 			    for( child = parent->FirstChild(); child; child = child->NextSibling() )
398 		    @endverbatim
399 
400 		    IterateChildren does the same thing with the syntax:
401 		    @verbatim
402 			    child = 0;
403 			    while( child = parent->IterateChildren( child ) )
404 		    @endverbatim
405 
406 		    IterateChildren takes the previous child as input and finds
407 		    the next one. If the previous child is null, it returns the
408 		    first. IterateChildren will return null when done.
409 	    */
410 	    TiXmlNode* IterateChildren( TiXmlNode* previous ) const;
411 
412 	    /// This flavor of IterateChildren searches for children with a particular 'value'
413 	    TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous ) const;
414 
415         #ifdef TIXML_USE_STL
IterateChildren(const std::string & _value,TiXmlNode * previous)416 	    TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) const	{	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
417 	    #endif
418 
419 	    /** Add a new node related to this. Adds a child past the LastChild.
420 		    Returns a pointer to the new object or NULL if an error occured.
421 	    */
422 	    TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
423 
424 
425 	    /** Add a new node related to this. Adds a child past the LastChild.
426 
427 		    NOTE: the node to be added is passed by pointer, and will be
428 		    henceforth owned (and deleted) by tinyXml. This method is efficient
429 		    and avoids an extra copy, but should be used with care as it
430 		    uses a different memory model than the other insert functions.
431 
432 		    @sa InsertEndChild
433 	    */
434 	    TiXmlNode* LinkEndChild( TiXmlNode* addThis );
435 
436 	    /** Add a new node related to this. Adds a child before the specified child.
437 		    Returns a pointer to the new object or NULL if an error occured.
438 	    */
439 	    TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
440 
441 	    /** Add a new node related to this. Adds a child after the specified child.
442 		    Returns a pointer to the new object or NULL if an error occured.
443 	    */
444 	    TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
445 
446 	    /** Replace a child of this node.
447 		    Returns a pointer to the new object or NULL if an error occured.
448 	    */
449 	    TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
450 
451 	    /// Delete a child of this node.
452 	    bool RemoveChild( TiXmlNode* removeThis );
453 
454 	    /// Navigate to a sibling node.
PreviousSibling()455 	    TiXmlNode* PreviousSibling() const			{ return prev; }
456 
457 	    /// Navigate to a sibling node.
458 	    TiXmlNode* PreviousSibling( const char * ) const;
459 
460         #ifdef TIXML_USE_STL
PreviousSibling(const std::string & _value)461 	    TiXmlNode* PreviousSibling( const std::string& _value ) const	{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
NextSibling(const std::string & _value)462 	    TiXmlNode* NextSibling( const std::string& _value) const		{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
463 	    #endif
464 
465 	    /// Navigate to a sibling node.
NextSibling()466 	    TiXmlNode* NextSibling() const				{ return next; }
467 
468 	    /// Navigate to a sibling node with the given 'value'.
469 	    TiXmlNode* NextSibling( const char * ) const;
470 
471 	    /** Convenience function to get through elements.
472 		    Calls NextSibling and ToElement. Will skip all non-Element
473 		    nodes. Returns 0 if there is not another element.
474 	    */
475 	    TiXmlElement* NextSiblingElement() const;
476 
477 	    /** Convenience function to get through elements.
478 		    Calls NextSibling and ToElement. Will skip all non-Element
479 		    nodes. Returns 0 if there is not another element.
480 	    */
481 	    TiXmlElement* NextSiblingElement( const char * ) const;
482 
483         #ifdef TIXML_USE_STL
NextSiblingElement(const std::string & _value)484 	    TiXmlElement* NextSiblingElement( const std::string& _value) const	{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
485 	    #endif
486 
487 	    /// Convenience function to get through elements.
488 	    TiXmlElement* FirstChildElement()	const;
489 
490 	    /// Convenience function to get through elements.
491 	    TiXmlElement* FirstChildElement( const char * value ) const;
492 
493         #ifdef TIXML_USE_STL
FirstChildElement(const std::string & _value)494 	    TiXmlElement* FirstChildElement( const std::string& _value ) const	{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
495 	    #endif
496 
497 	    /** Query the type (as an enumerated value, above) of this node.
498 		    The possible types are: DOCUMENT, ELEMENT, COMMENT,
499 								    UNKNOWN, TEXT, and DECLARATION.
500 	    */
Type()501 	    virtual int Type() const	{ return type; }
502 
503 	    /** Return a pointer to the Document this node lives in.
504 		    Returns null if not in a document.
505 	    */
506 	    TiXmlDocument* GetDocument() const;
507 
508 	    /// Returns true if this node has no children.
NoChildren()509 	    bool NoChildren() const						{ return !firstChild; }
510 
ToDocument()511 	    TiXmlDocument* ToDocument()	const		{ return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToElement()512 	    TiXmlElement*  ToElement() const		{ return ( this && type == ELEMENT  ) ? (TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToComment()513 	    TiXmlComment*  ToComment() const		{ return ( this && type == COMMENT  ) ? (TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToUnknown()514 	    TiXmlUnknown*  ToUnknown() const		{ return ( this && type == UNKNOWN  ) ? (TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToText()515 	    TiXmlText*	   ToText()    const		{ return ( this && type == TEXT     ) ? (TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
ToDeclaration()516 	    TiXmlDeclaration* ToDeclaration() const	{ return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
517 
518 	    virtual TiXmlNode* Clone() const = 0;
519 
SetUserData(void * user)520 	    void  SetUserData( void* user )			{ userData = user; }
GetUserData()521 	    void* GetUserData()						{ return userData; }
522 
523     protected:
524 	    TiXmlNode( NodeType type );
525 
526 	    #ifdef TIXML_USE_STL
527 	        // The real work of the input operator.
528 	        virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
529 	    #endif
530 
531 	    // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
532 	    TiXmlNode* Identify( const char* start );
CopyToClone(TiXmlNode * target)533 	    void CopyToClone( TiXmlNode* target ) const	{ target->SetValue (value.c_str() );
534 												    target->userData = userData; }
535 
536 	    // Internal Value function returning a TIXML_STRING
SValue()537 	    TIXML_STRING SValue() const	{ return value ; }
538 
539 	    TiXmlNode*		parent;
540 	    NodeType		type;
541 
542 	    TiXmlNode*		firstChild;
543 	    TiXmlNode*		lastChild;
544 
545 	    TIXML_STRING	value;
546 
547 	    TiXmlNode*		prev;
548 	    TiXmlNode*		next;
549 	    void*			userData;
550     };
551 
552 
553     /** An attribute is a name-value pair. Elements have an arbitrary
554 	    number of attributes, each with a unique name.
555 
556 	    @note The attributes are not TiXmlNodes, since they are not
557 		    part of the tinyXML document object model. There are other
558 		    suggested ways to look at this problem.
559     */
560     class CAL3D_API TiXmlAttribute : public TiXmlBase
561     {
562 	    friend class TiXmlAttributeSet;
563 
564     public:
565 	    /// Construct an empty attribute.
TiXmlAttribute()566 	    TiXmlAttribute()
567 	    {
568 		    document = 0;
569 		    prev = next = 0;
570 	    }
571 
572 	    #ifdef TIXML_USE_STL
573 	    /// std::string constructor.
TiXmlAttribute(const std::string & _name,const std::string & _value)574 	    TiXmlAttribute( const std::string& _name, const std::string& _value )
575 	    {
576 		    name = _name;
577 		    value = _value;
578 		    document = 0;
579 		    prev = next = 0;
580 	    }
581 	    #endif
582 
583 	    /// Construct an attribute with a name and value.
TiXmlAttribute(const char * _name,const char * _value)584 	    TiXmlAttribute( const char * _name, const char * _value )
585 	    {
586 		    name = _name;
587 		    value = _value;
588 		    document = 0;
589 		    prev = next = 0;
590 	    }
591 
Name()592 	    const char*		Name()  const		{ return name.c_str (); }		///< Return the name of this attribute.
Value()593 	    const char*		Value() const		{ return value.c_str (); }		///< Return the value of this attribute.
594 	    const int       IntValue() const;									///< Return the value of this attribute, converted to an integer.
595 	    const double	DoubleValue() const;								///< Return the value of this attribute, converted to a double.
596 
597 	    /** QueryIntValue examines the value string. It is an alternative to the
598 		    IntValue() method with richer error checking.
599 		    If the value is an integer, it is stored in 'value' and
600 		    the call returns TIXML_SUCCESS. If it is not
601 		    an integer, it returns TIXML_WRONG_TYPE.
602 
603 		    A specialized but useful call. Note that for success it returns 0,
604 		    which is the opposite of almost all other TinyXml calls.
605 	    */
606 	    int QueryIntValue( int* value ) const;
607 	    /// QueryDoubleValue examines the value string. See QueryIntValue().
608 	    int QueryDoubleValue( double* value ) const;
609 
SetName(const char * _name)610 	    void SetName( const char* _name )	{ name = _name; }				///< Set the name of this attribute.
SetValue(const char * _value)611 	    void SetValue( const char* _value )	{ value = _value; }				///< Set the value.
612 
613 	    void SetIntValue( int value );										///< Set the value from an integer.
614 	    void SetDoubleValue( double value );								///< Set the value from a double.
615 
616         #ifdef TIXML_USE_STL
617 	    /// STL std::string form.
SetName(const std::string & _name)618 	    void SetName( const std::string& _name )
619 	    {
620 		    StringToBuffer buf( _name );
621 		    SetName ( buf.buffer ? buf.buffer : "error" );
622 	    }
623 	    /// STL std::string form.
SetValue(const std::string & _value)624 	    void SetValue( const std::string& _value )
625 	    {
626 		    StringToBuffer buf( _value );
627 		    SetValue( buf.buffer ? buf.buffer : "error" );
628 	    }
629 	    #endif
630 
631 	    /// Get the next sibling attribute in the DOM. Returns null at end.
632 	    TiXmlAttribute* Next() const;
633 	    /// Get the previous sibling attribute in the DOM. Returns null at beginning.
634 	    TiXmlAttribute* Previous() const;
635 
636 	    bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
637 	    bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
638 	    bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
639 
640 	    /*	[internal use]
641 		    Attribtue parsing starts: first letter of the name
642 						    returns: the next char after the value end quote
643 	    */
644 	    virtual const char* Parse( const char* p, TiXmlParsingData* data );
645 
646 	    // [internal use]
647 	    virtual void Print( FILE* cfile, int depth ) const;
648 
649 	    virtual void StreamOut( TIXML_OSTREAM * out ) const;
650 	    // [internal use]
651 	    // Set the document pointer so the attribute can report errors.
SetDocument(TiXmlDocument * doc)652 	    void SetDocument( TiXmlDocument* doc )	{ document = doc; }
653 
654     private:
655 	    TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
656 	    TIXML_STRING name;
657 	    TIXML_STRING value;
658 	    TiXmlAttribute*	prev;
659 	    TiXmlAttribute*	next;
660     };
661 
662 
663     /*	A class used to manage a group of attributes.
664 	    It is only used internally, both by the ELEMENT and the DECLARATION.
665 
666 	    The set can be changed transparent to the Element and Declaration
667 	    classes that use it, but NOT transparent to the Attribute
668 	    which has to implement a next() and previous() method. Which makes
669 	    it a bit problematic and prevents the use of STL.
670 
671 	    This version is implemented with circular lists because:
672 		    - I like circular lists
673 		    - it demonstrates some independence from the (typical) doubly linked list.
674     */
675     class CAL3D_API TiXmlAttributeSet
676     {
677     public:
678 	    TiXmlAttributeSet();
679 	    ~TiXmlAttributeSet();
680 
681 	    void Add( TiXmlAttribute* attribute );
682 	    void Remove( TiXmlAttribute* attribute );
683 
First()684 	    TiXmlAttribute* First() const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
Last()685 	    TiXmlAttribute* Last()  const	{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
686 	    TiXmlAttribute*	Find( const char * name ) const;
687 
688     private:
689 	    TiXmlAttribute sentinel;
690     };
691 
692 
693     /** The element is a container class. It has a value, the element name,
694 	    and can contain other elements, text, comments, and unknowns.
695 	    Elements also contain an arbitrary number of attributes.
696     */
697     class CAL3D_API TiXmlElement : public TiXmlNode
698     {
699     public:
700 	    /// Construct an element.
701 	    TiXmlElement (const char * in_value);
702 
703 	    #ifdef TIXML_USE_STL
704 	    /// std::string constructor.
TiXmlElement(const std::string & _value)705 	    TiXmlElement( const std::string& _value ) : 	TiXmlNode( TiXmlNode::ELEMENT )
706 	    {
707 		    firstChild = lastChild = 0;
708 		    value = _value;
709 	    }
710 	    #endif
711 
712 	    virtual ~TiXmlElement();
713 
714 	    /** Given an attribute name, Attribute() returns the value
715 		    for the attribute of that name, or null if none exists.
716 	    */
717 	    const char* Attribute( const char* name ) const;
718 
719 	    /** Given an attribute name, Attribute() returns the value
720 		    for the attribute of that name, or null if none exists.
721 		    If the attribute exists and can be converted to an integer,
722 		    the integer value will be put in the return 'i', if 'i'
723 		    is non-null.
724 	    */
725 	    const char* Attribute( const char* name, int* i ) const;
726 
727 	    /** Given an attribute name, Attribute() returns the value
728 		    for the attribute of that name, or null if none exists.
729 		    If the attribute exists and can be converted to an double,
730 		    the double value will be put in the return 'd', if 'd'
731 		    is non-null.
732 	    */
733 	    const char* Attribute( const char* name, double* d ) const;
734 
735 	    /** QueryIntAttribute examines the attribute - it is an alternative to the
736 		    Attribute() method with richer error checking.
737 		    If the attribute is an integer, it is stored in 'value' and
738 		    the call returns TIXML_SUCCESS. If it is not
739 		    an integer, it returns TIXML_WRONG_TYPE. If the attribute
740 		    does not exist, then TIXML_NO_ATTRIBUTE is returned.
741 	    */
742 	    int QueryIntAttribute( const char* name, int* value ) const;
743 	    /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
744 	    int QueryDoubleAttribute( const char* name, double* value ) const;
745 
746 	    /** Sets an attribute of name to a given value. The attribute
747 		    will be created if it does not exist, or changed if it does.
748 	    */
749 	    void SetAttribute( const char* name, const char * value );
750 
751         #ifdef TIXML_USE_STL
Attribute(const std::string & name)752 	    const char* Attribute( const std::string& name ) const				{ return Attribute( name.c_str() ); }
Attribute(const std::string & name,int * i)753 	    const char* Attribute( const std::string& name, int* i ) const		{ return Attribute( name.c_str(), i ); }
754 
755 	    /// STL std::string form.
SetAttribute(const std::string & name,const std::string & _value)756 	    void SetAttribute( const std::string& name, const std::string& _value )
757 	    {
758 		    StringToBuffer n( name );
759 		    StringToBuffer v( _value );
760 		    if ( n.buffer && v.buffer )
761 			    SetAttribute (n.buffer, v.buffer );
762 	    }
763 	    ///< STL std::string form.
SetAttribute(const std::string & name,int _value)764 	    void SetAttribute( const std::string& name, int _value )
765 	    {
766 		    StringToBuffer n( name );
767 		    if ( n.buffer )
768 			    SetAttribute (n.buffer, _value);
769 	    }
770 	    #endif
771 
772 	    /** Sets an attribute of name to a given value. The attribute
773 		    will be created if it does not exist, or changed if it does.
774 	    */
775 	    void SetAttribute( const char * name, int value );
776 
777 	    /** Deletes an attribute with the given name.
778 	    */
779 	    void RemoveAttribute( const char * name );
780         #ifdef TIXML_USE_STL
RemoveAttribute(const std::string & name)781 	    void RemoveAttribute( const std::string& name )	{	RemoveAttribute (name.c_str ());	}	///< STL std::string form.
782 	    #endif
783 
FirstAttribute()784 	    TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
LastAttribute()785 	    TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.
786 
787 	    // [internal use] Creates a new Element and returs it.
788 	    virtual TiXmlNode* Clone() const;
789 	    // [internal use]
790 
791 	    virtual void Print( FILE* cfile, int depth ) const;
792 
793     protected:
794 
795 	    // Used to be public [internal use]
796 	    #ifdef TIXML_USE_STL
797 	        virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
798 	    #endif
799 	    virtual void StreamOut( TIXML_OSTREAM * out ) const;
800 
801 	    /*	[internal use]
802 		    Attribtue parsing starts: next char past '<'
803 						    returns: next char past '>'
804 	    */
805 	    virtual const char* Parse( const char* p, TiXmlParsingData* data );
806 
807 	    /*	[internal use]
808 		    Reads the "value" of the element -- another element, or text.
809 		    This should terminate with the current end tag.
810 	    */
811 	    const char* ReadValue( const char* in, TiXmlParsingData* prevData );
812 
813     private:
814 	    TiXmlAttributeSet attributeSet;
815     };
816 
817 
818     /**	An XML comment.
819     */
820     class CAL3D_API TiXmlComment : public TiXmlNode
821     {
822     public:
823 	    /// Constructs an empty comment.
TiXmlComment()824 	    TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
~TiXmlComment()825 	    virtual ~TiXmlComment()	{}
826 
827 	    // [internal use] Creates a new Element and returs it.
828 	    virtual TiXmlNode* Clone() const;
829 	    // [internal use]
830 	    virtual void Print( FILE* cfile, int depth ) const;
831     protected:
832 	    // used to be public
833 	    #ifdef TIXML_USE_STL
834 	        virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
835 	    #endif
836 	    virtual void StreamOut( TIXML_OSTREAM * out ) const;
837 	    /*	[internal use]
838 		    Attribtue parsing starts: at the ! of the !--
839 						    returns: next char past '>'
840 	    */
841 	    virtual const char* Parse( const char* p, TiXmlParsingData* data );
842     };
843 
844 
845     /** XML text. Contained in an element.
846     */
847     class CAL3D_API TiXmlText : public TiXmlNode
848     {
849 	    friend class TiXmlElement;
850     public:
851 	    /// Constructor.
TiXmlText(const char * initValue)852 	    TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT)
853 	    {
854 		    SetValue( initValue );
855 	    }
~TiXmlText()856 	    virtual ~TiXmlText() {}
857 
858 	    #ifdef TIXML_USE_STL
859 	    /// Constructor.
TiXmlText(const std::string & initValue)860 	    TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
861 	    {
862 		    SetValue( initValue );
863 	    }
864 	    #endif
865 
866 	    // [internal use]
867 	    virtual void Print( FILE* cfile, int depth ) const;
868 
869     protected :
870 	    // [internal use] Creates a new Element and returns it.
871 	    virtual TiXmlNode* Clone() const;
872 	    virtual void StreamOut ( TIXML_OSTREAM * out ) const;
873 	    // [internal use]
874 	    bool Blank() const;	// returns true if all white space and new lines
875 	    /*	[internal use]
876 			    Attribtue parsing starts: First char of the text
877 							    returns: next char past '>'
878 	    */
879 	    virtual const char* Parse( const char* p, TiXmlParsingData* data );
880 	    // [internal use]
881 	    #ifdef TIXML_USE_STL
882 	        virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
883 	    #endif
884     };
885 
886 
887     /** In correct XML the declaration is the first entry in the file.
888 	    @verbatim
889 		    <?xml version="1.0" standalone="yes"?>
890 	    @endverbatim
891 
892 	    TinyXml will happily read or write files without a declaration,
893 	    however. There are 3 possible attributes to the declaration:
894 	    version, encoding, and standalone.
895 
896 	    Note: In this version of the code, the attributes are
897 	    handled as special cases, not generic attributes, simply
898 	    because there can only be at most 3 and they are always the same.
899     */
900     class CAL3D_API TiXmlDeclaration : public TiXmlNode
901     {
902     public:
903 	    /// Construct an empty declaration.
TiXmlDeclaration()904 	    TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
905 
906     #ifdef TIXML_USE_STL
907 	    /// Constructor.
TiXmlDeclaration(const std::string & _version,const std::string & _encoding,const std::string & _standalone)908 	    TiXmlDeclaration(	const std::string& _version,
909 						    const std::string& _encoding,
910 						    const std::string& _standalone )
911 			    : TiXmlNode( TiXmlNode::DECLARATION )
912 	    {
913 		    version = _version;
914 		    encoding = _encoding;
915 		    standalone = _standalone;
916 	    }
917     #endif
918 
919 	    /// Construct.
920 	    TiXmlDeclaration(	const char* _version,
921 						    const char* _encoding,
922 						    const char* _standalone );
923 
~TiXmlDeclaration()924 	    virtual ~TiXmlDeclaration()	{}
925 
926 	    /// Version. Will return empty if none was found.
Version()927 	    const char * Version() const		{ return version.c_str (); }
928 	    /// Encoding. Will return empty if none was found.
Encoding()929 	    const char * Encoding() const		{ return encoding.c_str (); }
930 	    /// Is this a standalone document?
Standalone()931 	    const char * Standalone() const		{ return standalone.c_str (); }
932 
933 	    // [internal use] Creates a new Element and returs it.
934 	    virtual TiXmlNode* Clone() const;
935 	    // [internal use]
936 	    virtual void Print( FILE* cfile, int depth ) const;
937 
938     protected:
939 	    // used to be public
940 	    #ifdef TIXML_USE_STL
941 	        virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
942 	    #endif
943 	    virtual void StreamOut ( TIXML_OSTREAM * out) const;
944 	    //	[internal use]
945 	    //	Attribtue parsing starts: next char past '<'
946 	    //					 returns: next char past '>'
947 
948 	    virtual const char* Parse( const char* p, TiXmlParsingData* data );
949 
950     private:
951 	    TIXML_STRING version;
952 	    TIXML_STRING encoding;
953 	    TIXML_STRING standalone;
954     };
955 
956 
957     /** Any tag that tinyXml doesn't recognize is saved as an
958 	    unknown. It is a tag of text, but should not be modified.
959 	    It will be written back to the XML, unchanged, when the file
960 	    is saved.
961     */
962     class CAL3D_API TiXmlUnknown : public TiXmlNode
963     {
964     public:
TiXmlUnknown()965 	    TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
~TiXmlUnknown()966 	    virtual ~TiXmlUnknown() {}
967 
968 	    // [internal use]
969 	    virtual TiXmlNode* Clone() const;
970 	    // [internal use]
971 	    virtual void Print( FILE* cfile, int depth ) const;
972     protected:
973 	    #ifdef TIXML_USE_STL
974 	        virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
975 	    #endif
976 	    virtual void StreamOut ( TIXML_OSTREAM * out ) const;
977 	    /*	[internal use]
978 		    Attribute parsing starts: First char of the text
979 						    returns: next char past '>'
980 	    */
981 	    virtual const char* Parse( const char* p, TiXmlParsingData* data );
982     };
983 
984 
985     /** Always the top level node. A document binds together all the
986 	    XML pieces. It can be saved, loaded, and printed to the screen.
987 	    The 'value' of a document node is the xml file name.
988     */
989     class CAL3D_API TiXmlDocument : public TiXmlNode
990     {
991     public:
992 	    /// Create an empty document, that has no name.
993 	    TiXmlDocument();
994 	    /// Create a document with a name. The name of the document is also the filename of the xml.
995 	    TiXmlDocument( const char * documentName );
996 
997 	    #ifdef TIXML_USE_STL
998 	    /// Constructor.
TiXmlDocument(const std::string & documentName)999 	    TiXmlDocument( const std::string& documentName ) :
1000 	        TiXmlNode( TiXmlNode::DOCUMENT )
1001 	    {
1002             tabsize = 4;
1003             value = documentName;
1004 		    error = false;
1005 	    }
1006 	    #endif
1007 
~TiXmlDocument()1008 	    virtual ~TiXmlDocument() {}
1009 
1010 	    /** Load a file using the current document value.
1011 		    Returns true if successful. Will delete any existing
1012 		    document data before loading.
1013 	    */
1014 	    bool LoadFile();
1015 	    /// Save a file using the current document value. Returns true if successful.
1016 	    bool SaveFile() const;
1017 	    /// Load a file using the given filename. Returns true if successful.
1018 	    bool LoadFile( const char * filename );
1019 	    /// Save a file using the given filename. Returns true if successful.
1020 	    bool SaveFile( const char * filename ) const;
1021 
1022 	    #ifdef TIXML_USE_STL
LoadFile(const std::string & filename)1023 	    bool LoadFile( const std::string& filename )			///< STL std::string version.
1024 	    {
1025 		    StringToBuffer f( filename );
1026 		    return ( f.buffer && LoadFile( f.buffer ));
1027 	    }
SaveFile(const std::string & filename)1028 	    bool SaveFile( const std::string& filename ) const		///< STL std::string version.
1029 	    {
1030 		    StringToBuffer f( filename );
1031 		    return ( f.buffer && SaveFile( f.buffer ));
1032 	    }
1033 	    #endif
1034 
1035 	    /** Parse the given null terminated block of xml data.
1036 	    */
1037 	    virtual const char* Parse( const char* p, TiXmlParsingData* data = 0 );
1038 
1039 	    /** Get the root element -- the only top level element -- of the document.
1040 		    In well formed XML, there should only be one. TinyXml is tolerant of
1041 		    multiple elements at the document level.
1042 	    */
RootElement()1043 	    TiXmlElement* RootElement() const		{ return FirstChildElement(); }
1044 
1045 	    /** If an error occurs, Error will be set to true. Also,
1046 		    - The ErrorId() will contain the integer identifier of the error (not generally useful)
1047 		    - The ErrorDesc() method will return the name of the error. (very useful)
1048 		    - The ErrorRow() and ErrorCol() will return the location of the error (if known)
1049 	    */
Error()1050 	    bool Error() const						{ return error; }
1051 
1052 	    /// Contains a textual (english) description of the error if one occurs.
ErrorDesc()1053 	    const char * ErrorDesc() const	{ return errorDesc.c_str (); }
1054 
1055 	    /** Generally, you probably want the error string ( ErrorDesc() ). But if you
1056 		    prefer the ErrorId, this function will fetch it.
1057 	    */
ErrorId()1058 	    const int ErrorId()	const				{ return errorId; }
1059 
1060 	    /** Returns the location (if known) of the error. The first column is column 1,
1061 		    and the first row is row 1. A value of 0 means the row and column wasn't applicable
1062 		    (memory errors, for example, have no row/column) or the parser lost the error. (An
1063 		    error in the error reporting, in that case.)
1064 
1065 		    @sa SetTabSize, Row, Column
1066 	    */
ErrorRow()1067 	    int ErrorRow()	{ return errorLocation.row+1; }
ErrorCol()1068 	    int ErrorCol()	{ return errorLocation.col+1; }	///< The column where the error occured. See ErrorRow()
1069 
1070 	    /** By calling this method, with a tab size
1071 		    greater than 0, the row and column of each node and attribute is stored
1072 		    when the file is loaded. Very useful for tracking the DOM back in to
1073 		    the source file.
1074 
1075 		    The tab size is required for calculating the location of nodes. If not
1076 		    set, the default of 4 is used. The tabsize is set per document. Setting
1077 		    the tabsize to 0 disables row/column tracking.
1078 
1079 		    Note that row and column tracking is not supported when using operator>>.
1080 
1081 		    The tab size needs to be enabled before the parse or load. Correct usage:
1082 		    @verbatim
1083 		    TiXmlDocument doc;
1084 		    doc.SetTabSize( 8 );
1085 		    doc.Load( "myfile.xml" );
1086 		    @endverbatim
1087 
1088 		    @sa Row, Column
1089 	    */
SetTabSize(int _tabsize)1090 	    void SetTabSize( int _tabsize )		{ tabsize = _tabsize; }
1091 
TabSize()1092 	    int TabSize() const	{ return tabsize; }
1093 
1094 	    /** If you have handled the error, it can be reset with this call. The error
1095 		    state is automatically cleared if you Parse a new XML block.
1096 	    */
ClearError()1097 	    void ClearError()						{	error = false;
1098 												    errorId = 0;
1099 												    errorDesc = "";
1100 												    errorLocation.row = errorLocation.col = 0;
1101 												    //errorLocation.last = 0;
1102 											    }
1103 
1104 	    /** Dump the document to standard out. */
Print()1105 	    void Print() const						{ Print( stdout, 0 ); }
1106 
1107 	    // [internal use]
1108 	    virtual void Print( FILE* cfile, int depth = 0 ) const;
1109 	    // [internal use]
1110 	    void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData );
1111 
1112     protected :
1113 	    virtual void StreamOut ( TIXML_OSTREAM * out) const;
1114 	    // [internal use]
1115 	    virtual TiXmlNode* Clone() const;
1116 	    #ifdef TIXML_USE_STL
1117 	        virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1118 	    #endif
1119 
1120     private:
1121 	    bool error;
1122 	    int  errorId;
1123 	    TIXML_STRING errorDesc;
1124 	    int tabsize;
1125 	    TiXmlCursor errorLocation;
1126     };
1127 
1128 
1129     /**
1130 	    A TiXmlHandle is a class that wraps a node pointer with null checks; this is
1131 	    an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
1132 	    DOM structure. It is a separate utility class.
1133 
1134 	    Take an example:
1135 	    @verbatim
1136 	    <Document>
1137 		    <Element attributeA = "valueA">
1138 			    <Child attributeB = "value1" />
1139 			    <Child attributeB = "value2" />
1140 		    </Element>
1141 	    <Document>
1142 	    @endverbatim
1143 
1144 	    Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1145 	    easy to write a *lot* of code that looks like:
1146 
1147 	    @verbatim
1148 	    TiXmlElement* root = document.FirstChildElement( "Document" );
1149 	    if ( root )
1150 	    {
1151 		    TiXmlElement* element = root->FirstChildElement( "Element" );
1152 		    if ( element )
1153 		    {
1154 			    TiXmlElement* child = element->FirstChildElement( "Child" );
1155 			    if ( child )
1156 			    {
1157 				    TiXmlElement* child2 = child->NextSiblingElement( "Child" );
1158 				    if ( child2 )
1159 				    {
1160 					    // Finally do something useful.
1161 	    @endverbatim
1162 
1163 	    And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
1164 	    of such code. A TiXmlHandle checks for null	pointers so it is perfectly safe
1165 	    and correct to use:
1166 
1167 	    @verbatim
1168 	    TiXmlHandle docHandle( &document );
1169 	    TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
1170 	    if ( child2 )
1171 	    {
1172 		    // do something useful
1173 	    @endverbatim
1174 
1175 	    Which is MUCH more concise and useful.
1176 
1177 	    It is also safe to copy handles - internally they are nothing more than node pointers.
1178 	    @verbatim
1179 	    TiXmlHandle handleCopy = handle;
1180 	    @endverbatim
1181 
1182 	    What they should not be used for is iteration:
1183 
1184 	    @verbatim
1185 	    int i=0;
1186 	    while ( true )
1187 	    {
1188 		    TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
1189 		    if ( !child )
1190 			    break;
1191 		    // do something
1192 		    ++i;
1193 	    }
1194 	    @endverbatim
1195 
1196 	    It seems reasonable, but it is in fact two embedded while loops. The Child method is
1197 	    a linear walk to find the element, so this code would iterate much more than it needs
1198 	    to. Instead, prefer:
1199 
1200 	    @verbatim
1201 	    TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
1202 
1203 	    for( child; child; child=child->NextSiblingElement() )
1204 	    {
1205 		    // do something
1206 	    }
1207 	    @endverbatim
1208     */
1209     class CAL3D_API TiXmlHandle
1210     {
1211     public:
1212 	    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
TiXmlHandle(TiXmlNode * node)1213 	    TiXmlHandle( TiXmlNode* node )			{ this->node = node; }
1214 	    /// Copy constructor
TiXmlHandle(const TiXmlHandle & ref)1215 	    TiXmlHandle( const TiXmlHandle& ref )	{ this->node = ref.node; }
1216 
1217 	    /// Return a handle to the first child node.
1218 	    TiXmlHandle FirstChild() const;
1219 	    /// Return a handle to the first child node with the given name.
1220 	    TiXmlHandle FirstChild( const char * value ) const;
1221 	    /// Return a handle to the first child element.
1222 	    TiXmlHandle FirstChildElement() const;
1223 	    /// Return a handle to the first child element with the given name.
1224 	    TiXmlHandle FirstChildElement( const char * value ) const;
1225 
1226 	    /** Return a handle to the "index" child with the given name.
1227 		    The first child is 0, the second 1, etc.
1228 	    */
1229 	    TiXmlHandle Child( const char* value, int index ) const;
1230 	    /** Return a handle to the "index" child.
1231 		    The first child is 0, the second 1, etc.
1232 	    */
1233 	    TiXmlHandle Child( int index ) const;
1234 	    /** Return a handle to the "index" child element with the given name.
1235 		    The first child element is 0, the second 1, etc. Note that only TiXmlElements
1236 		    are indexed: other types are not counted.
1237 	    */
1238 	    TiXmlHandle ChildElement( const char* value, int index ) const;
1239 	    /** Return a handle to the "index" child element.
1240 		    The first child element is 0, the second 1, etc. Note that only TiXmlElements
1241 		    are indexed: other types are not counted.
1242 	    */
1243 	    TiXmlHandle ChildElement( int index ) const;
1244 
1245 	    #ifdef TIXML_USE_STL
FirstChild(const std::string & _value)1246 	    TiXmlHandle FirstChild( const std::string& _value ) const			{ return FirstChild( _value.c_str() ); }
FirstChildElement(const std::string & _value)1247 	    TiXmlHandle FirstChildElement( const std::string& _value ) const		{ return FirstChildElement( _value.c_str() ); }
1248 
Child(const std::string & _value,int index)1249 	    TiXmlHandle Child( const std::string& _value, int index ) const			{ return Child( _value.c_str(), index ); }
ChildElement(const std::string & _value,int index)1250 	    TiXmlHandle ChildElement( const std::string& _value, int index ) const	{ return ChildElement( _value.c_str(), index ); }
1251 	    #endif
1252 
1253 	    /// Return the handle as a TiXmlNode. This may return null.
Node()1254 	    TiXmlNode* Node() const			{ return node; }
1255 	    /// Return the handle as a TiXmlElement. This may return null.
Element()1256 	    TiXmlElement* Element() const	{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1257 	    /// Return the handle as a TiXmlText. This may return null.
Text()1258 	    TiXmlText* Text() const			{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1259 
1260     private:
1261 	    TiXmlNode* node;
1262     };
1263 
1264 }
1265 
1266 #endif
1267 
1268