stratgame

changeset 0:86b53f76899f

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 21 May 2012 19:07:40 +0300
parents
children 55a43e27339a
files .hgignore Makefile level/Makefile level/src/level.cc level/src/level.h level/src/tinyxml2.cc level/src/tinyxml2.h src/game_part.cc src/game_part.h src/main.cc src/menu_part.cc src/menu_part.h src/opengl.h src/part.cc src/part.h
diffstat 15 files changed, 3653 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Mon May 21 19:07:40 2012 +0300
     1.3 @@ -0,0 +1,8 @@
     1.4 +\.d$
     1.5 +\.o$
     1.6 +Makefile$
     1.7 +\.swp$
     1.8 +strat$
     1.9 +\.a$
    1.10 +\.so$
    1.11 +^data/
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Mon May 21 19:07:40 2012 +0300
     2.3 @@ -0,0 +1,36 @@
     2.4 +csrc = $(wildcard src/*.c)
     2.5 +ccsrc = $(wildcard src/*.cc)
     2.6 +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o)
     2.7 +dep = $(obj:.o=.d)
     2.8 +bin = strat
     2.9 +
    2.10 +incdir = -Isrc -Ilevel/src
    2.11 +
    2.12 +liblevel = level/liblevel.a
    2.13 +slibs = $(liblevel)
    2.14 +
    2.15 +CFLAGS = -pedantic -Wall -g $(incdir)
    2.16 +CXXFLAGS = -std=c++0x $(CFLAGS)
    2.17 +LDFLAGS = $(libdir) $(slibs) $(libgl) -limtk
    2.18 +
    2.19 +ifeq ($(shell uname -s), Darwin)
    2.20 +	libgl = -framework OpenGL -framework GLUT -lGLEW
    2.21 +else
    2.22 +	libgl = -lGL -lGLU -lglut -lGLEW
    2.23 +endif
    2.24 +
    2.25 +$(bin): $(obj) $(slibs)
    2.26 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    2.27 +
    2.28 +-include $(dep)
    2.29 +
    2.30 +%.d: %.c
    2.31 +	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    2.32 +
    2.33 +%.d: %.cc
    2.34 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    2.35 +
    2.36 +
    2.37 +.PHONY: clean
    2.38 +clean:
    2.39 +	rm -f $(obj) $(bin) $(dep)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/level/Makefile	Mon May 21 19:07:40 2012 +0300
     3.3 @@ -0,0 +1,18 @@
     3.4 +ccsrc = $(wildcard src/*.cc)
     3.5 +obj = $(ccsrc:.cc=.o)
     3.6 +dep = $(obj:.o=.d)
     3.7 +lib_a = liblevel.a
     3.8 +
     3.9 +CXXFLAGS = -std=c++0x -pedantic -Wall -g
    3.10 +
    3.11 +$(lib_a): $(obj)
    3.12 +	$(AR) rcs $@ $(obj)
    3.13 +
    3.14 +-include $(dep)
    3.15 +
    3.16 +%.d: %.cc
    3.17 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    3.18 +
    3.19 +.PHONY: clean
    3.20 +clean:
    3.21 +	rm -f $(obj) $(bin) $(dep)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/level/src/level.cc	Mon May 21 19:07:40 2012 +0300
     4.3 @@ -0,0 +1,24 @@
     4.4 +#include <stdio.h>
     4.5 +#include <string.h>
     4.6 +#include "level.h"
     4.7 +
     4.8 +Level::Level()
     4.9 +{
    4.10 +}
    4.11 +
    4.12 +Level::~Level()
    4.13 +{
    4.14 +}
    4.15 +
    4.16 +bool Level::load(const char *fname)
    4.17 +{
    4.18 +	if(!xml.loadFile(fname)) {
    4.19 +		fprintf(stderr, "failed to load level: %s\n", fname);
    4.20 +		return false;
    4.21 +	}
    4.22 +
    4.23 +	if(strcmp(xml.RootElement().Name(), "level") != 0) {
    4.24 +		fprintf(stderr, "invalid level file: %s\n", fname);
    4.25 +		return false;
    4.26 +	}
    4.27 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/level/src/level.h	Mon May 21 19:07:40 2012 +0300
     5.3 @@ -0,0 +1,22 @@
     5.4 +#ifndef LEVEL_H_
     5.5 +#define LEVEL_H_
     5.6 +
     5.7 +#include "tinyxml2.h"
     5.8 +
     5.9 +class Level {
    5.10 +private:
    5.11 +	tinyxml2::XMLDocument xml;
    5.12 +
    5.13 +public:
    5.14 +	Level();
    5.15 +	~Level();
    5.16 +
    5.17 +	bool load(const char *fname);
    5.18 +};
    5.19 +
    5.20 +class Map {
    5.21 +public:
    5.22 +	bool load(tinyxml2::XMLNode *xml);
    5.23 +};
    5.24 +
    5.25 +#endif	// LEVEL_H_
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/level/src/tinyxml2.cc	Mon May 21 19:07:40 2012 +0300
     6.3 @@ -0,0 +1,1826 @@
     6.4 +/*
     6.5 +Original code by Lee Thomason (www.grinninglizard.com)
     6.6 +
     6.7 +This software is provided 'as-is', without any express or implied
     6.8 +warranty. In no event will the authors be held liable for any
     6.9 +damages arising from the use of this software.
    6.10 +
    6.11 +Permission is granted to anyone to use this software for any
    6.12 +purpose, including commercial applications, and to alter it and
    6.13 +redistribute it freely, subject to the following restrictions:
    6.14 +
    6.15 +1. The origin of this software must not be misrepresented; you must
    6.16 +not claim that you wrote the original software. If you use this
    6.17 +software in a product, an acknowledgment in the product documentation
    6.18 +would be appreciated but is not required.
    6.19 +
    6.20 +2. Altered source versions must be plainly marked as such, and
    6.21 +must not be misrepresented as being the original software.
    6.22 +
    6.23 +3. This notice may not be removed or altered from any source
    6.24 +distribution.
    6.25 +*/
    6.26 +
    6.27 +#include "tinyxml2.h"
    6.28 +
    6.29 +#include <cstdio>
    6.30 +#include <cstdlib>
    6.31 +#include <new>
    6.32 +#include <cstddef>
    6.33 +
    6.34 +using namespace tinyxml2;
    6.35 +
    6.36 +static const char LINE_FEED				= (char)0x0a;			// all line endings are normalized to LF
    6.37 +static const char LF = LINE_FEED;
    6.38 +static const char CARRIAGE_RETURN		= (char)0x0d;			// CR gets filtered out
    6.39 +static const char CR = CARRIAGE_RETURN;
    6.40 +static const char SINGLE_QUOTE			= '\'';
    6.41 +static const char DOUBLE_QUOTE			= '\"';
    6.42 +
    6.43 +// Bunch of unicode info at:
    6.44 +//		http://www.unicode.org/faq/utf_bom.html
    6.45 +//	ef bb bf (Microsoft "lead bytes") - designates UTF-8
    6.46 +
    6.47 +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
    6.48 +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
    6.49 +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
    6.50 +
    6.51 +
    6.52 +#define DELETE_NODE( node )	{			\
    6.53 +	if ( node ) {						\
    6.54 +		MemPool* pool = node->memPool;	\
    6.55 +		node->~XMLNode();				\
    6.56 +		pool->Free( node );				\
    6.57 +	}									\
    6.58 +}
    6.59 +#define DELETE_ATTRIBUTE( attrib ) {		\
    6.60 +	if ( attrib ) {							\
    6.61 +		MemPool* pool = attrib->memPool;	\
    6.62 +		attrib->~XMLAttribute();			\
    6.63 +		pool->Free( attrib );				\
    6.64 +	}										\
    6.65 +}
    6.66 +
    6.67 +struct Entity {
    6.68 +	const char* pattern;
    6.69 +	int length;
    6.70 +	char value;
    6.71 +};
    6.72 +
    6.73 +static const int NUM_ENTITIES = 5;
    6.74 +static const Entity entities[NUM_ENTITIES] = 
    6.75 +{
    6.76 +	{ "quot", 4,	DOUBLE_QUOTE },
    6.77 +	{ "amp", 3,		'&'  },
    6.78 +	{ "apos", 4,	SINGLE_QUOTE },
    6.79 +	{ "lt",	2, 		'<'	 },
    6.80 +	{ "gt",	2,		'>'	 }
    6.81 +};
    6.82 +
    6.83 +
    6.84 +StrPair::~StrPair()
    6.85 +{
    6.86 +	Reset();
    6.87 +}
    6.88 +
    6.89 +
    6.90 +void StrPair::Reset()
    6.91 +{
    6.92 +	if ( flags & NEEDS_DELETE ) {
    6.93 +		delete [] start;
    6.94 +	}
    6.95 +	flags = 0;
    6.96 +	start = 0;
    6.97 +	end = 0;
    6.98 +}
    6.99 +
   6.100 +
   6.101 +void StrPair::SetStr( const char* str, int flags )
   6.102 +{
   6.103 +	Reset();
   6.104 +	size_t len = strlen( str );
   6.105 +	start = new char[ len+1 ];
   6.106 +	memcpy( start, str, len+1 );
   6.107 +	end = start + len;
   6.108 +	this->flags = flags | NEEDS_DELETE;
   6.109 +}
   6.110 +
   6.111 +
   6.112 +char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
   6.113 +{
   6.114 +	TIXMLASSERT( endTag && *endTag );
   6.115 +
   6.116 +	char* start = p;	// fixme: hides a member
   6.117 +	char  endChar = *endTag;
   6.118 +	size_t length = strlen( endTag );
   6.119 +
   6.120 +	// Inner loop of text parsing.
   6.121 +	while ( *p ) {
   6.122 +		if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
   6.123 +			Set( start, p, strFlags );
   6.124 +			return p + length;
   6.125 +		}
   6.126 +		++p;
   6.127 +	}	
   6.128 +	return 0;
   6.129 +}
   6.130 +
   6.131 +
   6.132 +char* StrPair::ParseName( char* p )
   6.133 +{
   6.134 +	char* start = p;
   6.135 +
   6.136 +	if ( !start || !(*start) ) {
   6.137 +		return 0;
   6.138 +	}
   6.139 +
   6.140 +	if ( !XMLUtil::IsAlpha( *p ) ) {
   6.141 +		return 0;
   6.142 +	}
   6.143 +
   6.144 +	while( *p && (
   6.145 +			   XMLUtil::IsAlphaNum( (unsigned char) *p ) 
   6.146 +			|| *p == '_'
   6.147 +			|| *p == '-'
   6.148 +			|| *p == '.'
   6.149 +			|| *p == ':' ))
   6.150 +	{
   6.151 +		++p;
   6.152 +	}
   6.153 +
   6.154 +	if ( p > start ) {
   6.155 +		Set( start, p, 0 );
   6.156 +		return p;
   6.157 +	}
   6.158 +	return 0;
   6.159 +}
   6.160 +
   6.161 +
   6.162 +
   6.163 +const char* StrPair::GetStr()
   6.164 +{
   6.165 +	if ( flags & NEEDS_FLUSH ) {
   6.166 +		*end = 0;
   6.167 +		flags ^= NEEDS_FLUSH;
   6.168 +
   6.169 +		if ( flags ) {
   6.170 +			char* p = start;	// the read pointer
   6.171 +			char* q = start;	// the write pointer
   6.172 +
   6.173 +			while( p < end ) {
   6.174 +				if ( (flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
   6.175 +					// CR-LF pair becomes LF
   6.176 +					// CR alone becomes LF
   6.177 +					// LF-CR becomes LF
   6.178 +					if ( *(p+1) == LF ) {
   6.179 +						p += 2;
   6.180 +					}
   6.181 +					else {
   6.182 +						++p;
   6.183 +					}
   6.184 +					*q++ = LF;
   6.185 +				}
   6.186 +				else if ( (flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
   6.187 +					if ( *(p+1) == CR ) {
   6.188 +						p += 2;
   6.189 +					}
   6.190 +					else {
   6.191 +						++p;
   6.192 +					}
   6.193 +					*q++ = LF;
   6.194 +				}
   6.195 +				else if ( (flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
   6.196 +					int i=0;
   6.197 +
   6.198 +					// Entities handled by tinyXML2:
   6.199 +					// - special entities in the entity table [in/out]
   6.200 +					// - numeric character reference [in]
   6.201 +					//   &#20013; or &#x4e2d;
   6.202 +
   6.203 +					if ( *(p+1) == '#' ) {
   6.204 +						char buf[10] = { 0 };
   6.205 +						int len;
   6.206 +						p = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
   6.207 +						for( int i=0; i<len; ++i ) {
   6.208 +							*q++ = buf[i];
   6.209 +						}
   6.210 +						TIXMLASSERT( q <= p );
   6.211 +					}
   6.212 +					else {
   6.213 +						for( i=0; i<NUM_ENTITIES; ++i ) {
   6.214 +							if (    strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
   6.215 +								 && *(p+entities[i].length+1) == ';' ) 
   6.216 +							{
   6.217 +								// Found an entity convert;
   6.218 +								*q = entities[i].value;
   6.219 +								++q;
   6.220 +								p += entities[i].length + 2;
   6.221 +								break;
   6.222 +							}
   6.223 +						}
   6.224 +						if ( i == NUM_ENTITIES ) {
   6.225 +							// fixme: treat as error?
   6.226 +							++p;
   6.227 +							++q;
   6.228 +						}
   6.229 +					}
   6.230 +				}
   6.231 +				else {
   6.232 +					*q = *p;
   6.233 +					++p;
   6.234 +					++q;
   6.235 +				}
   6.236 +			}
   6.237 +			*q = 0;
   6.238 +		}
   6.239 +		flags = (flags & NEEDS_DELETE);
   6.240 +	}
   6.241 +	return start;
   6.242 +}
   6.243 +
   6.244 +
   6.245 +
   6.246 +
   6.247 +// --------- XMLUtil ----------- //
   6.248 +
   6.249 +const char* XMLUtil::ReadBOM( const char* p, bool* bom )
   6.250 +{
   6.251 +	*bom = false;
   6.252 +	const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
   6.253 +	// Check for BOM:
   6.254 +	if (    *(pu+0) == TIXML_UTF_LEAD_0 
   6.255 +		 && *(pu+1) == TIXML_UTF_LEAD_1
   6.256 +		 && *(pu+2) == TIXML_UTF_LEAD_2 ) 
   6.257 +	{
   6.258 +		*bom = true;
   6.259 +		p += 3;
   6.260 +	}
   6.261 +	return p;
   6.262 +}
   6.263 +
   6.264 +
   6.265 +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
   6.266 +{
   6.267 +	const unsigned long BYTE_MASK = 0xBF;
   6.268 +	const unsigned long BYTE_MARK = 0x80;
   6.269 +	const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
   6.270 +
   6.271 +	if (input < 0x80) 
   6.272 +		*length = 1;
   6.273 +	else if ( input < 0x800 )
   6.274 +		*length = 2;
   6.275 +	else if ( input < 0x10000 )
   6.276 +		*length = 3;
   6.277 +	else if ( input < 0x200000 )
   6.278 +		*length = 4;
   6.279 +	else
   6.280 +		{ *length = 0; return; }	// This code won't covert this correctly anyway.
   6.281 +
   6.282 +	output += *length;
   6.283 +
   6.284 +	// Scary scary fall throughs.
   6.285 +	switch (*length) 
   6.286 +	{
   6.287 +		case 4:
   6.288 +			--output; 
   6.289 +			*output = (char)((input | BYTE_MARK) & BYTE_MASK); 
   6.290 +			input >>= 6;
   6.291 +		case 3:
   6.292 +			--output; 
   6.293 +			*output = (char)((input | BYTE_MARK) & BYTE_MASK); 
   6.294 +			input >>= 6;
   6.295 +		case 2:
   6.296 +			--output; 
   6.297 +			*output = (char)((input | BYTE_MARK) & BYTE_MASK); 
   6.298 +			input >>= 6;
   6.299 +		case 1:
   6.300 +			--output; 
   6.301 +			*output = (char)(input | FIRST_BYTE_MARK[*length]);
   6.302 +	}
   6.303 +}
   6.304 +
   6.305 +
   6.306 +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
   6.307 +{
   6.308 +	// Presume an entity, and pull it out.
   6.309 +	*length = 0;
   6.310 +
   6.311 +	if ( *(p+1) == '#' && *(p+2) )
   6.312 +	{
   6.313 +		unsigned long ucs = 0;
   6.314 +		ptrdiff_t delta = 0;
   6.315 +		unsigned mult = 1;
   6.316 +
   6.317 +		if ( *(p+2) == 'x' )
   6.318 +		{
   6.319 +			// Hexadecimal.
   6.320 +			if ( !*(p+3) ) return 0;
   6.321 +
   6.322 +			const char* q = p+3;
   6.323 +			q = strchr( q, ';' );
   6.324 +
   6.325 +			if ( !q || !*q ) return 0;
   6.326 +
   6.327 +			delta = q-p;
   6.328 +			--q;
   6.329 +
   6.330 +			while ( *q != 'x' )
   6.331 +			{
   6.332 +				if ( *q >= '0' && *q <= '9' )
   6.333 +					ucs += mult * (*q - '0');
   6.334 +				else if ( *q >= 'a' && *q <= 'f' )
   6.335 +					ucs += mult * (*q - 'a' + 10);
   6.336 +				else if ( *q >= 'A' && *q <= 'F' )
   6.337 +					ucs += mult * (*q - 'A' + 10 );
   6.338 +				else 
   6.339 +					return 0;
   6.340 +				mult *= 16;
   6.341 +				--q;
   6.342 +			}
   6.343 +		}
   6.344 +		else
   6.345 +		{
   6.346 +			// Decimal.
   6.347 +			if ( !*(p+2) ) return 0;
   6.348 +
   6.349 +			const char* q = p+2;
   6.350 +			q = strchr( q, ';' );
   6.351 +
   6.352 +			if ( !q || !*q ) return 0;
   6.353 +
   6.354 +			delta = q-p;
   6.355 +			--q;
   6.356 +
   6.357 +			while ( *q != '#' )
   6.358 +			{
   6.359 +				if ( *q >= '0' && *q <= '9' )
   6.360 +					ucs += mult * (*q - '0');
   6.361 +				else 
   6.362 +					return 0;
   6.363 +				mult *= 10;
   6.364 +				--q;
   6.365 +			}
   6.366 +		}
   6.367 +		// convert the UCS to UTF-8
   6.368 +		ConvertUTF32ToUTF8( ucs, value, length );
   6.369 +		return p + delta + 1;
   6.370 +	}
   6.371 +	return p+1;
   6.372 +}
   6.373 +
   6.374 +
   6.375 +char* XMLDocument::Identify( char* p, XMLNode** node ) 
   6.376 +{
   6.377 +	XMLNode* returnNode = 0;
   6.378 +	char* start = p;
   6.379 +	p = XMLUtil::SkipWhiteSpace( p );
   6.380 +	if( !p || !*p )
   6.381 +	{
   6.382 +		return p;
   6.383 +	}
   6.384 +
   6.385 +	// What is this thing? 
   6.386 +	// - Elements start with a letter or underscore, but xml is reserved.
   6.387 +	// - Comments: <!--
   6.388 +	// - Decleration: <?
   6.389 +	// - Everthing else is unknown to tinyxml.
   6.390 +	//
   6.391 +
   6.392 +	static const char* xmlHeader		= { "<?" };
   6.393 +	static const char* commentHeader	= { "<!--" };
   6.394 +	static const char* dtdHeader		= { "<!" };
   6.395 +	static const char* cdataHeader		= { "<![CDATA[" };
   6.396 +	static const char* elementHeader	= { "<" };	// and a header for everything else; check last.
   6.397 +
   6.398 +	static const int xmlHeaderLen		= 2;
   6.399 +	static const int commentHeaderLen	= 4;
   6.400 +	static const int dtdHeaderLen		= 2;
   6.401 +	static const int cdataHeaderLen		= 9;
   6.402 +	static const int elementHeaderLen	= 1;
   6.403 +
   6.404 +#if defined(_MSC_VER)
   6.405 +#pragma warning ( push )
   6.406 +#pragma warning ( disable : 4127 )
   6.407 +#endif
   6.408 +	TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );		// use same memory pool
   6.409 +	TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );	// use same memory pool
   6.410 +#if defined(_MSC_VER)
   6.411 +#pragma warning (pop)
   6.412 +#endif
   6.413 +	if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
   6.414 +		returnNode = new (commentPool.Alloc()) XMLDeclaration( this );
   6.415 +		returnNode->memPool = &commentPool;
   6.416 +		p += xmlHeaderLen;
   6.417 +	}
   6.418 +	else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
   6.419 +		returnNode = new (commentPool.Alloc()) XMLComment( this );
   6.420 +		returnNode->memPool = &commentPool;
   6.421 +		p += commentHeaderLen;
   6.422 +	}
   6.423 +	else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
   6.424 +		XMLText* text = new (textPool.Alloc()) XMLText( this );
   6.425 +		returnNode = text;
   6.426 +		returnNode->memPool = &textPool;
   6.427 +		p += cdataHeaderLen;
   6.428 +		text->SetCData( true );
   6.429 +	}
   6.430 +	else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
   6.431 +		returnNode = new (commentPool.Alloc()) XMLUnknown( this );
   6.432 +		returnNode->memPool = &commentPool;
   6.433 +		p += dtdHeaderLen;
   6.434 +	}
   6.435 +	else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
   6.436 +		returnNode = new (elementPool.Alloc()) XMLElement( this );
   6.437 +		returnNode->memPool = &elementPool;
   6.438 +		p += elementHeaderLen;
   6.439 +	}
   6.440 +	else {
   6.441 +		returnNode = new (textPool.Alloc()) XMLText( this );
   6.442 +		returnNode->memPool = &textPool;
   6.443 +		p = start;	// Back it up, all the text counts.
   6.444 +	}
   6.445 +
   6.446 +	*node = returnNode;
   6.447 +	return p;
   6.448 +}
   6.449 +
   6.450 +
   6.451 +bool XMLDocument::Accept( XMLVisitor* visitor ) const
   6.452 +{
   6.453 +	if ( visitor->VisitEnter( *this ) )
   6.454 +	{
   6.455 +		for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
   6.456 +		{
   6.457 +			if ( !node->Accept( visitor ) )
   6.458 +				break;
   6.459 +		}
   6.460 +	}
   6.461 +	return visitor->VisitExit( *this );
   6.462 +}
   6.463 +
   6.464 +
   6.465 +// --------- XMLNode ----------- //
   6.466 +
   6.467 +XMLNode::XMLNode( XMLDocument* doc ) :
   6.468 +	document( doc ),
   6.469 +	parent( 0 ),
   6.470 +	firstChild( 0 ), lastChild( 0 ),
   6.471 +	prev( 0 ), next( 0 )
   6.472 +{
   6.473 +}
   6.474 +
   6.475 +
   6.476 +XMLNode::~XMLNode()
   6.477 +{
   6.478 +	DeleteChildren();
   6.479 +	if ( parent ) {
   6.480 +		parent->Unlink( this );
   6.481 +	}
   6.482 +}
   6.483 +
   6.484 +
   6.485 +void XMLNode::SetValue( const char* str, bool staticMem )
   6.486 +{
   6.487 +	if ( staticMem )
   6.488 +		value.SetInternedStr( str );
   6.489 +	else
   6.490 +		value.SetStr( str );
   6.491 +}
   6.492 +
   6.493 +
   6.494 +void XMLNode::DeleteChildren()
   6.495 +{
   6.496 +	while( firstChild ) {
   6.497 +		XMLNode* node = firstChild;
   6.498 +		Unlink( node );
   6.499 +		
   6.500 +		DELETE_NODE( node );
   6.501 +	}
   6.502 +	firstChild = lastChild = 0;
   6.503 +}
   6.504 +
   6.505 +
   6.506 +void XMLNode::Unlink( XMLNode* child )
   6.507 +{
   6.508 +	TIXMLASSERT( child->parent == this );
   6.509 +	if ( child == firstChild ) 
   6.510 +		firstChild = firstChild->next;
   6.511 +	if ( child == lastChild ) 
   6.512 +		lastChild = lastChild->prev;
   6.513 +
   6.514 +	if ( child->prev ) {
   6.515 +		child->prev->next = child->next;
   6.516 +	}
   6.517 +	if ( child->next ) {
   6.518 +		child->next->prev = child->prev;
   6.519 +	}
   6.520 +	child->parent = 0;
   6.521 +}
   6.522 +
   6.523 +
   6.524 +void XMLNode::DeleteChild( XMLNode* node )
   6.525 +{
   6.526 +	TIXMLASSERT( node->parent == this );
   6.527 +	DELETE_NODE( node );
   6.528 +}
   6.529 +
   6.530 +
   6.531 +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
   6.532 +{
   6.533 +	if ( lastChild ) {
   6.534 +		TIXMLASSERT( firstChild );
   6.535 +		TIXMLASSERT( lastChild->next == 0 );
   6.536 +		lastChild->next = addThis;
   6.537 +		addThis->prev = lastChild;
   6.538 +		lastChild = addThis;
   6.539 +
   6.540 +		addThis->next = 0;
   6.541 +	}
   6.542 +	else {
   6.543 +		TIXMLASSERT( firstChild == 0 );
   6.544 +		firstChild = lastChild = addThis;
   6.545 +
   6.546 +		addThis->prev = 0;
   6.547 +		addThis->next = 0;
   6.548 +	}
   6.549 +	addThis->parent = this;
   6.550 +	return addThis;
   6.551 +}
   6.552 +
   6.553 +
   6.554 +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
   6.555 +{
   6.556 +	if ( firstChild ) {
   6.557 +		TIXMLASSERT( lastChild );
   6.558 +		TIXMLASSERT( firstChild->prev == 0 );
   6.559 +
   6.560 +		firstChild->prev = addThis;
   6.561 +		addThis->next = firstChild;
   6.562 +		firstChild = addThis;
   6.563 +
   6.564 +		addThis->prev = 0;
   6.565 +	}
   6.566 +	else {
   6.567 +		TIXMLASSERT( lastChild == 0 );
   6.568 +		firstChild = lastChild = addThis;
   6.569 +
   6.570 +		addThis->prev = 0;
   6.571 +		addThis->next = 0;
   6.572 +	}
   6.573 +	addThis->parent = this;
   6.574 +	return addThis;
   6.575 +}
   6.576 +
   6.577 +
   6.578 +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
   6.579 +{
   6.580 +	TIXMLASSERT( afterThis->parent == this );
   6.581 +	if ( afterThis->parent != this )
   6.582 +		return 0;
   6.583 +
   6.584 +	if ( afterThis->next == 0 ) {
   6.585 +		// The last node or the only node.
   6.586 +		return InsertEndChild( addThis );
   6.587 +	}
   6.588 +	addThis->prev = afterThis;
   6.589 +	addThis->next = afterThis->next;
   6.590 +	afterThis->next->prev = addThis;
   6.591 +	afterThis->next = addThis;
   6.592 +	addThis->parent = this;
   6.593 +	return addThis;
   6.594 +}
   6.595 +
   6.596 +
   6.597 +
   6.598 +
   6.599 +const XMLElement* XMLNode::FirstChildElement( const char* value ) const
   6.600 +{
   6.601 +	for( XMLNode* node=firstChild; node; node=node->next ) {
   6.602 +		XMLElement* element = node->ToElement();
   6.603 +		if ( element ) {
   6.604 +			if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
   6.605 +				return element;
   6.606 +			}
   6.607 +		}
   6.608 +	}
   6.609 +	return 0;
   6.610 +}
   6.611 +
   6.612 +
   6.613 +const XMLElement* XMLNode::LastChildElement( const char* value ) const
   6.614 +{
   6.615 +	for( XMLNode* node=lastChild; node; node=node->prev ) {
   6.616 +		XMLElement* element = node->ToElement();
   6.617 +		if ( element ) {
   6.618 +			if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
   6.619 +				return element;
   6.620 +			}
   6.621 +		}
   6.622 +	}
   6.623 +	return 0;
   6.624 +}
   6.625 +
   6.626 +
   6.627 +const XMLElement* XMLNode::NextSiblingElement( const char* value ) const
   6.628 +{
   6.629 +	for( XMLNode* element=this->next; element; element = element->next ) {
   6.630 +		if (    element->ToElement() 
   6.631 +			 && (!value || XMLUtil::StringEqual( value, element->Value() ))) 
   6.632 +		{
   6.633 +			return element->ToElement();
   6.634 +		}
   6.635 +	}
   6.636 +	return 0;
   6.637 +}
   6.638 +
   6.639 +
   6.640 +const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const
   6.641 +{
   6.642 +	for( XMLNode* element=this->prev; element; element = element->prev ) {
   6.643 +		if (    element->ToElement()
   6.644 +			 && (!value || XMLUtil::StringEqual( value, element->Value() ))) 
   6.645 +		{
   6.646 +			return element->ToElement();
   6.647 +		}
   6.648 +	}
   6.649 +	return 0;
   6.650 +}
   6.651 +
   6.652 +
   6.653 +char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
   6.654 +{
   6.655 +	// This is a recursive method, but thinking about it "at the current level"
   6.656 +	// it is a pretty simple flat list:
   6.657 +	//		<foo/>
   6.658 +	//		<!-- comment -->
   6.659 +	//
   6.660 +	// With a special case:
   6.661 +	//		<foo>
   6.662 +	//		</foo>
   6.663 +	//		<!-- comment -->
   6.664 +	//		
   6.665 +	// Where the closing element (/foo) *must* be the next thing after the opening
   6.666 +	// element, and the names must match. BUT the tricky bit is that the closing
   6.667 +	// element will be read by the child.
   6.668 +	// 
   6.669 +	// 'endTag' is the end tag for this node, it is returned by a call to a child.
   6.670 +	// 'parentEnd' is the end tag for the parent, which is filled in and returned.
   6.671 +
   6.672 +	while( p && *p ) {
   6.673 +		XMLNode* node = 0;
   6.674 +
   6.675 +		p = document->Identify( p, &node );
   6.676 +		if ( p == 0 || node == 0 ) {
   6.677 +			break;
   6.678 +		}
   6.679 +
   6.680 +		StrPair endTag;
   6.681 +		p = node->ParseDeep( p, &endTag );
   6.682 +		if ( !p ) {
   6.683 +			DELETE_NODE( node );
   6.684 +			node = 0;
   6.685 +			if ( !document->Error() ) {
   6.686 +				document->SetError( XML_ERROR_PARSING, 0, 0 );
   6.687 +			}
   6.688 +			break;
   6.689 +		}
   6.690 +
   6.691 +		// We read the end tag. Return it to the parent.
   6.692 +		if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) {
   6.693 +			if ( parentEnd ) {
   6.694 +				*parentEnd = ((XMLElement*)node)->value;
   6.695 +			}
   6.696 +			DELETE_NODE( node );
   6.697 +			return p;
   6.698 +		}
   6.699 +
   6.700 +		// Handle an end tag returned to this level.
   6.701 +		// And handle a bunch of annoying errors.
   6.702 +		XMLElement* ele = node->ToElement();
   6.703 +		if ( ele ) {
   6.704 +			if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) {
   6.705 +				document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
   6.706 +				p = 0;
   6.707 +			}
   6.708 +			else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) {
   6.709 +				document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
   6.710 +				p = 0;
   6.711 +			}
   6.712 +			else if ( !endTag.Empty() ) {
   6.713 +				if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) { 
   6.714 +					document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 );
   6.715 +					p = 0;
   6.716 +				}
   6.717 +			}
   6.718 +		}
   6.719 +		if ( p == 0 ) {
   6.720 +			DELETE_NODE( node );
   6.721 +			node = 0;
   6.722 +		}
   6.723 +		if ( node ) {
   6.724 +			this->InsertEndChild( node );
   6.725 +		}
   6.726 +	}
   6.727 +	return 0;
   6.728 +}
   6.729 +
   6.730 +// --------- XMLText ---------- //
   6.731 +char* XMLText::ParseDeep( char* p, StrPair* )
   6.732 +{
   6.733 +	const char* start = p;
   6.734 +	if ( this->CData() ) {
   6.735 +		p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
   6.736 +		if ( !p ) {
   6.737 +			document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
   6.738 +		}
   6.739 +		return p;
   6.740 +	}
   6.741 +	else {
   6.742 +		p = value.ParseText( p, "<", document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES );
   6.743 +		if ( !p ) {
   6.744 +			document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
   6.745 +		}
   6.746 +		if ( p && *p ) {
   6.747 +			return p-1;
   6.748 +		}
   6.749 +	}
   6.750 +	return 0;
   6.751 +}
   6.752 +
   6.753 +
   6.754 +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
   6.755 +{
   6.756 +	if ( !doc ) {
   6.757 +		doc = document;
   6.758 +	}
   6.759 +	XMLText* text = doc->NewText( Value() );	// fixme: this will always allocate memory. Intern?
   6.760 +	text->SetCData( this->CData() );
   6.761 +	return text;
   6.762 +}
   6.763 +
   6.764 +
   6.765 +bool XMLText::ShallowEqual( const XMLNode* compare ) const
   6.766 +{
   6.767 +	return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() ));
   6.768 +}
   6.769 +
   6.770 +
   6.771 +bool XMLText::Accept( XMLVisitor* visitor ) const
   6.772 +{
   6.773 +	return visitor->Visit( *this );
   6.774 +}
   6.775 +
   6.776 +
   6.777 +// --------- XMLComment ---------- //
   6.778 +
   6.779 +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
   6.780 +{
   6.781 +}
   6.782 +
   6.783 +
   6.784 +XMLComment::~XMLComment()
   6.785 +{
   6.786 +	//printf( "~XMLComment\n" );
   6.787 +}
   6.788 +
   6.789 +
   6.790 +char* XMLComment::ParseDeep( char* p, StrPair* )
   6.791 +{
   6.792 +	// Comment parses as text.
   6.793 +	const char* start = p;
   6.794 +	p = value.ParseText( p, "-->", StrPair::COMMENT );
   6.795 +	if ( p == 0 ) {
   6.796 +		document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
   6.797 +	}
   6.798 +	return p;
   6.799 +}
   6.800 +
   6.801 +
   6.802 +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
   6.803 +{
   6.804 +	if ( !doc ) {
   6.805 +		doc = document;
   6.806 +	}
   6.807 +	XMLComment* comment = doc->NewComment( Value() );	// fixme: this will always allocate memory. Intern?
   6.808 +	return comment;
   6.809 +}
   6.810 +
   6.811 +
   6.812 +bool XMLComment::ShallowEqual( const XMLNode* compare ) const
   6.813 +{
   6.814 +	return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() ));
   6.815 +}
   6.816 +
   6.817 +
   6.818 +bool XMLComment::Accept( XMLVisitor* visitor ) const
   6.819 +{
   6.820 +	return visitor->Visit( *this );
   6.821 +}
   6.822 +
   6.823 +
   6.824 +// --------- XMLDeclaration ---------- //
   6.825 +
   6.826 +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
   6.827 +{
   6.828 +}
   6.829 +
   6.830 +
   6.831 +XMLDeclaration::~XMLDeclaration()
   6.832 +{
   6.833 +	//printf( "~XMLDeclaration\n" );
   6.834 +}
   6.835 +
   6.836 +
   6.837 +char* XMLDeclaration::ParseDeep( char* p, StrPair* )
   6.838 +{
   6.839 +	// Declaration parses as text.
   6.840 +	const char* start = p;
   6.841 +	p = value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
   6.842 +	if ( p == 0 ) {
   6.843 +		document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
   6.844 +	}
   6.845 +	return p;
   6.846 +}
   6.847 +
   6.848 +
   6.849 +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
   6.850 +{
   6.851 +	if ( !doc ) {
   6.852 +		doc = document;
   6.853 +	}
   6.854 +	XMLDeclaration* dec = doc->NewDeclaration( Value() );	// fixme: this will always allocate memory. Intern?
   6.855 +	return dec;
   6.856 +}
   6.857 +
   6.858 +
   6.859 +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
   6.860 +{
   6.861 +	return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() ));
   6.862 +}
   6.863 +
   6.864 +
   6.865 +
   6.866 +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
   6.867 +{
   6.868 +	return visitor->Visit( *this );
   6.869 +}
   6.870 +
   6.871 +// --------- XMLUnknown ---------- //
   6.872 +
   6.873 +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
   6.874 +{
   6.875 +}
   6.876 +
   6.877 +
   6.878 +XMLUnknown::~XMLUnknown()
   6.879 +{
   6.880 +}
   6.881 +
   6.882 +
   6.883 +char* XMLUnknown::ParseDeep( char* p, StrPair* )
   6.884 +{
   6.885 +	// Unknown parses as text.
   6.886 +	const char* start = p;
   6.887 +
   6.888 +	p = value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
   6.889 +	if ( !p ) {
   6.890 +		document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
   6.891 +	}
   6.892 +	return p;
   6.893 +}
   6.894 +
   6.895 +
   6.896 +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
   6.897 +{
   6.898 +	if ( !doc ) {
   6.899 +		doc = document;
   6.900 +	}
   6.901 +	XMLUnknown* text = doc->NewUnknown( Value() );	// fixme: this will always allocate memory. Intern?
   6.902 +	return text;
   6.903 +}
   6.904 +
   6.905 +
   6.906 +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
   6.907 +{
   6.908 +	return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() ));
   6.909 +}
   6.910 +
   6.911 +
   6.912 +bool XMLUnknown::Accept( XMLVisitor* visitor ) const
   6.913 +{
   6.914 +	return visitor->Visit( *this );
   6.915 +}
   6.916 +
   6.917 +// --------- XMLAttribute ---------- //
   6.918 +char* XMLAttribute::ParseDeep( char* p, bool processEntities )
   6.919 +{
   6.920 +	p = name.ParseText( p, "=", StrPair::ATTRIBUTE_NAME );
   6.921 +	if ( !p || !*p ) return 0;
   6.922 +
   6.923 +	char endTag[2] = { *p, 0 };
   6.924 +	++p;
   6.925 +	p = value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
   6.926 +	//if ( value.Empty() ) return 0;
   6.927 +	return p;
   6.928 +}
   6.929 +
   6.930 +
   6.931 +void XMLAttribute::SetName( const char* n )
   6.932 +{
   6.933 +	name.SetStr( n );
   6.934 +}
   6.935 +
   6.936 +
   6.937 +int XMLAttribute::QueryIntValue( int* value ) const
   6.938 +{
   6.939 +	if ( TIXML_SSCANF( Value(), "%d", value ) == 1 )
   6.940 +		return XML_NO_ERROR;
   6.941 +	return XML_WRONG_ATTRIBUTE_TYPE;
   6.942 +}
   6.943 +
   6.944 +
   6.945 +int XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
   6.946 +{
   6.947 +	if ( TIXML_SSCANF( Value(), "%u", value ) == 1 )
   6.948 +		return XML_NO_ERROR;
   6.949 +	return XML_WRONG_ATTRIBUTE_TYPE;
   6.950 +}
   6.951 +
   6.952 +
   6.953 +int XMLAttribute::QueryBoolValue( bool* value ) const
   6.954 +{
   6.955 +	int ival = -1;
   6.956 +	QueryIntValue( &ival );
   6.957 +
   6.958 +	if ( ival > 0 || XMLUtil::StringEqual( Value(), "true" ) ) {
   6.959 +		*value = true;
   6.960 +		return XML_NO_ERROR;
   6.961 +	}
   6.962 +	else if ( ival == 0 || XMLUtil::StringEqual( Value(), "false" ) ) {
   6.963 +		*value = false;
   6.964 +		return XML_NO_ERROR;
   6.965 +	}
   6.966 +	return XML_WRONG_ATTRIBUTE_TYPE;
   6.967 +}
   6.968 +
   6.969 +
   6.970 +int XMLAttribute::QueryDoubleValue( double* value ) const
   6.971 +{
   6.972 +	if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 )
   6.973 +		return XML_NO_ERROR;
   6.974 +	return XML_WRONG_ATTRIBUTE_TYPE;
   6.975 +}
   6.976 +
   6.977 +
   6.978 +int XMLAttribute::QueryFloatValue( float* value ) const
   6.979 +{
   6.980 +	if ( TIXML_SSCANF( Value(), "%f", value ) == 1 )
   6.981 +		return XML_NO_ERROR;
   6.982 +	return XML_WRONG_ATTRIBUTE_TYPE;
   6.983 +}
   6.984 +
   6.985 +
   6.986 +void XMLAttribute::SetAttribute( const char* v )
   6.987 +{
   6.988 +	value.SetStr( v );
   6.989 +}
   6.990 +
   6.991 +
   6.992 +void XMLAttribute::SetAttribute( int v )
   6.993 +{
   6.994 +	char buf[BUF_SIZE];
   6.995 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v );	
   6.996 +	value.SetStr( buf );
   6.997 +}
   6.998 +
   6.999 +
  6.1000 +void XMLAttribute::SetAttribute( unsigned v )
  6.1001 +{
  6.1002 +	char buf[BUF_SIZE];
  6.1003 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%u", v );	
  6.1004 +	value.SetStr( buf );
  6.1005 +}
  6.1006 +
  6.1007 +
  6.1008 +void XMLAttribute::SetAttribute( bool v )
  6.1009 +{
  6.1010 +	char buf[BUF_SIZE];
  6.1011 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v ? 1 : 0 );	
  6.1012 +	value.SetStr( buf );
  6.1013 +}
  6.1014 +
  6.1015 +void XMLAttribute::SetAttribute( double v )
  6.1016 +{
  6.1017 +	char buf[BUF_SIZE];
  6.1018 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%f", v );	
  6.1019 +	value.SetStr( buf );
  6.1020 +}
  6.1021 +
  6.1022 +void XMLAttribute::SetAttribute( float v )
  6.1023 +{
  6.1024 +	char buf[BUF_SIZE];
  6.1025 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%f", v );	
  6.1026 +	value.SetStr( buf );
  6.1027 +}
  6.1028 +
  6.1029 +
  6.1030 +// --------- XMLElement ---------- //
  6.1031 +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
  6.1032 +	closingType( 0 ),
  6.1033 +	rootAttribute( 0 )
  6.1034 +{
  6.1035 +}
  6.1036 +
  6.1037 +
  6.1038 +XMLElement::~XMLElement()
  6.1039 +{
  6.1040 +	while( rootAttribute ) {
  6.1041 +		XMLAttribute* next = rootAttribute->next;
  6.1042 +		DELETE_ATTRIBUTE( rootAttribute );
  6.1043 +		rootAttribute = next;
  6.1044 +	}
  6.1045 +}
  6.1046 +
  6.1047 +
  6.1048 +XMLAttribute* XMLElement::FindAttribute( const char* name )
  6.1049 +{
  6.1050 +	XMLAttribute* a = 0;
  6.1051 +	for( a=rootAttribute; a; a = a->next ) {
  6.1052 +		if ( XMLUtil::StringEqual( a->Name(), name ) )
  6.1053 +			return a;
  6.1054 +	}
  6.1055 +	return 0;
  6.1056 +}
  6.1057 +
  6.1058 +
  6.1059 +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
  6.1060 +{
  6.1061 +	XMLAttribute* a = 0;
  6.1062 +	for( a=rootAttribute; a; a = a->next ) {
  6.1063 +		if ( XMLUtil::StringEqual( a->Name(), name ) )
  6.1064 +			return a;
  6.1065 +	}
  6.1066 +	return 0;
  6.1067 +}
  6.1068 +
  6.1069 +
  6.1070 +const char* XMLElement::Attribute( const char* name, const char* value ) const
  6.1071 +{ 
  6.1072 +	const XMLAttribute* a = FindAttribute( name ); 
  6.1073 +	if ( !a ) 
  6.1074 +		return 0; 
  6.1075 +	if ( !value || XMLUtil::StringEqual( a->Value(), value ))
  6.1076 +		return a->Value();
  6.1077 +	return 0;
  6.1078 +}
  6.1079 +
  6.1080 +
  6.1081 +const char* XMLElement::GetText() const
  6.1082 +{
  6.1083 +	if ( FirstChild() && FirstChild()->ToText() ) {
  6.1084 +		return FirstChild()->ToText()->Value();
  6.1085 +	}
  6.1086 +	return 0;
  6.1087 +}
  6.1088 +
  6.1089 +
  6.1090 +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
  6.1091 +{
  6.1092 +	XMLAttribute* last = 0;
  6.1093 +	XMLAttribute* attrib = 0;
  6.1094 +	for( attrib = rootAttribute;
  6.1095 +		 attrib;
  6.1096 +		 last = attrib, attrib = attrib->next )
  6.1097 +	{		 
  6.1098 +		if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
  6.1099 +			break;
  6.1100 +		}
  6.1101 +	}
  6.1102 +	if ( !attrib ) {
  6.1103 +		attrib = new (document->attributePool.Alloc() ) XMLAttribute();
  6.1104 +		attrib->memPool = &document->attributePool;
  6.1105 +		if ( last ) {
  6.1106 +			last->next = attrib;
  6.1107 +		}
  6.1108 +		else {
  6.1109 +			rootAttribute = attrib;
  6.1110 +		}
  6.1111 +		attrib->SetName( name );
  6.1112 +	}
  6.1113 +	return attrib;
  6.1114 +}
  6.1115 +
  6.1116 +
  6.1117 +void XMLElement::DeleteAttribute( const char* name )
  6.1118 +{
  6.1119 +	XMLAttribute* prev = 0;
  6.1120 +	for( XMLAttribute* a=rootAttribute; a; a=a->next ) {
  6.1121 +		if ( XMLUtil::StringEqual( name, a->Name() ) ) {
  6.1122 +			if ( prev ) {
  6.1123 +				prev->next = a->next;
  6.1124 +			}
  6.1125 +			else {
  6.1126 +				rootAttribute = a->next;
  6.1127 +			}
  6.1128 +			DELETE_ATTRIBUTE( a );
  6.1129 +			break;
  6.1130 +		}
  6.1131 +		prev = a;
  6.1132 +	}
  6.1133 +}
  6.1134 +
  6.1135 +
  6.1136 +char* XMLElement::ParseAttributes( char* p )
  6.1137 +{
  6.1138 +	const char* start = p;
  6.1139 +	XMLAttribute* prevAttribute = 0;
  6.1140 +
  6.1141 +	// Read the attributes.
  6.1142 +	while( p ) {
  6.1143 +		p = XMLUtil::SkipWhiteSpace( p );
  6.1144 +		if ( !p || !(*p) ) {
  6.1145 +			document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
  6.1146 +			return 0;
  6.1147 +		}
  6.1148 +
  6.1149 +		// attribute.
  6.1150 +		if ( XMLUtil::IsAlpha( *p ) ) {
  6.1151 +			XMLAttribute* attrib = new (document->attributePool.Alloc() ) XMLAttribute();
  6.1152 +			attrib->memPool = &document->attributePool;
  6.1153 +
  6.1154 +			p = attrib->ParseDeep( p, document->ProcessEntities() );
  6.1155 +			if ( !p || Attribute( attrib->Name() ) ) {
  6.1156 +				DELETE_ATTRIBUTE( attrib );
  6.1157 +				document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
  6.1158 +				return 0;
  6.1159 +			}
  6.1160 +			// There is a minor bug here: if the attribute in the source xml
  6.1161 +			// document is duplicated, it will not be detected and the
  6.1162 +			// attribute will be doubly added. However, tracking the 'prevAttribute'
  6.1163 +			// avoids re-scanning the attribute list. Preferring performance for
  6.1164 +			// now, may reconsider in the future.
  6.1165 +			if ( prevAttribute ) { 
  6.1166 +				prevAttribute->next = attrib;
  6.1167 +			}
  6.1168 +			else {
  6.1169 +				rootAttribute = attrib;
  6.1170 +			}	
  6.1171 +			prevAttribute = attrib;
  6.1172 +		}
  6.1173 +		// end of the tag
  6.1174 +		else if ( *p == '/' && *(p+1) == '>' ) {
  6.1175 +			closingType = CLOSED;
  6.1176 +			return p+2;	// done; sealed element.
  6.1177 +		}
  6.1178 +		// end of the tag
  6.1179 +		else if ( *p == '>' ) {
  6.1180 +			++p;
  6.1181 +			break;
  6.1182 +		}
  6.1183 +		else {
  6.1184 +			document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
  6.1185 +			return 0;
  6.1186 +		}
  6.1187 +	}
  6.1188 +	return p;
  6.1189 +}
  6.1190 +
  6.1191 +
  6.1192 +//
  6.1193 +//	<ele></ele>
  6.1194 +//	<ele>foo<b>bar</b></ele>
  6.1195 +//
  6.1196 +char* XMLElement::ParseDeep( char* p, StrPair* strPair )
  6.1197 +{
  6.1198 +	// Read the element name.
  6.1199 +	p = XMLUtil::SkipWhiteSpace( p );
  6.1200 +	if ( !p ) return 0;
  6.1201 +
  6.1202 +	// The closing element is the </element> form. It is
  6.1203 +	// parsed just like a regular element then deleted from
  6.1204 +	// the DOM.
  6.1205 +	if ( *p == '/' ) {
  6.1206 +		closingType = CLOSING;
  6.1207 +		++p;
  6.1208 +	}
  6.1209 +
  6.1210 +	p = value.ParseName( p );
  6.1211 +	if ( value.Empty() ) return 0;
  6.1212 +
  6.1213 +	p = ParseAttributes( p );
  6.1214 +	if ( !p || !*p || closingType ) 
  6.1215 +		return p;
  6.1216 +
  6.1217 +	p = XMLNode::ParseDeep( p, strPair );
  6.1218 +	return p;
  6.1219 +}
  6.1220 +
  6.1221 +
  6.1222 +
  6.1223 +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
  6.1224 +{
  6.1225 +	if ( !doc ) {
  6.1226 +		doc = document;
  6.1227 +	}
  6.1228 +	XMLElement* element = doc->NewElement( Value() );					// fixme: this will always allocate memory. Intern?
  6.1229 +	for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
  6.1230 +		element->SetAttribute( a->Name(), a->Value() );					// fixme: this will always allocate memory. Intern?
  6.1231 +	}
  6.1232 +	return element;
  6.1233 +}
  6.1234 +
  6.1235 +
  6.1236 +bool XMLElement::ShallowEqual( const XMLNode* compare ) const
  6.1237 +{
  6.1238 +	const XMLElement* other = compare->ToElement();
  6.1239 +	if ( other && XMLUtil::StringEqual( other->Value(), Value() )) {
  6.1240 +
  6.1241 +		const XMLAttribute* a=FirstAttribute();
  6.1242 +		const XMLAttribute* b=other->FirstAttribute();
  6.1243 +
  6.1244 +		while ( a && b ) {
  6.1245 +			if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
  6.1246 +				return false;
  6.1247 +			}
  6.1248 +		}	
  6.1249 +		if ( a || b ) {
  6.1250 +			// different count
  6.1251 +			return false;
  6.1252 +		}
  6.1253 +		return true;
  6.1254 +	}
  6.1255 +	return false;
  6.1256 +}
  6.1257 +
  6.1258 +
  6.1259 +bool XMLElement::Accept( XMLVisitor* visitor ) const
  6.1260 +{
  6.1261 +	if ( visitor->VisitEnter( *this, rootAttribute ) ) 
  6.1262 +	{
  6.1263 +		for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
  6.1264 +		{
  6.1265 +			if ( !node->Accept( visitor ) )
  6.1266 +				break;
  6.1267 +		}
  6.1268 +	}
  6.1269 +	return visitor->VisitExit( *this );
  6.1270 +}
  6.1271 +
  6.1272 +
  6.1273 +// --------- XMLDocument ----------- //
  6.1274 +XMLDocument::XMLDocument( bool _processEntities ) :
  6.1275 +	XMLNode( 0 ),
  6.1276 +	writeBOM( false ),
  6.1277 +	processEntities( _processEntities ),
  6.1278 +	errorID( 0 ),
  6.1279 +	errorStr1( 0 ),
  6.1280 +	errorStr2( 0 ),
  6.1281 +	charBuffer( 0 )
  6.1282 +{
  6.1283 +	document = this;	// avoid warning about 'this' in initializer list
  6.1284 +}
  6.1285 +
  6.1286 +
  6.1287 +XMLDocument::~XMLDocument()
  6.1288 +{
  6.1289 +	DeleteChildren();
  6.1290 +	delete [] charBuffer;
  6.1291 +
  6.1292 +#if 0
  6.1293 +	textPool.Trace( "text" );
  6.1294 +	elementPool.Trace( "element" );
  6.1295 +	commentPool.Trace( "comment" );
  6.1296 +	attributePool.Trace( "attribute" );
  6.1297 +#endif
  6.1298 +
  6.1299 +	TIXMLASSERT( textPool.CurrentAllocs() == 0 );
  6.1300 +	TIXMLASSERT( elementPool.CurrentAllocs() == 0 );
  6.1301 +	TIXMLASSERT( commentPool.CurrentAllocs() == 0 );
  6.1302 +	TIXMLASSERT( attributePool.CurrentAllocs() == 0 );
  6.1303 +}
  6.1304 +
  6.1305 +
  6.1306 +void XMLDocument::InitDocument()
  6.1307 +{
  6.1308 +	errorID = XML_NO_ERROR;
  6.1309 +	errorStr1 = 0;
  6.1310 +	errorStr2 = 0;
  6.1311 +
  6.1312 +	delete [] charBuffer;
  6.1313 +	charBuffer = 0;
  6.1314 +
  6.1315 +}
  6.1316 +
  6.1317 +
  6.1318 +XMLElement* XMLDocument::NewElement( const char* name )
  6.1319 +{
  6.1320 +	XMLElement* ele = new (elementPool.Alloc()) XMLElement( this );
  6.1321 +	ele->memPool = &elementPool;
  6.1322 +	ele->SetName( name );
  6.1323 +	return ele;
  6.1324 +}
  6.1325 +
  6.1326 +
  6.1327 +XMLComment* XMLDocument::NewComment( const char* str )
  6.1328 +{
  6.1329 +	XMLComment* comment = new (commentPool.Alloc()) XMLComment( this );
  6.1330 +	comment->memPool = &commentPool;
  6.1331 +	comment->SetValue( str );
  6.1332 +	return comment;
  6.1333 +}
  6.1334 +
  6.1335 +
  6.1336 +XMLText* XMLDocument::NewText( const char* str )
  6.1337 +{
  6.1338 +	XMLText* text = new (textPool.Alloc()) XMLText( this );
  6.1339 +	text->memPool = &textPool;
  6.1340 +	text->SetValue( str );
  6.1341 +	return text;
  6.1342 +}
  6.1343 +
  6.1344 +
  6.1345 +XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
  6.1346 +{
  6.1347 +	XMLDeclaration* dec = new (commentPool.Alloc()) XMLDeclaration( this );
  6.1348 +	dec->memPool = &commentPool;
  6.1349 +	dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
  6.1350 +	return dec;
  6.1351 +}
  6.1352 +
  6.1353 +
  6.1354 +XMLUnknown* XMLDocument::NewUnknown( const char* str )
  6.1355 +{
  6.1356 +	XMLUnknown* unk = new (commentPool.Alloc()) XMLUnknown( this );
  6.1357 +	unk->memPool = &commentPool;
  6.1358 +	unk->SetValue( str );
  6.1359 +	return unk;
  6.1360 +}
  6.1361 +
  6.1362 +
  6.1363 +int XMLDocument::LoadFile( const char* filename )
  6.1364 +{
  6.1365 +	DeleteChildren();
  6.1366 +	InitDocument();
  6.1367 +
  6.1368 +#if defined(_MSC_VER)
  6.1369 +#pragma warning ( push )
  6.1370 +#pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
  6.1371 +#endif
  6.1372 +	FILE* fp = fopen( filename, "rb" );
  6.1373 +#if defined(_MSC_VER)
  6.1374 +#pragma warning ( pop )
  6.1375 +#endif
  6.1376 +	if ( !fp ) {
  6.1377 +		SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
  6.1378 +		return errorID;
  6.1379 +	}
  6.1380 +	LoadFile( fp );
  6.1381 +	fclose( fp );
  6.1382 +	return errorID;
  6.1383 +}
  6.1384 +
  6.1385 +
  6.1386 +int XMLDocument::LoadFile( FILE* fp ) 
  6.1387 +{
  6.1388 +	DeleteChildren();
  6.1389 +	InitDocument();
  6.1390 +
  6.1391 +	fseek( fp, 0, SEEK_END );
  6.1392 +	unsigned size = ftell( fp );
  6.1393 +	fseek( fp, 0, SEEK_SET );
  6.1394 +
  6.1395 +	if ( size == 0 ) {
  6.1396 +		return errorID;
  6.1397 +	}
  6.1398 +
  6.1399 +	charBuffer = new char[size+1];
  6.1400 +	fread( charBuffer, size, 1, fp );
  6.1401 +	charBuffer[size] = 0;
  6.1402 +
  6.1403 +	const char* p = charBuffer;
  6.1404 +	p = XMLUtil::SkipWhiteSpace( p );
  6.1405 +	p = XMLUtil::ReadBOM( p, &writeBOM );
  6.1406 +	if ( !p || !*p ) {
  6.1407 +		SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
  6.1408 +		return errorID;
  6.1409 +	}
  6.1410 +
  6.1411 +	ParseDeep( charBuffer + (p-charBuffer), 0 );
  6.1412 +	return errorID;
  6.1413 +}
  6.1414 +
  6.1415 +
  6.1416 +int XMLDocument::SaveFile( const char* filename )
  6.1417 +{
  6.1418 +#if defined(_MSC_VER)
  6.1419 +#pragma warning ( push )
  6.1420 +#pragma warning ( disable : 4996 )		// Fail to see a compelling reason why this should be deprecated.
  6.1421 +#endif
  6.1422 +	FILE* fp = fopen( filename, "w" );
  6.1423 +#if defined(_MSC_VER)
  6.1424 +#pragma warning ( pop )
  6.1425 +#endif
  6.1426 +	if ( !fp ) {
  6.1427 +		SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
  6.1428 +		return errorID;
  6.1429 +	}
  6.1430 +	SaveFile(fp);
  6.1431 +	fclose( fp );
  6.1432 +	return errorID;
  6.1433 +}
  6.1434 +
  6.1435 +
  6.1436 +int XMLDocument::SaveFile( FILE* fp )
  6.1437 +{
  6.1438 +	XMLPrinter stream( fp );
  6.1439 +	Print( &stream );
  6.1440 +	return errorID;
  6.1441 +}
  6.1442 +
  6.1443 +
  6.1444 +int XMLDocument::Parse( const char* p )
  6.1445 +{
  6.1446 +	DeleteChildren();
  6.1447 +	InitDocument();
  6.1448 +
  6.1449 +	if ( !p || !*p ) {
  6.1450 +		SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
  6.1451 +		return errorID;
  6.1452 +	}
  6.1453 +	p = XMLUtil::SkipWhiteSpace( p );
  6.1454 +	p = XMLUtil::ReadBOM( p, &writeBOM );
  6.1455 +	if ( !p || !*p ) {
  6.1456 +		SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
  6.1457 +		return errorID;
  6.1458 +	}
  6.1459 +
  6.1460 +	size_t len = strlen( p );
  6.1461 +	charBuffer = new char[ len+1 ];
  6.1462 +	memcpy( charBuffer, p, len+1 );
  6.1463 +
  6.1464 +	
  6.1465 +	ParseDeep( charBuffer, 0 );
  6.1466 +	return errorID;
  6.1467 +}
  6.1468 +
  6.1469 +
  6.1470 +void XMLDocument::Print( XMLPrinter* streamer ) 
  6.1471 +{
  6.1472 +	XMLPrinter stdStreamer( stdout );
  6.1473 +	if ( !streamer )
  6.1474 +		streamer = &stdStreamer;
  6.1475 +	Accept( streamer );
  6.1476 +}
  6.1477 +
  6.1478 +
  6.1479 +void XMLDocument::SetError( int error, const char* str1, const char* str2 )
  6.1480 +{
  6.1481 +	errorID = error;
  6.1482 +	errorStr1 = str1;
  6.1483 +	errorStr2 = str2;
  6.1484 +}
  6.1485 +
  6.1486 +
  6.1487 +void XMLDocument::PrintError() const 
  6.1488 +{
  6.1489 +	if ( errorID ) {
  6.1490 +		static const int LEN = 20;
  6.1491 +		char buf1[LEN] = { 0 };
  6.1492 +		char buf2[LEN] = { 0 };
  6.1493 +		
  6.1494 +		if ( errorStr1 ) {
  6.1495 +			TIXML_SNPRINTF( buf1, LEN, "%s", errorStr1 );
  6.1496 +		}
  6.1497 +		if ( errorStr2 ) {
  6.1498 +			TIXML_SNPRINTF( buf2, LEN, "%s", errorStr2 );
  6.1499 +		}
  6.1500 +
  6.1501 +		printf( "XMLDocument error id=%d str1=%s str2=%s\n",
  6.1502 +			    errorID, buf1, buf2 );
  6.1503 +	}
  6.1504 +}
  6.1505 +
  6.1506 +
  6.1507 +XMLPrinter::XMLPrinter( FILE* file ) : 
  6.1508 +	elementJustOpened( false ), 
  6.1509 +	firstElement( true ),
  6.1510 +	fp( file ), 
  6.1511 +	depth( 0 ), 
  6.1512 +	textDepth( -1 ),
  6.1513 +	processEntities( true )
  6.1514 +{
  6.1515 +	for( int i=0; i<ENTITY_RANGE; ++i ) {
  6.1516 +		entityFlag[i] = false;
  6.1517 +		restrictedEntityFlag[i] = false;
  6.1518 +	}
  6.1519 +	for( int i=0; i<NUM_ENTITIES; ++i ) {
  6.1520 +		TIXMLASSERT( entities[i].value < ENTITY_RANGE );
  6.1521 +		if ( entities[i].value < ENTITY_RANGE ) {
  6.1522 +			entityFlag[ (int)entities[i].value ] = true;
  6.1523 +		}
  6.1524 +	}
  6.1525 +	restrictedEntityFlag[(int)'&'] = true;
  6.1526 +	restrictedEntityFlag[(int)'<'] = true;
  6.1527 +	restrictedEntityFlag[(int)'>'] = true;	// not required, but consistency is nice
  6.1528 +	buffer.Push( 0 );
  6.1529 +}
  6.1530 +
  6.1531 +
  6.1532 +void XMLPrinter::Print( const char* format, ... )
  6.1533 +{
  6.1534 +    va_list     va;
  6.1535 +    va_start( va, format );
  6.1536 +
  6.1537 +	if ( fp ) {
  6.1538 +		vfprintf( fp, format, va );
  6.1539 +	}
  6.1540 +	else {
  6.1541 +		// This seems brutally complex. Haven't figured out a better
  6.1542 +		// way on windows.
  6.1543 +		#ifdef _MSC_VER
  6.1544 +			int len = -1;
  6.1545 +			int expand = 1000;
  6.1546 +			while ( len < 0 ) {
  6.1547 +				len = vsnprintf_s( accumulator.Mem(), accumulator.Capacity(), _TRUNCATE, format, va );
  6.1548 +				if ( len < 0 ) {
  6.1549 +					expand *= 3/2;
  6.1550 +					accumulator.PushArr( expand );
  6.1551 +				}
  6.1552 +			}
  6.1553 +			char* p = buffer.PushArr( len ) - 1;
  6.1554 +			memcpy( p, accumulator.Mem(), len+1 );
  6.1555 +		#else
  6.1556 +			int len = vsnprintf( 0, 0, format, va );
  6.1557 +			// Close out and re-start the va-args
  6.1558 +			va_end( va );
  6.1559 +			va_start( va, format );		
  6.1560 +			char* p = buffer.PushArr( len ) - 1;
  6.1561 +			vsnprintf( p, len+1, format, va );
  6.1562 +		#endif
  6.1563 +	}
  6.1564 +    va_end( va );
  6.1565 +}
  6.1566 +
  6.1567 +
  6.1568 +void XMLPrinter::PrintSpace( int depth )
  6.1569 +{
  6.1570 +	for( int i=0; i<depth; ++i ) {
  6.1571 +		Print( "    " );
  6.1572 +	}
  6.1573 +}
  6.1574 +
  6.1575 +
  6.1576 +void XMLPrinter::PrintString( const char* p, bool restricted )
  6.1577 +{
  6.1578 +	// Look for runs of bytes between entities to print.
  6.1579 +	const char* q = p;
  6.1580 +	const bool* flag = restricted ? restrictedEntityFlag : entityFlag;
  6.1581 +
  6.1582 +	if ( processEntities ) {
  6.1583 +		while ( *q ) {
  6.1584 +			// Remember, char is sometimes signed. (How many times has that bitten me?)
  6.1585 +			if ( *q > 0 && *q < ENTITY_RANGE ) {
  6.1586 +				// Check for entities. If one is found, flush
  6.1587 +				// the stream up until the entity, write the 
  6.1588 +				// entity, and keep looking.
  6.1589 +				if ( flag[(unsigned)(*q)] ) {
  6.1590 +					while ( p < q ) {
  6.1591 +						Print( "%c", *p );
  6.1592 +						++p;
  6.1593 +					}
  6.1594 +					for( int i=0; i<NUM_ENTITIES; ++i ) {
  6.1595 +						if ( entities[i].value == *q ) {
  6.1596 +							Print( "&%s;", entities[i].pattern );
  6.1597 +							break;
  6.1598 +						}
  6.1599 +					}
  6.1600 +					++p;
  6.1601 +				}
  6.1602 +			}
  6.1603 +			++q;
  6.1604 +		}
  6.1605 +	}
  6.1606 +	// Flush the remaining string. This will be the entire
  6.1607 +	// string if an entity wasn't found.
  6.1608 +	if ( !processEntities || (q-p > 0) ) {
  6.1609 +		Print( "%s", p );
  6.1610 +	}
  6.1611 +}
  6.1612 +
  6.1613 +
  6.1614 +void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
  6.1615 +{
  6.1616 +	static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
  6.1617 +	if ( writeBOM ) {
  6.1618 +		Print( "%s", bom );
  6.1619 +	}
  6.1620 +	if ( writeDec ) {
  6.1621 +		PushDeclaration( "xml version=\"1.0\"" );
  6.1622 +	}
  6.1623 +}
  6.1624 +
  6.1625 +
  6.1626 +void XMLPrinter::OpenElement( const char* name )
  6.1627 +{
  6.1628 +	if ( elementJustOpened ) {
  6.1629 +		SealElement();
  6.1630 +	}
  6.1631 +	stack.Push( name );
  6.1632 +
  6.1633 +	if ( textDepth < 0 && !firstElement ) {
  6.1634 +		Print( "\n" );
  6.1635 +		PrintSpace( depth );
  6.1636 +	}
  6.1637 +
  6.1638 +	Print( "<%s", name );
  6.1639 +	elementJustOpened = true;
  6.1640 +	firstElement = false;
  6.1641 +	++depth;
  6.1642 +}
  6.1643 +
  6.1644 +
  6.1645 +void XMLPrinter::PushAttribute( const char* name, const char* value )
  6.1646 +{
  6.1647 +	TIXMLASSERT( elementJustOpened );
  6.1648 +	Print( " %s=\"", name );
  6.1649 +	PrintString( value, false );
  6.1650 +	Print( "\"" );
  6.1651 +}
  6.1652 +
  6.1653 +
  6.1654 +void XMLPrinter::PushAttribute( const char* name, int v )
  6.1655 +{
  6.1656 +	char buf[BUF_SIZE];
  6.1657 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v );	
  6.1658 +	PushAttribute( name, buf );
  6.1659 +}
  6.1660 +
  6.1661 +
  6.1662 +void XMLPrinter::PushAttribute( const char* name, unsigned v )
  6.1663 +{
  6.1664 +	char buf[BUF_SIZE];
  6.1665 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%u", v );	
  6.1666 +	PushAttribute( name, buf );
  6.1667 +}
  6.1668 +
  6.1669 +
  6.1670 +void XMLPrinter::PushAttribute( const char* name, bool v )
  6.1671 +{
  6.1672 +	char buf[BUF_SIZE];
  6.1673 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%d", v ? 1 : 0 );	
  6.1674 +	PushAttribute( name, buf );
  6.1675 +}
  6.1676 +
  6.1677 +
  6.1678 +void XMLPrinter::PushAttribute( const char* name, double v )
  6.1679 +{
  6.1680 +	char buf[BUF_SIZE];
  6.1681 +	TIXML_SNPRINTF( buf, BUF_SIZE, "%f", v );	
  6.1682 +	PushAttribute( name, buf );
  6.1683 +}
  6.1684 +
  6.1685 +
  6.1686 +void XMLPrinter::CloseElement()
  6.1687 +{
  6.1688 +	--depth;
  6.1689 +	const char* name = stack.Pop();
  6.1690 +
  6.1691 +	if ( elementJustOpened ) {
  6.1692 +		Print( "/>" );
  6.1693 +	}
  6.1694 +	else {
  6.1695 +		if ( textDepth < 0 ) {
  6.1696 +			Print( "\n" );
  6.1697 +			PrintSpace( depth );
  6.1698 +		}
  6.1699 +		Print( "</%s>", name );
  6.1700 +	}
  6.1701 +
  6.1702 +	if ( textDepth == depth )
  6.1703 +		textDepth = -1;
  6.1704 +	if ( depth == 0 )
  6.1705 +		Print( "\n" );
  6.1706 +	elementJustOpened = false;
  6.1707 +}
  6.1708 +
  6.1709 +
  6.1710 +void XMLPrinter::SealElement()
  6.1711 +{
  6.1712 +	elementJustOpened = false;
  6.1713 +	Print( ">" );
  6.1714 +}
  6.1715 +
  6.1716 +
  6.1717 +void XMLPrinter::PushText( const char* text, bool cdata )
  6.1718 +{
  6.1719 +	textDepth = depth-1;
  6.1720 +
  6.1721 +	if ( elementJustOpened ) {
  6.1722 +		SealElement();
  6.1723 +	}
  6.1724 +	if ( cdata ) {
  6.1725 +		Print( "<![CDATA[" );
  6.1726 +		Print( "%s", text );
  6.1727 +		Print( "]]>" );
  6.1728 +	}
  6.1729 +	else {
  6.1730 +		PrintString( text, true );
  6.1731 +	}
  6.1732 +}
  6.1733 +
  6.1734 +
  6.1735 +void XMLPrinter::PushComment( const char* comment )
  6.1736 +{
  6.1737 +	if ( elementJustOpened ) {
  6.1738 +		SealElement();
  6.1739 +	}
  6.1740 +	if ( textDepth < 0 && !firstElement ) {
  6.1741 +		Print( "\n" );
  6.1742 +		PrintSpace( depth );
  6.1743 +	}
  6.1744 +	firstElement = false;
  6.1745 +	Print( "<!--%s-->", comment );
  6.1746 +}
  6.1747 +
  6.1748 +
  6.1749 +void XMLPrinter::PushDeclaration( const char* value )
  6.1750 +{
  6.1751 +	if ( elementJustOpened ) {
  6.1752 +		SealElement();
  6.1753 +	}
  6.1754 +	if ( textDepth < 0 && !firstElement) {
  6.1755 +		Print( "\n" );
  6.1756 +		PrintSpace( depth );
  6.1757 +	}
  6.1758 +	firstElement = false;
  6.1759 +	Print( "<?%s?>", value );
  6.1760 +}
  6.1761 +
  6.1762 +
  6.1763 +void XMLPrinter::PushUnknown( const char* value )
  6.1764 +{
  6.1765 +	if ( elementJustOpened ) {
  6.1766 +		SealElement();
  6.1767 +	}
  6.1768 +	if ( textDepth < 0 && !firstElement ) {
  6.1769 +		Print( "\n" );
  6.1770 +		PrintSpace( depth );
  6.1771 +	}
  6.1772 +	firstElement = false;
  6.1773 +	Print( "<!%s>", value );
  6.1774 +}
  6.1775 +
  6.1776 +
  6.1777 +bool XMLPrinter::VisitEnter( const XMLDocument& doc )
  6.1778 +{
  6.1779 +	processEntities = doc.ProcessEntities();
  6.1780 +	if ( doc.HasBOM() ) {
  6.1781 +		PushHeader( true, false );
  6.1782 +	}
  6.1783 +	return true;
  6.1784 +}
  6.1785 +
  6.1786 +
  6.1787 +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
  6.1788 +{
  6.1789 +	OpenElement( element.Name() );
  6.1790 +	while ( attribute ) {
  6.1791 +		PushAttribute( attribute->Name(), attribute->Value() );
  6.1792 +		attribute = attribute->Next();
  6.1793 +	}
  6.1794 +	return true;
  6.1795 +}
  6.1796 +
  6.1797 +
  6.1798 +bool XMLPrinter::VisitExit( const XMLElement& )
  6.1799 +{
  6.1800 +	CloseElement();
  6.1801 +	return true;
  6.1802 +}
  6.1803 +
  6.1804 +
  6.1805 +bool XMLPrinter::Visit( const XMLText& text )
  6.1806 +{
  6.1807 +	PushText( text.Value(), text.CData() );
  6.1808 +	return true;
  6.1809 +}
  6.1810 +
  6.1811 +
  6.1812 +bool XMLPrinter::Visit( const XMLComment& comment )
  6.1813 +{
  6.1814 +	PushComment( comment.Value() );
  6.1815 +	return true;
  6.1816 +}
  6.1817 +
  6.1818 +bool XMLPrinter::Visit( const XMLDeclaration& declaration )
  6.1819 +{
  6.1820 +	PushDeclaration( declaration.Value() );
  6.1821 +	return true;
  6.1822 +}
  6.1823 +
  6.1824 +
  6.1825 +bool XMLPrinter::Visit( const XMLUnknown& unknown )
  6.1826 +{
  6.1827 +	PushUnknown( unknown.Value() );
  6.1828 +	return true;
  6.1829 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/level/src/tinyxml2.h	Mon May 21 19:07:40 2012 +0300
     7.3 @@ -0,0 +1,1403 @@
     7.4 +/*
     7.5 +Original code by Lee Thomason (www.grinninglizard.com)
     7.6 +
     7.7 +This software is provided 'as-is', without any express or implied
     7.8 +warranty. In no event will the authors be held liable for any
     7.9 +damages arising from the use of this software.
    7.10 +
    7.11 +Permission is granted to anyone to use this software for any
    7.12 +purpose, including commercial applications, and to alter it and
    7.13 +redistribute it freely, subject to the following restrictions:
    7.14 +
    7.15 +1. The origin of this software must not be misrepresented; you must
    7.16 +not claim that you wrote the original software. If you use this
    7.17 +software in a product, an acknowledgment in the product documentation
    7.18 +would be appreciated but is not required.
    7.19 +
    7.20 +2. Altered source versions must be plainly marked as such, and
    7.21 +must not be misrepresented as being the original software.
    7.22 +
    7.23 +3. This notice may not be removed or altered from any source
    7.24 +distribution.
    7.25 +*/
    7.26 +
    7.27 +#ifndef TINYXML2_INCLUDED
    7.28 +#define TINYXML2_INCLUDED
    7.29 +
    7.30 +#include <cctype>
    7.31 +#include <climits>
    7.32 +#include <cstdio>
    7.33 +#include <cstring>
    7.34 +#include <cstdarg>
    7.35 +
    7.36 +/* 
    7.37 +   TODO: intern strings instead of allocation.
    7.38 +*/
    7.39 +/*
    7.40 +	gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
    7.41 +*/
    7.42 +
    7.43 +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
    7.44 +	#ifndef DEBUG
    7.45 +		#define DEBUG
    7.46 +	#endif
    7.47 +#endif
    7.48 +
    7.49 +
    7.50 +#if defined(DEBUG)
    7.51 +        #if defined(_MSC_VER)
    7.52 +                #define TIXMLASSERT( x )           if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
    7.53 +        #elif defined (ANDROID_NDK)
    7.54 +                #include <android/log.h>
    7.55 +                #define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
    7.56 +        #else
    7.57 +                #include <assert.h>
    7.58 +                #define TIXMLASSERT                assert
    7.59 +        #endif
    7.60 +#else
    7.61 +        #define TIXMLASSERT( x )           {}
    7.62 +#endif
    7.63 +
    7.64 +
    7.65 +#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
    7.66 +	// Microsoft visual studio, version 2005 and higher.
    7.67 +	/*int _snprintf_s(
    7.68 +	   char *buffer,
    7.69 +	   size_t sizeOfBuffer,
    7.70 +	   size_t count,	
    7.71 +	   const char *format [,
    7.72 +		  argument] ... 
    7.73 +	);*/
    7.74 +	inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
    7.75 +	    va_list va;
    7.76 +		va_start( va, format );
    7.77 +		int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
    7.78 +	    va_end( va );
    7.79 +		return result;
    7.80 +	}
    7.81 +	#define TIXML_SSCANF   sscanf_s
    7.82 +#else
    7.83 +	// GCC version 3 and higher
    7.84 +	//#warning( "Using sn* functions." )
    7.85 +	#define TIXML_SNPRINTF snprintf
    7.86 +	#define TIXML_SSCANF   sscanf
    7.87 +#endif
    7.88 +
    7.89 +static const int TIXML2_MAJOR_VERSION = 1;
    7.90 +static const int TIXML2_MINOR_VERSION = 0;
    7.91 +static const int TIXML2_PATCH_VERSION = 1;
    7.92 +
    7.93 +namespace tinyxml2
    7.94 +{
    7.95 +class XMLDocument;
    7.96 +class XMLElement;
    7.97 +class XMLAttribute;
    7.98 +class XMLComment;
    7.99 +class XMLNode;
   7.100 +class XMLText;
   7.101 +class XMLDeclaration;
   7.102 +class XMLUnknown;
   7.103 +
   7.104 +class XMLPrinter;
   7.105 +
   7.106 +/*
   7.107 +	A class that wraps strings. Normally stores the start and end
   7.108 +	pointers into the XML file itself, and will apply normalization
   7.109 +	and entity translation if actually read. Can also store (and memory
   7.110 +	manage) a traditional char[]
   7.111 +*/
   7.112 +class StrPair
   7.113 +{
   7.114 +public:
   7.115 +	enum {
   7.116 +		NEEDS_ENTITY_PROCESSING			= 0x01,
   7.117 +		NEEDS_NEWLINE_NORMALIZATION		= 0x02,
   7.118 +
   7.119 +		TEXT_ELEMENT		= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
   7.120 +		TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
   7.121 +		ATTRIBUTE_NAME		= 0,
   7.122 +		ATTRIBUTE_VALUE		= NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
   7.123 +		ATTRIBUTE_VALUE_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
   7.124 +		COMMENT				= NEEDS_NEWLINE_NORMALIZATION
   7.125 +	};
   7.126 +
   7.127 +	StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
   7.128 +	~StrPair();
   7.129 +
   7.130 +	void Set( char* _start, char* _end, int _flags ) {
   7.131 +		Reset();
   7.132 +		this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
   7.133 +	}
   7.134 +	const char* GetStr();
   7.135 +	bool Empty() const { return start == end; }
   7.136 +
   7.137 +	void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
   7.138 +	void SetStr( const char* str, int flags=0 );
   7.139 +
   7.140 +	char* ParseText( char* in, const char* endTag, int strFlags );
   7.141 +	char* ParseName( char* in );
   7.142 +
   7.143 +
   7.144 +private:
   7.145 +	void Reset();
   7.146 +
   7.147 +	enum {
   7.148 +		NEEDS_FLUSH = 0x100,
   7.149 +		NEEDS_DELETE = 0x200
   7.150 +	};
   7.151 +
   7.152 +	// After parsing, if *end != 0, it can be set to zero.
   7.153 +	int flags;
   7.154 +	char* start;	
   7.155 +	char* end;
   7.156 +};
   7.157 +
   7.158 +
   7.159 +/*
   7.160 +	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
   7.161 +	Has a small initial memory pool, so that low or no usage will not
   7.162 +	cause a call to new/delete
   7.163 +*/
   7.164 +template <class T, int INIT>
   7.165 +class DynArray
   7.166 +{
   7.167 +public:
   7.168 +	DynArray< T, INIT >() 
   7.169 +	{
   7.170 +		mem = pool;
   7.171 +		allocated = INIT;
   7.172 +		size = 0;
   7.173 +	}
   7.174 +	~DynArray()
   7.175 +	{
   7.176 +		if ( mem != pool ) {
   7.177 +			delete [] mem;
   7.178 +		}
   7.179 +	}
   7.180 +	void Push( T t )
   7.181 +	{
   7.182 +		EnsureCapacity( size+1 );
   7.183 +		mem[size++] = t;
   7.184 +	}
   7.185 +
   7.186 +	T* PushArr( int count )
   7.187 +	{
   7.188 +		EnsureCapacity( size+count );
   7.189 +		T* ret = &mem[size];
   7.190 +		size += count;
   7.191 +		return ret;
   7.192 +	}
   7.193 +	T Pop() {
   7.194 +		return mem[--size];
   7.195 +	}
   7.196 +	void PopArr( int count ) 
   7.197 +	{
   7.198 +		TIXMLASSERT( size >= count );
   7.199 +		size -= count;
   7.200 +	}
   7.201 +
   7.202 +	bool Empty() const					{ return size == 0; }
   7.203 +	T& operator[](int i)				{ TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
   7.204 +	const T& operator[](int i) const	{ TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
   7.205 +	int Size() const					{ return size; }
   7.206 +	int Capacity() const				{ return allocated; }
   7.207 +	const T* Mem() const				{ return mem; }
   7.208 +	T* Mem()							{ return mem; }
   7.209 +
   7.210 +
   7.211 +private:
   7.212 +	void EnsureCapacity( int cap ) {
   7.213 +		if ( cap > allocated ) {
   7.214 +			int newAllocated = cap * 2;
   7.215 +			T* newMem = new T[newAllocated];
   7.216 +			memcpy( newMem, mem, sizeof(T)*size );	// warning: not using constructors, only works for PODs
   7.217 +			if ( mem != pool ) delete [] mem;
   7.218 +			mem = newMem;
   7.219 +			allocated = newAllocated;
   7.220 +		}
   7.221 +	}
   7.222 +
   7.223 +	T* mem;
   7.224 +	T pool[INIT];
   7.225 +	int allocated;		// objects allocated
   7.226 +	int size;			// number objects in use
   7.227 +};
   7.228 +
   7.229 +
   7.230 +/*
   7.231 +	Parent virtual class of a pool for fast allocation
   7.232 +	and deallocation of objects.
   7.233 +*/
   7.234 +class MemPool
   7.235 +{
   7.236 +public:
   7.237 +	MemPool() {}
   7.238 +	virtual ~MemPool() {}
   7.239 +
   7.240 +	virtual int ItemSize() const = 0;
   7.241 +	virtual void* Alloc() = 0;
   7.242 +	virtual void Free( void* ) = 0; 
   7.243 +};
   7.244 +
   7.245 +
   7.246 +/*
   7.247 +	Template child class to create pools of the correct type.
   7.248 +*/
   7.249 +template< int SIZE >
   7.250 +class MemPoolT : public MemPool
   7.251 +{
   7.252 +public:
   7.253 +	MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0)	{}
   7.254 +	~MemPoolT() {
   7.255 +		// Delete the blocks.
   7.256 +		for( int i=0; i<blockPtrs.Size(); ++i ) {
   7.257 +			delete blockPtrs[i];
   7.258 +		}
   7.259 +	}
   7.260 +
   7.261 +	virtual int ItemSize() const	{ return SIZE; }
   7.262 +	int CurrentAllocs() const		{ return currentAllocs; }
   7.263 +
   7.264 +	virtual void* Alloc() {
   7.265 +		if ( !root ) {
   7.266 +			// Need a new block.
   7.267 +			Block* block = new Block();
   7.268 +			blockPtrs.Push( block );
   7.269 +
   7.270 +			for( int i=0; i<COUNT-1; ++i ) {
   7.271 +				block->chunk[i].next = &block->chunk[i+1];
   7.272 +			}
   7.273 +			block->chunk[COUNT-1].next = 0;
   7.274 +			root = block->chunk;
   7.275 +		}
   7.276 +		void* result = root;
   7.277 +		root = root->next;
   7.278 +
   7.279 +		++currentAllocs;
   7.280 +		if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
   7.281 +		nAllocs++;
   7.282 +		return result;
   7.283 +	}
   7.284 +	virtual void Free( void* mem ) {
   7.285 +		if ( !mem ) return;
   7.286 +		--currentAllocs;
   7.287 +		Chunk* chunk = (Chunk*)mem;
   7.288 +		memset( chunk, 0xfe, sizeof(Chunk) );
   7.289 +		chunk->next = root;
   7.290 +		root = chunk;
   7.291 +	}
   7.292 +	void Trace( const char* name ) {
   7.293 +		printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
   7.294 +				 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
   7.295 +	}
   7.296 +
   7.297 +private:
   7.298 +	enum { COUNT = 1024/SIZE };
   7.299 +	union Chunk {
   7.300 +		Chunk* next;
   7.301 +		char mem[SIZE];
   7.302 +	};
   7.303 +	struct Block {
   7.304 +		Chunk chunk[COUNT];
   7.305 +	};
   7.306 +	DynArray< Block*, 10 > blockPtrs;
   7.307 +	Chunk* root;
   7.308 +
   7.309 +	int currentAllocs;
   7.310 +	int nAllocs;
   7.311 +	int maxAllocs;
   7.312 +};
   7.313 +
   7.314 +
   7.315 +
   7.316 +/**
   7.317 +	Implements the interface to the "Visitor pattern" (see the Accept() method.)
   7.318 +	If you call the Accept() method, it requires being passed a XMLVisitor
   7.319 +	class to handle callbacks. For nodes that contain other nodes (Document, Element)
   7.320 +	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
   7.321 +	are simply called with Visit().
   7.322 +
   7.323 +	If you return 'true' from a Visit method, recursive parsing will continue. If you return
   7.324 +	false, <b>no children of this node or its sibilings</b> will be visited.
   7.325 +
   7.326 +	All flavors of Visit methods have a default implementation that returns 'true' (continue 
   7.327 +	visiting). You need to only override methods that are interesting to you.
   7.328 +
   7.329 +	Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
   7.330 +
   7.331 +	You should never change the document from a callback.
   7.332 +
   7.333 +	@sa XMLNode::Accept()
   7.334 +*/
   7.335 +class XMLVisitor
   7.336 +{
   7.337 +public:
   7.338 +	virtual ~XMLVisitor() {}
   7.339 +
   7.340 +	/// Visit a document.
   7.341 +	virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{ return true; }
   7.342 +	/// Visit a document.
   7.343 +	virtual bool VisitExit( const XMLDocument& /*doc*/ )			{ return true; }
   7.344 +
   7.345 +	/// Visit an element.
   7.346 +	virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{ return true; }
   7.347 +	/// Visit an element.
   7.348 +	virtual bool VisitExit( const XMLElement& /*element*/ )			{ return true; }
   7.349 +
   7.350 +	/// Visit a declaration.
   7.351 +	virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{ return true; }
   7.352 +	/// Visit a text node.
   7.353 +	virtual bool Visit( const XMLText& /*text*/ )					{ return true; }
   7.354 +	/// Visit a comment node.
   7.355 +	virtual bool Visit( const XMLComment& /*comment*/ )				{ return true; }
   7.356 +	/// Visit an unknown node.
   7.357 +	virtual bool Visit( const XMLUnknown& /*unknown*/ )				{ return true; }
   7.358 +};
   7.359 +
   7.360 +
   7.361 +/*
   7.362 +	Utility functionality.
   7.363 +*/
   7.364 +class XMLUtil
   7.365 +{
   7.366 +public:
   7.367 +	// Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't 
   7.368 +	// correct, but simple, and usually works.
   7.369 +	static const char* SkipWhiteSpace( const char* p )	{ while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
   7.370 +	static char* SkipWhiteSpace( char* p )				{ while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
   7.371 +
   7.372 +	inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
   7.373 +		int n = 0;
   7.374 +		if ( p == q ) {
   7.375 +			return true;
   7.376 +		}
   7.377 +		while( *p && *q && *p == *q && n<nChar ) {
   7.378 +			++p; ++q; ++n;
   7.379 +		}
   7.380 +		if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
   7.381 +			return true;
   7.382 +		}
   7.383 +		return false;
   7.384 +	}
   7.385 +	inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
   7.386 +	inline static int IsAlphaNum( unsigned char anyByte )	{ return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
   7.387 +	inline static int IsAlpha( unsigned char anyByte )		{ return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
   7.388 +
   7.389 +	static const char* ReadBOM( const char* p, bool* hasBOM );
   7.390 +	// p is the starting location,
   7.391 +	// the UTF-8 value of the entity will be placed in value, and length filled in.
   7.392 +	static const char* GetCharacterRef( const char* p, char* value, int* length );
   7.393 +	static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
   7.394 +};
   7.395 +
   7.396 +
   7.397 +/** XMLNode is a base class for every object that is in the
   7.398 +	XML Document Object Model (DOM), except XMLAttributes.
   7.399 +	Nodes have siblings, a parent, and children which can
   7.400 +	be navigated. A node is always in a XMLDocument.
   7.401 +	The type of a XMLNode can be queried, and it can 
   7.402 +	be cast to its more defined type.
   7.403 +
   7.404 +	A XMLDocument allocates memory for all its Nodes.
   7.405 +	When the XMLDocument gets deleted, all its Nodes
   7.406 +	will also be deleted.
   7.407 +
   7.408 +	@verbatim
   7.409 +	A Document can contain:	Element	(container or leaf)
   7.410 +							Comment (leaf)
   7.411 +							Unknown (leaf)
   7.412 +							Declaration( leaf )
   7.413 +
   7.414 +	An Element can contain:	Element (container or leaf)
   7.415 +							Text	(leaf)
   7.416 +							Attributes (not on tree)
   7.417 +							Comment (leaf)
   7.418 +							Unknown (leaf)
   7.419 +
   7.420 +	@endverbatim
   7.421 +*/
   7.422 +class XMLNode
   7.423 +{
   7.424 +	friend class XMLDocument;
   7.425 +	friend class XMLElement;
   7.426 +public:
   7.427 +
   7.428 +	/// Get the XMLDocument that owns this XMLNode.
   7.429 +	const XMLDocument* GetDocument() const	{ return document; }
   7.430 +	/// Get the XMLDocument that owns this XMLNode.
   7.431 +	XMLDocument* GetDocument()				{ return document; }
   7.432 +
   7.433 +	virtual XMLElement*		ToElement()		{ return 0; }	///< Safely cast to an Element, or null.
   7.434 +	virtual XMLText*		ToText()		{ return 0; }	///< Safely cast to Text, or null.
   7.435 +	virtual XMLComment*		ToComment()		{ return 0; }	///< Safely cast to a Comment, or null.
   7.436 +	virtual XMLDocument*	ToDocument()	{ return 0; }	///< Safely cast to a Document, or null.
   7.437 +	virtual XMLDeclaration*	ToDeclaration()	{ return 0; }	///< Safely cast to a Declaration, or null.
   7.438 +	virtual XMLUnknown*		ToUnknown()		{ return 0; }	///< Safely cast to an Unknown, or null.
   7.439 +
   7.440 +	virtual const XMLElement*		ToElement() const		{ return 0; }
   7.441 +	virtual const XMLText*			ToText() const			{ return 0; }
   7.442 +	virtual const XMLComment*		ToComment() const		{ return 0; }
   7.443 +	virtual const XMLDocument*		ToDocument() const		{ return 0; }
   7.444 +	virtual const XMLDeclaration*	ToDeclaration() const	{ return 0; }
   7.445 +	virtual const XMLUnknown*		ToUnknown() const		{ return 0; }
   7.446 +
   7.447 +	/** The meaning of 'value' changes for the specific type.
   7.448 +		@verbatim
   7.449 +		Document:	empty
   7.450 +		Element:	name of the element
   7.451 +		Comment:	the comment text
   7.452 +		Unknown:	the tag contents
   7.453 +		Text:		the text string
   7.454 +		@endverbatim
   7.455 +	*/
   7.456 +	const char* Value() const			{ return value.GetStr(); }
   7.457 +	/** Set the Value of an XML node.
   7.458 +		@sa Value()
   7.459 +	*/
   7.460 +	void SetValue( const char* val, bool staticMem=false );
   7.461 +
   7.462 +	/// Get the parent of this node on the DOM.
   7.463 +	const XMLNode*	Parent() const			{ return parent; }
   7.464 +	XMLNode* Parent()						{ return parent; }
   7.465 +
   7.466 +	/// Returns true if this node has no children.
   7.467 +	bool NoChildren() const					{ return !firstChild; }
   7.468 +
   7.469 +	/// Get the first child node, or null if none exists.
   7.470 +	const XMLNode*  FirstChild() const		{ return firstChild; }
   7.471 +	XMLNode*		FirstChild()			{ return firstChild; }
   7.472 +	/** Get the first child element, or optionally the first child
   7.473 +	    element with the specified name.
   7.474 +	*/
   7.475 +	const XMLElement* FirstChildElement( const char* value=0 ) const;
   7.476 +	XMLElement* FirstChildElement( const char* _value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
   7.477 +
   7.478 +	/// Get the last child node, or null if none exists.
   7.479 +	const XMLNode*	LastChild() const						{ return lastChild; }
   7.480 +	XMLNode*		LastChild()								{ return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
   7.481 +
   7.482 +	/** Get the last child element or optionally the last child
   7.483 +	    element with the specified name.
   7.484 +	*/
   7.485 +	const XMLElement* LastChildElement( const char* value=0 ) const;
   7.486 +	XMLElement* LastChildElement( const char* _value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
   7.487 +	
   7.488 +	/// Get the previous (left) sibling node of this node.
   7.489 +	const XMLNode*	PreviousSibling() const					{ return prev; }
   7.490 +	XMLNode*	PreviousSibling()							{ return prev; }
   7.491 +
   7.492 +	/// Get the previous (left) sibling element of this node, with an opitionally supplied name.
   7.493 +	const XMLElement*	PreviousSiblingElement( const char* value=0 ) const ;
   7.494 +	XMLElement*	PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
   7.495 +	
   7.496 +	/// Get the next (right) sibling node of this node.
   7.497 +	const XMLNode*	NextSibling() const						{ return next; }
   7.498 +	XMLNode*	NextSibling()								{ return next; }
   7.499 +		
   7.500 +	/// Get the next (right) sibling element of this node, with an opitionally supplied name.
   7.501 +	const XMLElement*	NextSiblingElement( const char* value=0 ) const;
   7.502 + 	XMLElement*	NextSiblingElement( const char* _value=0 )	{ return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
   7.503 +
   7.504 +	/**
   7.505 +		Add a child node as the last (right) child.
   7.506 +	*/
   7.507 +	XMLNode* InsertEndChild( XMLNode* addThis );
   7.508 +
   7.509 +	XMLNode* LinkEndChild( XMLNode* addThis )	{ return InsertEndChild( addThis ); }
   7.510 +	/**
   7.511 +		Add a child node as the first (left) child.
   7.512 +	*/
   7.513 +	XMLNode* InsertFirstChild( XMLNode* addThis );
   7.514 +	/**
   7.515 +		Add a node after the specified child node.
   7.516 +	*/
   7.517 +	XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
   7.518 +	
   7.519 +	/**
   7.520 +		Delete all the children of this node.
   7.521 +	*/
   7.522 +	void DeleteChildren();
   7.523 +
   7.524 +	/**
   7.525 +		Delete a child of this node.
   7.526 +	*/
   7.527 +	void DeleteChild( XMLNode* node );
   7.528 +
   7.529 +	/**
   7.530 +		Make a copy of this node, but not its children.
   7.531 +		You may pass in a Document pointer that will be
   7.532 +		the owner of the new Node. If the 'document' is 
   7.533 +		null, then the node returned will be allocated
   7.534 +		from the current Document. (this->GetDocument())
   7.535 +
   7.536 +		Note: if called on a XMLDocument, this will return null.
   7.537 +	*/
   7.538 +	virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
   7.539 +
   7.540 +	/**
   7.541 +		Test if 2 nodes are the same, but don't test children.
   7.542 +		The 2 nodes do not need to be in the same Document.
   7.543 +
   7.544 +		Note: if called on a XMLDocument, this will return false.
   7.545 +	*/
   7.546 +	virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
   7.547 +
   7.548 +	/** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the 
   7.549 +		XML tree will be conditionally visited and the host will be called back
   7.550 +		via the TiXmlVisitor interface.
   7.551 +
   7.552 +		This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
   7.553 +		the XML for the callbacks, so the performance of TinyXML is unchanged by using this
   7.554 +		interface versus any other.)
   7.555 +
   7.556 +		The interface has been based on ideas from:
   7.557 +
   7.558 +		- http://www.saxproject.org/
   7.559 +		- http://c2.com/cgi/wiki?HierarchicalVisitorPattern 
   7.560 +
   7.561 +		Which are both good references for "visiting".
   7.562 +
   7.563 +		An example of using Accept():
   7.564 +		@verbatim
   7.565 +		TiXmlPrinter printer;
   7.566 +		tinyxmlDoc.Accept( &printer );
   7.567 +		const char* xmlcstr = printer.CStr();
   7.568 +		@endverbatim
   7.569 +	*/
   7.570 +	virtual bool Accept( XMLVisitor* visitor ) const = 0;
   7.571 +
   7.572 +	// internal
   7.573 +	virtual char* ParseDeep( char*, StrPair* );
   7.574 +
   7.575 +protected:
   7.576 +	XMLNode( XMLDocument* );
   7.577 +	virtual ~XMLNode();
   7.578 +	XMLNode( const XMLNode& );	// not supported
   7.579 +	void operator=( const XMLNode& );	// not supported
   7.580 +	
   7.581 +	XMLDocument*	document;
   7.582 +	XMLNode*		parent;
   7.583 +	mutable StrPair	value;
   7.584 +
   7.585 +	XMLNode*		firstChild;
   7.586 +	XMLNode*		lastChild;
   7.587 +
   7.588 +	XMLNode*		prev;
   7.589 +	XMLNode*		next;
   7.590 +
   7.591 +private:
   7.592 +	MemPool*		memPool;
   7.593 +	void Unlink( XMLNode* child );
   7.594 +};
   7.595 +
   7.596 +
   7.597 +/** XML text.
   7.598 +
   7.599 +	Note that a text node can have child element nodes, for example:
   7.600 +	@verbatim
   7.601 +	<root>This is <b>bold</b></root>
   7.602 +	@endverbatim
   7.603 +
   7.604 +	A text node can have 2 ways to output the next. "normal" output 
   7.605 +	and CDATA. It will default to the mode it was parsed from the XML file and
   7.606 +	you generally want to leave it alone, but you can change the output mode with 
   7.607 +	SetCDATA() and query it with CDATA().
   7.608 +*/
   7.609 +class XMLText : public XMLNode
   7.610 +{
   7.611 +	friend class XMLBase;
   7.612 +	friend class XMLDocument;
   7.613 +public:
   7.614 +	virtual bool Accept( XMLVisitor* visitor ) const;
   7.615 +
   7.616 +	virtual XMLText*	ToText()			{ return this; }
   7.617 +	virtual const XMLText*	ToText() const	{ return this; }
   7.618 +
   7.619 +	/// Declare whether this should be CDATA or standard text.
   7.620 +	void SetCData( bool _isCData )			{ this->isCData = _isCData; }
   7.621 +	/// Returns true if this is a CDATA text element.
   7.622 +	bool CData() const						{ return isCData; }
   7.623 +
   7.624 +	char* ParseDeep( char*, StrPair* endTag );
   7.625 +	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   7.626 +	virtual bool ShallowEqual( const XMLNode* compare ) const;
   7.627 +
   7.628 +
   7.629 +protected:
   7.630 +	XMLText( XMLDocument* doc )	: XMLNode( doc ), isCData( false )	{}
   7.631 +	virtual ~XMLText()												{}
   7.632 +	XMLText( const XMLText& );	// not supported
   7.633 +	void operator=( const XMLText& );	// not supported
   7.634 +
   7.635 +private:
   7.636 +	bool isCData;
   7.637 +};
   7.638 +
   7.639 +
   7.640 +/** An XML Comment. */
   7.641 +class XMLComment : public XMLNode
   7.642 +{
   7.643 +	friend class XMLDocument;
   7.644 +public:
   7.645 +	virtual XMLComment*	ToComment()					{ return this; }
   7.646 +	virtual const XMLComment* ToComment() const		{ return this; }
   7.647 +
   7.648 +	virtual bool Accept( XMLVisitor* visitor ) const;
   7.649 +
   7.650 +	char* ParseDeep( char*, StrPair* endTag );
   7.651 +	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   7.652 +	virtual bool ShallowEqual( const XMLNode* compare ) const;
   7.653 +
   7.654 +protected:
   7.655 +	XMLComment( XMLDocument* doc );
   7.656 +	virtual ~XMLComment();
   7.657 +	XMLComment( const XMLComment& );	// not supported
   7.658 +	void operator=( const XMLComment& );	// not supported
   7.659 +
   7.660 +private:
   7.661 +};
   7.662 +
   7.663 +
   7.664 +/** In correct XML the declaration is the first entry in the file.
   7.665 +	@verbatim
   7.666 +		<?xml version="1.0" standalone="yes"?>
   7.667 +	@endverbatim
   7.668 +
   7.669 +	TinyXML2 will happily read or write files without a declaration,
   7.670 +	however.
   7.671 +
   7.672 +	The text of the declaration isn't interpreted. It is parsed
   7.673 +	and written as a string.
   7.674 +*/
   7.675 +class XMLDeclaration : public XMLNode
   7.676 +{
   7.677 +	friend class XMLDocument;
   7.678 +public:
   7.679 +	virtual XMLDeclaration*	ToDeclaration()					{ return this; }
   7.680 +	virtual const XMLDeclaration* ToDeclaration() const		{ return this; }
   7.681 +
   7.682 +	virtual bool Accept( XMLVisitor* visitor ) const;
   7.683 +
   7.684 +	char* ParseDeep( char*, StrPair* endTag );
   7.685 +	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   7.686 +	virtual bool ShallowEqual( const XMLNode* compare ) const;
   7.687 +
   7.688 +protected:
   7.689 +	XMLDeclaration( XMLDocument* doc );
   7.690 +	virtual ~XMLDeclaration();
   7.691 +	XMLDeclaration( const XMLDeclaration& );	// not supported
   7.692 +	void operator=( const XMLDeclaration& );	// not supported
   7.693 +};
   7.694 +
   7.695 +
   7.696 +/** Any tag that tinyXml doesn't recognize is saved as an
   7.697 +	unknown. It is a tag of text, but should not be modified.
   7.698 +	It will be written back to the XML, unchanged, when the file
   7.699 +	is saved.
   7.700 +
   7.701 +	DTD tags get thrown into TiXmlUnknowns.
   7.702 +*/
   7.703 +class XMLUnknown : public XMLNode
   7.704 +{
   7.705 +	friend class XMLDocument;
   7.706 +public:
   7.707 +	virtual XMLUnknown*	ToUnknown()					{ return this; }
   7.708 +	virtual const XMLUnknown* ToUnknown() const		{ return this; }
   7.709 +
   7.710 +	virtual bool Accept( XMLVisitor* visitor ) const;
   7.711 +
   7.712 +	char* ParseDeep( char*, StrPair* endTag );
   7.713 +	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   7.714 +	virtual bool ShallowEqual( const XMLNode* compare ) const;
   7.715 +
   7.716 +protected:
   7.717 +	XMLUnknown( XMLDocument* doc );
   7.718 +	virtual ~XMLUnknown();
   7.719 +	XMLUnknown( const XMLUnknown& );	// not supported
   7.720 +	void operator=( const XMLUnknown& );	// not supported
   7.721 +};
   7.722 +
   7.723 +
   7.724 +enum {
   7.725 +	XML_NO_ERROR = 0,
   7.726 +	XML_SUCCESS = 0,
   7.727 +
   7.728 +	XML_NO_ATTRIBUTE,
   7.729 +	XML_WRONG_ATTRIBUTE_TYPE,
   7.730 +
   7.731 +	XML_ERROR_FILE_NOT_FOUND,
   7.732 +	XML_ERROR_FILE_COULD_NOT_BE_OPENED,
   7.733 +	XML_ERROR_ELEMENT_MISMATCH,
   7.734 +	XML_ERROR_PARSING_ELEMENT,
   7.735 +	XML_ERROR_PARSING_ATTRIBUTE,
   7.736 +	XML_ERROR_IDENTIFYING_TAG,
   7.737 +	XML_ERROR_PARSING_TEXT,
   7.738 +	XML_ERROR_PARSING_CDATA,
   7.739 +	XML_ERROR_PARSING_COMMENT,
   7.740 +	XML_ERROR_PARSING_DECLARATION,
   7.741 +	XML_ERROR_PARSING_UNKNOWN,
   7.742 +	XML_ERROR_EMPTY_DOCUMENT,
   7.743 +	XML_ERROR_MISMATCHED_ELEMENT,
   7.744 +	XML_ERROR_PARSING
   7.745 +};
   7.746 +
   7.747 +
   7.748 +/** An attribute is a name-value pair. Elements have an arbitrary
   7.749 +	number of attributes, each with a unique name.
   7.750 +
   7.751 +	@note The attributes are not XMLNodes. You may only query the
   7.752 +	Next() attribute in a list.
   7.753 +*/
   7.754 +class XMLAttribute
   7.755 +{
   7.756 +	friend class XMLElement;
   7.757 +public:
   7.758 +	const char* Name() const { return name.GetStr(); }			///< The name of the attribute.
   7.759 +	const char* Value() const { return value.GetStr(); }		///< The value of the attribute.
   7.760 +	const XMLAttribute* Next() const { return next; }			///< The next attribute in the list.
   7.761 +
   7.762 +	/** IntAttribute interprets the attribute as an integer, and returns the value.
   7.763 +	    If the value isn't an integer, 0 will be returned. There is no error checking;
   7.764 +		use QueryIntAttribute() if you need error checking.
   7.765 +	*/
   7.766 +	int		 IntValue() const				{ int i=0;		QueryIntValue( &i );		return i; }
   7.767 +	/// Query as an unsigned integer. See IntAttribute()
   7.768 +	unsigned UnsignedValue() const			{ unsigned i=0; QueryUnsignedValue( &i );	return i; }
   7.769 +	/// Query as a boolean. See IntAttribute()
   7.770 +	bool	 BoolValue() const				{ bool b=false; QueryBoolValue( &b );		return b; }
   7.771 +	/// Query as a double. See IntAttribute()
   7.772 +	double 	 DoubleValue() const			{ double d=0;	QueryDoubleValue( &d );		return d; }
   7.773 +	/// Query as a float. See IntAttribute()
   7.774 +	float	 FloatValue() const				{ float f=0;	QueryFloatValue( &f );		return f; }
   7.775 +
   7.776 +	/** QueryIntAttribute interprets the attribute as an integer, and returns the value
   7.777 +		in the provided paremeter. The function will return XML_NO_ERROR on success,
   7.778 +		and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
   7.779 +	*/
   7.780 +	int QueryIntValue( int* value ) const;
   7.781 +	/// See QueryIntAttribute
   7.782 +	int QueryUnsignedValue( unsigned int* value ) const;
   7.783 +	/// See QueryIntAttribute
   7.784 +	int QueryBoolValue( bool* value ) const;
   7.785 +	/// See QueryIntAttribute
   7.786 +	int QueryDoubleValue( double* value ) const;
   7.787 +	/// See QueryIntAttribute
   7.788 +	int QueryFloatValue( float* value ) const;
   7.789 +
   7.790 +	/// Set the attribute to a string value.
   7.791 +	void SetAttribute( const char* value );
   7.792 +	/// Set the attribute to value.
   7.793 +	void SetAttribute( int value );
   7.794 +	/// Set the attribute to value.
   7.795 +	void SetAttribute( unsigned value );
   7.796 +	/// Set the attribute to value.
   7.797 +	void SetAttribute( bool value );
   7.798 +	/// Set the attribute to value.
   7.799 +	void SetAttribute( double value );
   7.800 +	/// Set the attribute to value.
   7.801 +	void SetAttribute( float value );
   7.802 +
   7.803 +private:
   7.804 +	enum { BUF_SIZE = 200 };
   7.805 +
   7.806 +	XMLAttribute() : next( 0 ) {}
   7.807 +	virtual ~XMLAttribute()	{}
   7.808 +	XMLAttribute( const XMLAttribute& );	// not supported
   7.809 +	void operator=( const XMLAttribute& );	// not supported
   7.810 +	void SetName( const char* name );
   7.811 +
   7.812 +	char* ParseDeep( char* p, bool processEntities );
   7.813 +
   7.814 +	mutable StrPair name;
   7.815 +	mutable StrPair value;
   7.816 +	XMLAttribute* next;
   7.817 +	MemPool* memPool;
   7.818 +};
   7.819 +
   7.820 +
   7.821 +/** The element is a container class. It has a value, the element name,
   7.822 +	and can contain other elements, text, comments, and unknowns.
   7.823 +	Elements also contain an arbitrary number of attributes.
   7.824 +*/
   7.825 +class XMLElement : public XMLNode
   7.826 +{
   7.827 +	friend class XMLBase;
   7.828 +	friend class XMLDocument;
   7.829 +public:
   7.830 +	/// Get the name of an element (which is the Value() of the node.)
   7.831 +	const char* Name() const		{ return Value(); }
   7.832 +	/// Set the name of the element.
   7.833 +	void SetName( const char* str, bool staticMem=false )	{ SetValue( str, staticMem ); }
   7.834 +
   7.835 +	virtual XMLElement* ToElement()				{ return this; }
   7.836 +	virtual const XMLElement* ToElement() const { return this; }
   7.837 +	virtual bool Accept( XMLVisitor* visitor ) const;
   7.838 +
   7.839 +	/** Given an attribute name, Attribute() returns the value
   7.840 +		for the attribute of that name, or null if none 
   7.841 +		exists. For example:
   7.842 +
   7.843 +		@verbatim
   7.844 +		const char* value = ele->Attribute( "foo" );
   7.845 +		@endverbatim
   7.846 +
   7.847 +		The 'value' parameter is normally null. However, if specified, 
   7.848 +		the attribute will only be returned if the 'name' and 'value' 
   7.849 +		match. This allow you to write code:
   7.850 +
   7.851 +		@verbatim
   7.852 +		if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
   7.853 +		@endverbatim
   7.854 +
   7.855 +		rather than:
   7.856 +		@verbatim
   7.857 +		if ( ele->Attribute( "foo" ) ) {
   7.858 +			if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
   7.859 +		}
   7.860 +		@endverbatim
   7.861 +	*/
   7.862 +	const char* Attribute( const char* name, const char* value=0 ) const;
   7.863 +
   7.864 +	/** Given an attribute name, IntAttribute() returns the value
   7.865 +		of the attribute interpreted as an integer. 0 will be
   7.866 +		returned if there is an error. For a method with error 
   7.867 +		checking, see QueryIntAttribute()
   7.868 +	*/
   7.869 +	int		 IntAttribute( const char* name ) const		{ int i=0;		QueryIntAttribute( name, &i );		return i; }
   7.870 +	/// See IntAttribute()
   7.871 +	unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
   7.872 +	/// See IntAttribute()
   7.873 +	bool	 BoolAttribute( const char* name ) const	{ bool b=false; QueryBoolAttribute( name, &b );		return b; }
   7.874 +	/// See IntAttribute()
   7.875 +	double 	 DoubleAttribute( const char* name ) const	{ double d=0;	QueryDoubleAttribute( name, &d );	return d; }
   7.876 +	/// See IntAttribute()
   7.877 +	float	 FloatAttribute( const char* name ) const	{ float f=0;	QueryFloatAttribute( name, &f );	return f; }
   7.878 +
   7.879 +	/** Given an attribute name, QueryIntAttribute() returns 
   7.880 +		XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
   7.881 +		can't be performed, or XML_NO_ATTRIBUTE if the attribute
   7.882 +		doesn't exist. If successful, the result of the conversion
   7.883 +		will be written to 'value'. If not successful, nothing will
   7.884 +		be written to 'value'. This allows you to provide default
   7.885 +		value:
   7.886 +
   7.887 +		@verbatim
   7.888 +		int value = 10;
   7.889 +		QueryIntAttribute( "foo", &value );		// if "foo" isn't found, value will still be 10
   7.890 +		@endverbatim
   7.891 +	*/
   7.892 +	int QueryIntAttribute( const char* name, int* _value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); } 
   7.893 +	/// See QueryIntAttribute()
   7.894 +	int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const	{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
   7.895 +	/// See QueryIntAttribute()
   7.896 +	int QueryBoolAttribute( const char* name, bool* _value ) const				{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
   7.897 +	/// See QueryIntAttribute()
   7.898 +	int QueryDoubleAttribute( const char* name, double* _value ) const			{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
   7.899 +	/// See QueryIntAttribute()
   7.900 +	int QueryFloatAttribute( const char* name, float* _value ) const			{ const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
   7.901 +
   7.902 +	/// Sets the named attribute to value.
   7.903 +	void SetAttribute( const char* name, const char* _value )	{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
   7.904 +	/// Sets the named attribute to value.
   7.905 +	void SetAttribute( const char* name, int _value )			{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
   7.906 +	/// Sets the named attribute to value.
   7.907 +	void SetAttribute( const char* name, unsigned _value )		{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
   7.908 +	/// Sets the named attribute to value.
   7.909 +	void SetAttribute( const char* name, bool _value )			{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
   7.910 +	/// Sets the named attribute to value.
   7.911 +	void SetAttribute( const char* name, double _value )		{ XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
   7.912 +
   7.913 +	/**
   7.914 +		Delete an attribute.
   7.915 +	*/
   7.916 +	void DeleteAttribute( const char* name );
   7.917 +
   7.918 +	/// Return the first attribute in the list.
   7.919 +	const XMLAttribute* FirstAttribute() const { return rootAttribute; }
   7.920 +	/// Query a specific attribute in the list.
   7.921 +	const XMLAttribute* FindAttribute( const char* name ) const;
   7.922 +
   7.923 +	/** Convenience function for easy access to the text inside an element. Although easy
   7.924 +		and concise, GetText() is limited compared to getting the TiXmlText child
   7.925 +		and accessing it directly.
   7.926 +	
   7.927 +		If the first child of 'this' is a TiXmlText, the GetText()
   7.928 +		returns the character string of the Text node, else null is returned.
   7.929 +
   7.930 +		This is a convenient method for getting the text of simple contained text:
   7.931 +		@verbatim
   7.932 +		<foo>This is text</foo>
   7.933 +		const char* str = fooElement->GetText();
   7.934 +		@endverbatim
   7.935 +
   7.936 +		'str' will be a pointer to "This is text". 
   7.937 +		
   7.938 +		Note that this function can be misleading. If the element foo was created from
   7.939 +		this XML:
   7.940 +		@verbatim
   7.941 +		<foo><b>This is text</b></foo> 
   7.942 +		@endverbatim
   7.943 +
   7.944 +		then the value of str would be null. The first child node isn't a text node, it is
   7.945 +		another element. From this XML:
   7.946 +		@verbatim
   7.947 +		<foo>This is <b>text</b></foo> 
   7.948 +		@endverbatim
   7.949 +		GetText() will return "This is ".
   7.950 +	*/
   7.951 +	const char* GetText() const;
   7.952 +
   7.953 +	// internal:
   7.954 +	enum {
   7.955 +		OPEN,		// <foo>
   7.956 +		CLOSED,		// <foo/>
   7.957 +		CLOSING		// </foo>
   7.958 +	};
   7.959 +	int ClosingType() const { return closingType; }
   7.960 +	char* ParseDeep( char* p, StrPair* endTag );
   7.961 +	virtual XMLNode* ShallowClone( XMLDocument* document ) const;
   7.962 +	virtual bool ShallowEqual( const XMLNode* compare ) const;
   7.963 +
   7.964 +private:
   7.965 +	XMLElement( XMLDocument* doc );
   7.966 +	virtual ~XMLElement();
   7.967 +	XMLElement( const XMLElement& );	// not supported
   7.968 +	void operator=( const XMLElement& );	// not supported
   7.969 +
   7.970 +	XMLAttribute* FindAttribute( const char* name );
   7.971 +	XMLAttribute* FindOrCreateAttribute( const char* name );
   7.972 +	//void LinkAttribute( XMLAttribute* attrib );
   7.973 +	char* ParseAttributes( char* p );
   7.974 +
   7.975 +	int closingType;
   7.976 +	// The attribute list is ordered; there is no 'lastAttribute'
   7.977 +	// because the list needs to be scanned for dupes before adding
   7.978 +	// a new attribute.
   7.979 +	XMLAttribute* rootAttribute;
   7.980 +};
   7.981 +
   7.982 +
   7.983 +/** A Document binds together all the functionality. 
   7.984 +	It can be saved, loaded, and printed to the screen.
   7.985 +	All Nodes are connected and allocated to a Document.
   7.986 +	If the Document is deleted, all its Nodes are also deleted.
   7.987 +*/
   7.988 +class XMLDocument : public XMLNode
   7.989 +{
   7.990 +	friend class XMLElement;
   7.991 +public:
   7.992 +	/// constructor
   7.993 +	XMLDocument( bool processEntities = true ); 
   7.994 +	~XMLDocument();
   7.995 +
   7.996 +	virtual XMLDocument* ToDocument()				{ return this; }
   7.997 +	virtual const XMLDocument* ToDocument() const	{ return this; }
   7.998 +
   7.999 +	/**
  7.1000 +		Parse an XML file from a character string.
  7.1001 +		Returns XML_NO_ERROR (0) on success, or
  7.1002 +		an errorID.
  7.1003 +	*/
  7.1004 +	int Parse( const char* xml );
  7.1005 +	
  7.1006 +	/**
  7.1007 +		Load an XML file from disk.
  7.1008 +		Returns XML_NO_ERROR (0) on success, or
  7.1009 +		an errorID.
  7.1010 +	*/	
  7.1011 +	int LoadFile( const char* filename );
  7.1012 +	
  7.1013 +	/**
  7.1014 +		Load an XML file from disk. You are responsible
  7.1015 +		for providing and closing the FILE*.
  7.1016 +
  7.1017 +		Returns XML_NO_ERROR (0) on success, or
  7.1018 +		an errorID.
  7.1019 +	*/	
  7.1020 +	int LoadFile( FILE* );
  7.1021 +	
  7.1022 +	/**
  7.1023 +		Save the XML file to disk.
  7.1024 +		Returns XML_NO_ERROR (0) on success, or
  7.1025 +		an errorID.
  7.1026 +	*/
  7.1027 +	int SaveFile( const char* filename );
  7.1028 +
  7.1029 +	/**
  7.1030 +		Save the XML file to disk. You are responsible
  7.1031 +		for providing and closing the FILE*.
  7.1032 +
  7.1033 +		Returns XML_NO_ERROR (0) on success, or
  7.1034 +		an errorID.
  7.1035 +	*/
  7.1036 +	int SaveFile( FILE* );
  7.1037 +
  7.1038 +	bool ProcessEntities() const						{ return processEntities; }
  7.1039 +
  7.1040 +	/**
  7.1041 +		Returns true if this document has a leading Byte Order Mark of UTF8.
  7.1042 +	*/
  7.1043 +	bool HasBOM() const { return writeBOM; }
  7.1044 +	/** Sets whether to write the BOM when writing the file.
  7.1045 +	*/
  7.1046 +	void SetBOM( bool useBOM ) { writeBOM = useBOM; }
  7.1047 +
  7.1048 +	/** Return the root element of DOM. Equivalent to FirstChildElement().
  7.1049 +	    To get the first node, use FirstChild().
  7.1050 +	*/
  7.1051 +	XMLElement* RootElement()				{ return FirstChildElement(); }
  7.1052 +	const XMLElement* RootElement() const	{ return FirstChildElement(); }
  7.1053 +
  7.1054 +	/** Print the Document. If the Printer is not provided, it will
  7.1055 +	    print to stdout. If you provide Printer, this can print to a file:
  7.1056 +		@verbatim
  7.1057 +		XMLPrinter printer( fp );
  7.1058 +		doc.Print( &printer );
  7.1059 +		@endverbatim
  7.1060 +
  7.1061 +		Or you can use a printer to print to memory:
  7.1062 +		@verbatim
  7.1063 +		XMLPrinter printer;
  7.1064 +		doc->Print( &printer );
  7.1065 +		// printer.CStr() has a const char* to the XML
  7.1066 +		@endverbatim
  7.1067 +	*/
  7.1068 +	void Print( XMLPrinter* streamer=0 );
  7.1069 +	virtual bool Accept( XMLVisitor* visitor ) const;
  7.1070 +
  7.1071 +	/**
  7.1072 +		Create a new Element associated with
  7.1073 +		this Document. The memory for the Element
  7.1074 +		is managed by the Document.
  7.1075 +	*/
  7.1076 +	XMLElement* NewElement( const char* name );
  7.1077 +	/**
  7.1078 +		Create a new Comment associated with
  7.1079 +		this Document. The memory for the Comment
  7.1080 +		is managed by the Document.
  7.1081 +	*/
  7.1082 +	XMLComment* NewComment( const char* comment );
  7.1083 +	/**
  7.1084 +		Create a new Text associated with
  7.1085 +		this Document. The memory for the Text
  7.1086 +		is managed by the Document.
  7.1087 +	*/
  7.1088 +	XMLText* NewText( const char* text );
  7.1089 +	/**
  7.1090 +		Create a new Declaration associated with
  7.1091 +		this Document. The memory for the object
  7.1092 +		is managed by the Document.
  7.1093 +
  7.1094 +		If the 'text' param is null, the standard
  7.1095 +		declaration is used.:
  7.1096 +		@verbatim
  7.1097 +			<?xml version="1.0" encoding="UTF-8"?>
  7.1098 +		@endverbatim
  7.1099 +	*/
  7.1100 +	XMLDeclaration* NewDeclaration( const char* text=0 );
  7.1101 +	/**
  7.1102 +		Create a new Unknown associated with
  7.1103 +		this Document. The memory for the object
  7.1104 +		is managed by the Document.
  7.1105 +	*/
  7.1106 +	XMLUnknown* NewUnknown( const char* text );
  7.1107 +
  7.1108 +	/**
  7.1109 +		Delete a node associated with this document.
  7.1110 +		It will be unlinked from the DOM.
  7.1111 +	*/
  7.1112 +	void DeleteNode( XMLNode* node )	{ node->parent->DeleteChild( node ); }
  7.1113 +
  7.1114 +	void SetError( int error, const char* str1, const char* str2 );
  7.1115 +	
  7.1116 +	/// Return true if there was an error parsing the document.
  7.1117 +	bool Error() const { return errorID != XML_NO_ERROR; }
  7.1118 +	/// Return the errorID.
  7.1119 +	int  ErrorID() const { return errorID; }
  7.1120 +	/// Return a possibly helpful diagnostic location or string.
  7.1121 +	const char* GetErrorStr1() const { return errorStr1; }
  7.1122 +	/// Return a possibly helpful secondary diagnostic location or string.
  7.1123 +	const char* GetErrorStr2() const { return errorStr2; }
  7.1124 +	/// If there is an error, print it to stdout.
  7.1125 +	void PrintError() const;
  7.1126 +
  7.1127 +	// internal
  7.1128 +	char* Identify( char* p, XMLNode** node );
  7.1129 +
  7.1130 +	virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const	{ return 0; }
  7.1131 +	virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const	{ return false; }
  7.1132 +
  7.1133 +private:
  7.1134 +	XMLDocument( const XMLDocument& );	// not supported
  7.1135 +	void operator=( const XMLDocument& );	// not supported
  7.1136 +	void InitDocument();
  7.1137 +
  7.1138 +	bool writeBOM;
  7.1139 +	bool processEntities;
  7.1140 +	int errorID;
  7.1141 +	const char* errorStr1;
  7.1142 +	const char* errorStr2;
  7.1143 +	char* charBuffer;
  7.1144 +
  7.1145 +	MemPoolT< sizeof(XMLElement) >	elementPool;
  7.1146 +	MemPoolT< sizeof(XMLAttribute) > attributePool;
  7.1147 +	MemPoolT< sizeof(XMLText) >		textPool;
  7.1148 +	MemPoolT< sizeof(XMLComment) >	commentPool;
  7.1149 +};
  7.1150 +
  7.1151 +
  7.1152 +/**
  7.1153 +	A XMLHandle is a class that wraps a node pointer with null checks; this is
  7.1154 +	an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
  7.1155 +	DOM structure. It is a separate utility class.
  7.1156 +
  7.1157 +	Take an example:
  7.1158 +	@verbatim
  7.1159 +	<Document>
  7.1160 +		<Element attributeA = "valueA">
  7.1161 +			<Child attributeB = "value1" />
  7.1162 +			<Child attributeB = "value2" />
  7.1163 +		</Element>
  7.1164 +	</Document>
  7.1165 +	@endverbatim
  7.1166 +
  7.1167 +	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 
  7.1168 +	easy to write a *lot* of code that looks like:
  7.1169 +
  7.1170 +	@verbatim
  7.1171 +	XMLElement* root = document.FirstChildElement( "Document" );
  7.1172 +	if ( root )
  7.1173 +	{
  7.1174 +		XMLElement* element = root->FirstChildElement( "Element" );
  7.1175 +		if ( element )
  7.1176 +		{
  7.1177 +			XMLElement* child = element->FirstChildElement( "Child" );
  7.1178 +			if ( child )
  7.1179 +			{
  7.1180 +				XMLElement* child2 = child->NextSiblingElement( "Child" );
  7.1181 +				if ( child2 )
  7.1182 +				{
  7.1183 +					// Finally do something useful.
  7.1184 +	@endverbatim
  7.1185 +
  7.1186 +	And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
  7.1187 +	of such code. A XMLHandle checks for null pointers so it is perfectly safe 
  7.1188 +	and correct to use:
  7.1189 +
  7.1190 +	@verbatim
  7.1191 +	XMLHandle docHandle( &document );
  7.1192 +	XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
  7.1193 +	if ( child2 )
  7.1194 +	{
  7.1195 +		// do something useful
  7.1196 +	@endverbatim
  7.1197 +
  7.1198 +	Which is MUCH more concise and useful.
  7.1199 +
  7.1200 +	It is also safe to copy handles - internally they are nothing more than node pointers.
  7.1201 +	@verbatim
  7.1202 +	XMLHandle handleCopy = handle;
  7.1203 +	@endverbatim
  7.1204 +
  7.1205 +	See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
  7.1206 +*/
  7.1207 +class XMLHandle
  7.1208 +{
  7.1209 +public:
  7.1210 +	/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
  7.1211 +	XMLHandle( XMLNode* _node )												{ node = _node; }
  7.1212 +	/// Create a handle from a node.
  7.1213 +	XMLHandle( XMLNode& _node )												{ node = &_node; }
  7.1214 +	/// Copy constructor
  7.1215 +	XMLHandle( const XMLHandle& ref )										{ node = ref.node; }
  7.1216 +	/// Assignment
  7.1217 +	XMLHandle operator=( const XMLHandle& ref )								{ node = ref.node; return *this; }
  7.1218 +
  7.1219 +	/// Get the first child of this handle.
  7.1220 +	XMLHandle FirstChild() 													{ return XMLHandle( node ? node->FirstChild() : 0 ); }
  7.1221 +	/// Get the first child element of this handle.
  7.1222 +	XMLHandle FirstChildElement( const char* value=0 )						{ return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
  7.1223 +	/// Get the last child of this handle.
  7.1224 +	XMLHandle LastChild()													{ return XMLHandle( node ? node->LastChild() : 0 ); }
  7.1225 +	/// Get the last child element of this handle.
  7.1226 +	XMLHandle LastChildElement( const char* _value=0 )						{ return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
  7.1227 +	/// Get the previous sibling of this handle.
  7.1228 +	XMLHandle PreviousSibling()												{ return XMLHandle( node ? node->PreviousSibling() : 0 ); }
  7.1229 +	/// Get the previous sibling element of this handle.
  7.1230 +	XMLHandle PreviousSiblingElement( const char* _value=0 )				{ return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
  7.1231 +	/// Get the next sibling of this handle.
  7.1232 +	XMLHandle NextSibling()													{ return XMLHandle( node ? node->NextSibling() : 0 ); }		
  7.1233 +	/// Get the next sibling element of this handle.
  7.1234 +	XMLHandle NextSiblingElement( const char* _value=0 )					{ return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
  7.1235 +
  7.1236 +	/// Safe cast to XMLNode. This can return null.
  7.1237 +	XMLNode* ToNode()							{ return node; } 
  7.1238 +	/// Safe cast to XMLElement. This can return null.
  7.1239 +	XMLElement* ToElement() 					{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
  7.1240 +	/// Safe cast to XMLText. This can return null.
  7.1241 +	XMLText* ToText() 							{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
  7.1242 +	/// Safe cast to XMLUnknown. This can return null.
  7.1243 +	XMLUnknown* ToUnknown() 					{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
  7.1244 +	/// Safe cast to XMLDeclaration. This can return null.
  7.1245 +	XMLDeclaration* ToDeclaration() 			{ return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
  7.1246 +
  7.1247 +private:
  7.1248 +	XMLNode* node;
  7.1249 +};
  7.1250 +
  7.1251 +
  7.1252 +/**
  7.1253 +	A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
  7.1254 +	same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
  7.1255 +*/
  7.1256 +class XMLConstHandle
  7.1257 +{
  7.1258 +public:
  7.1259 +	XMLConstHandle( const XMLNode* _node )											{ node = _node; }
  7.1260 +	XMLConstHandle( const XMLNode& _node )											{ node = &_node; }
  7.1261 +	XMLConstHandle( const XMLConstHandle& ref )										{ node = ref.node; }
  7.1262 +
  7.1263 +	XMLConstHandle operator=( const XMLConstHandle& ref )							{ node = ref.node; return *this; }
  7.1264 +
  7.1265 +	const XMLConstHandle FirstChild() const											{ return XMLConstHandle( node ? node->FirstChild() : 0 ); }
  7.1266 +	const XMLConstHandle FirstChildElement( const char* value=0 ) const				{ return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
  7.1267 +	const XMLConstHandle LastChild()	const										{ return XMLConstHandle( node ? node->LastChild() : 0 ); }
  7.1268 +	const XMLConstHandle LastChildElement( const char* _value=0 ) const				{ return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
  7.1269 +	const XMLConstHandle PreviousSibling() const									{ return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
  7.1270 +	const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const		{ return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
  7.1271 +	const XMLConstHandle NextSibling() const										{ return XMLConstHandle( node ? node->NextSibling() : 0 ); }
  7.1272 +	const XMLConstHandle NextSiblingElement( const char* _value=0 ) const			{ return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
  7.1273 +
  7.1274 +
  7.1275 +	const XMLNode* ToNode() const				{ return node; } 
  7.1276 +	const XMLElement* ToElement() const			{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
  7.1277 +	const XMLText* ToText() const				{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
  7.1278 +	const XMLUnknown* ToUnknown() const			{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
  7.1279 +	const XMLDeclaration* ToDeclaration() const	{ return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
  7.1280 +
  7.1281 +private:
  7.1282 +	const XMLNode* node;
  7.1283 +};
  7.1284 +
  7.1285 +
  7.1286 +/**
  7.1287 +	Printing functionality. The XMLPrinter gives you more
  7.1288 +	options than the XMLDocument::Print() method.
  7.1289 +
  7.1290 +	It can:
  7.1291 +	-# Print to memory.
  7.1292 +	-# Print to a file you provide.
  7.1293 +	-# Print XML without a XMLDocument.
  7.1294 +
  7.1295 +	Print to Memory
  7.1296 +
  7.1297 +	@verbatim
  7.1298 +	XMLPrinter printer;
  7.1299 +	doc->Print( &printer );
  7.1300 +	SomeFunction( printer.CStr() );
  7.1301 +	@endverbatim
  7.1302 +
  7.1303 +	Print to a File
  7.1304 +	
  7.1305 +	You provide the file pointer.
  7.1306 +	@verbatim
  7.1307 +	XMLPrinter printer( fp );
  7.1308 +	doc.Print( &printer );
  7.1309 +	@endverbatim
  7.1310 +
  7.1311 +	Print without a XMLDocument
  7.1312 +
  7.1313 +	When loading, an XML parser is very useful. However, sometimes
  7.1314 +	when saving, it just gets in the way. The code is often set up
  7.1315 +	for streaming, and constructing the DOM is just overhead.
  7.1316 +
  7.1317 +	The Printer supports the streaming case. The following code
  7.1318 +	prints out a trivially simple XML file without ever creating
  7.1319 +	an XML document.
  7.1320 +
  7.1321 +	@verbatim
  7.1322 +	XMLPrinter printer( fp );
  7.1323 +	printer.OpenElement( "foo" );
  7.1324 +	printer.PushAttribute( "foo", "bar" );
  7.1325 +	printer.CloseElement();
  7.1326 +	@endverbatim
  7.1327 +*/
  7.1328 +class XMLPrinter : public XMLVisitor
  7.1329 +{
  7.1330 +public:
  7.1331 +	/** Construct the printer. If the FILE* is specified,
  7.1332 +		this will print to the FILE. Else it will print
  7.1333 +		to memory, and the result is available in CStr()
  7.1334 +	*/
  7.1335 +	XMLPrinter( FILE* file=0 );
  7.1336 +	~XMLPrinter()	{}
  7.1337 +
  7.1338 +	/** If streaming, write the BOM and declaration. */
  7.1339 +	void PushHeader( bool writeBOM, bool writeDeclaration );
  7.1340 +	/** If streaming, start writing an element.
  7.1341 +	    The element must be closed with CloseElement()
  7.1342 +	*/
  7.1343 +	void OpenElement( const char* name );
  7.1344 +	/// If streaming, add an attribute to an open element.
  7.1345 +	void PushAttribute( const char* name, const char* value );
  7.1346 +	void PushAttribute( const char* name, int value );
  7.1347 +	void PushAttribute( const char* name, unsigned value );
  7.1348 +	void PushAttribute( const char* name, bool value );
  7.1349 +	void PushAttribute( const char* name, double value );
  7.1350 +	/// If streaming, close the Element.
  7.1351 +	void CloseElement();
  7.1352 +
  7.1353 +	/// Add a text node.
  7.1354 +	void PushText( const char* text, bool cdata=false );
  7.1355 +	/// Add a comment.
  7.1356 +	void PushComment( const char* comment );
  7.1357 +
  7.1358 +	void PushDeclaration( const char* value );
  7.1359 +	void PushUnknown( const char* value );
  7.1360 +
  7.1361 +	virtual bool VisitEnter( const XMLDocument& /*doc*/ );
  7.1362 +	virtual bool VisitExit( const XMLDocument& /*doc*/ )			{ return true; }
  7.1363 +
  7.1364 +	virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
  7.1365 +	virtual bool VisitExit( const XMLElement& element );
  7.1366 +
  7.1367 +	virtual bool Visit( const XMLText& text );
  7.1368 +	virtual bool Visit( const XMLComment& comment );
  7.1369 +	virtual bool Visit( const XMLDeclaration& declaration );
  7.1370 +	virtual bool Visit( const XMLUnknown& unknown );
  7.1371 +
  7.1372 +	/**
  7.1373 +		If in print to memory mode, return a pointer to
  7.1374 +		the XML file in memory.
  7.1375 +	*/
  7.1376 +	const char* CStr() const { return buffer.Mem(); }
  7.1377 +
  7.1378 +private:
  7.1379 +	void SealElement();
  7.1380 +	void PrintSpace( int depth );
  7.1381 +	void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
  7.1382 +	void Print( const char* format, ... );
  7.1383 +
  7.1384 +	bool elementJustOpened;
  7.1385 +	bool firstElement;
  7.1386 +	FILE* fp;
  7.1387 +	int depth;
  7.1388 +	int textDepth;
  7.1389 +	bool processEntities;
  7.1390 +
  7.1391 +	enum {
  7.1392 +		ENTITY_RANGE = 64,
  7.1393 +		BUF_SIZE = 200
  7.1394 +	};
  7.1395 +	bool entityFlag[ENTITY_RANGE];
  7.1396 +	bool restrictedEntityFlag[ENTITY_RANGE];
  7.1397 +
  7.1398 +	DynArray< const char*, 10 > stack;
  7.1399 +	DynArray< char, 20 > buffer, accumulator;
  7.1400 +};
  7.1401 +
  7.1402 +
  7.1403 +}	// tinyxml2
  7.1404 +
  7.1405 +
  7.1406 +#endif // TINYXML2_INCLUDED
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/game_part.cc	Mon May 21 19:07:40 2012 +0300
     8.3 @@ -0,0 +1,38 @@
     8.4 +#include "opengl.h"
     8.5 +#include "game_part.h"
     8.6 +#include "level.h"
     8.7 +
     8.8 +Game::~Game() {}
     8.9 +
    8.10 +void Game::draw() const
    8.11 +{
    8.12 +	glClear(GL_COLOR_BUFFER_BIT);
    8.13 +
    8.14 +	glMatrixMode(GL_MODELVIEW);
    8.15 +	glLoadIdentity();
    8.16 +	glRotatef(current_time / 100.0, 0, 0, 1);
    8.17 +	glScalef(0.5, 0.5, 1);
    8.18 +
    8.19 +	glBegin(GL_QUADS);
    8.20 +	glColor3f(1, 0, 0);
    8.21 +	glVertex2f(-1, -1);
    8.22 +	glColor3f(0, 1, 0);
    8.23 +	glVertex2f(1, -1);
    8.24 +	glColor3f(0, 0, 1);
    8.25 +	glVertex2f(1, 1);
    8.26 +	glColor3f(1, 0, 1);
    8.27 +	glVertex2f(-1, 1);
    8.28 +	glEnd();
    8.29 +}
    8.30 +
    8.31 +void Game::key(int key, bool pressed)
    8.32 +{
    8.33 +	switch(key) {
    8.34 +	case 27:
    8.35 +		cur_part = menu_part;
    8.36 +		break;
    8.37 +
    8.38 +	default:
    8.39 +		break;
    8.40 +	}
    8.41 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/game_part.h	Mon May 21 19:07:40 2012 +0300
     9.3 @@ -0,0 +1,17 @@
     9.4 +#ifndef GAME_PART_H_
     9.5 +#define GAME_PART_H_
     9.6 +
     9.7 +#include "part.h"
     9.8 +#include "level.h"
     9.9 +
    9.10 +class Game : public Part {
    9.11 +private:
    9.12 +	Level *level;
    9.13 +public:
    9.14 +	~Game();
    9.15 +
    9.16 +	void draw() const;
    9.17 +	void key(int key, bool pressed);
    9.18 +};
    9.19 +
    9.20 +#endif	// GAME_PART_H_
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/main.cc	Mon May 21 19:07:40 2012 +0300
    10.3 @@ -0,0 +1,133 @@
    10.4 +#include <stdio.h>
    10.5 +#include <stdlib.h>
    10.6 +#include <unistd.h>
    10.7 +#include "opengl.h"
    10.8 +#include "part.h"
    10.9 +#include "menu_part.h"
   10.10 +#include "game_part.h"
   10.11 +
   10.12 +static bool init();
   10.13 +static void cleanup();
   10.14 +static void disp();
   10.15 +static void idle();
   10.16 +static void reshape(int x, int y);
   10.17 +static void key_press(unsigned char key, int x, int y);
   10.18 +static void key_release(unsigned char key, int x, int y);
   10.19 +static void mouse(int bn, int state, int x, int y);
   10.20 +static void motion(int x, int y);
   10.21 +static void sball_motion(int x, int y, int z);
   10.22 +static void sball_rotate(int x, int y, int z);
   10.23 +static void sball_button(int bn, int state);
   10.24 +
   10.25 +int main(int argc, char **argv)
   10.26 +{
   10.27 +	glutInit(&argc, argv);
   10.28 +	glutInitWindowSize(1280, 800);
   10.29 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL);
   10.30 +	glutCreateWindow("Foo");
   10.31 +
   10.32 +	glutDisplayFunc(disp);
   10.33 +	glutIdleFunc(idle);
   10.34 +	glutReshapeFunc(reshape);
   10.35 +	glutKeyboardFunc(key_press);
   10.36 +	glutKeyboardUpFunc(key_release);
   10.37 +	glutMouseFunc(mouse);
   10.38 +	glutMotionFunc(motion);
   10.39 +	glutPassiveMotionFunc(motion);
   10.40 +	glutSpaceballMotionFunc(sball_motion);
   10.41 +	glutSpaceballRotateFunc(sball_rotate);
   10.42 +	glutSpaceballButtonFunc(sball_button);
   10.43 +
   10.44 +	if(!init()) {
   10.45 +		return 1;
   10.46 +	}
   10.47 +	atexit(cleanup);
   10.48 +
   10.49 +	glutMainLoop();
   10.50 +	return 0;
   10.51 +}
   10.52 +
   10.53 +
   10.54 +static bool init()
   10.55 +{
   10.56 +	glewInit();
   10.57 +
   10.58 +	menu_part = new MainMenu;
   10.59 +	game_part = new Game;
   10.60 +	cur_part = menu_part;
   10.61 +
   10.62 +	return true;
   10.63 +}
   10.64 +
   10.65 +static void cleanup()
   10.66 +{
   10.67 +	delete menu_part;
   10.68 +	delete game_part;
   10.69 +}
   10.70 +
   10.71 +static void disp()
   10.72 +{
   10.73 +	unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
   10.74 +	cur_part->update(msec);
   10.75 +	cur_part->draw();
   10.76 +
   10.77 +	glutSwapBuffers();
   10.78 +	usleep(1000);
   10.79 +}
   10.80 +
   10.81 +static void idle()
   10.82 +{
   10.83 +	glutPostRedisplay();
   10.84 +}
   10.85 +
   10.86 +static void reshape(int x, int y)
   10.87 +{
   10.88 +	glViewport(0, 0, x, y);
   10.89 +
   10.90 +	cur_part->reshape(x, y);
   10.91 +}
   10.92 +
   10.93 +static void key_press(unsigned char key, int x, int y)
   10.94 +{
   10.95 +	cur_part->key(key, true);
   10.96 +}
   10.97 +
   10.98 +static void key_release(unsigned char key, int x, int y)
   10.99 +{
  10.100 +	cur_part->key(key, false);
  10.101 +}
  10.102 +
  10.103 +static void mouse(int bn, int state, int x, int y)
  10.104 +{
  10.105 +	cur_part->mouse_button(bn - GLUT_LEFT_BUTTON, state == GLUT_DOWN);
  10.106 +}
  10.107 +
  10.108 +static void motion(int x, int y)
  10.109 +{
  10.110 +	cur_part->mouse_motion(x, y);
  10.111 +}
  10.112 +
  10.113 +static int sbmotion[6];
  10.114 +
  10.115 +static void sball_motion(int x, int y, int z)
  10.116 +{
  10.117 +	sbmotion[0] = x;
  10.118 +	sbmotion[1] = y;
  10.119 +	sbmotion[2] = z;
  10.120 +	cur_part->spaceball_motion(sbmotion[0], sbmotion[1], sbmotion[2],
  10.121 +			sbmotion[3], sbmotion[4], sbmotion[5]);
  10.122 +}
  10.123 +
  10.124 +static void sball_rotate(int x, int y, int z)
  10.125 +{
  10.126 +	sbmotion[3] = x;
  10.127 +	sbmotion[4] = y;
  10.128 +	sbmotion[5] = z;
  10.129 +	cur_part->spaceball_motion(sbmotion[0], sbmotion[1], sbmotion[2],
  10.130 +			sbmotion[3], sbmotion[4], sbmotion[5]);
  10.131 +}
  10.132 +
  10.133 +static void sball_button(int bn, int state)
  10.134 +{
  10.135 +	cur_part->spaceball_button(bn, state == GLUT_DOWN);
  10.136 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/menu_part.cc	Mon May 21 19:07:40 2012 +0300
    11.3 @@ -0,0 +1,48 @@
    11.4 +#include <stdlib.h>
    11.5 +#include <imtk.h>
    11.6 +#include "opengl.h"
    11.7 +#include "part.h"
    11.8 +#include "game_part.h"
    11.9 +#include "menu_part.h"
   11.10 +
   11.11 +static int width, height;
   11.12 +
   11.13 +
   11.14 +MainMenu::~MainMenu() {}
   11.15 +
   11.16 +void MainMenu::draw() const
   11.17 +{
   11.18 +	glClear(GL_COLOR_BUFFER_BIT);
   11.19 +
   11.20 +	imtk_begin();
   11.21 +
   11.22 +	imtk_layout_start(width / 2, height / 2);
   11.23 +	imtk_layout_dir(IMTK_VERTICAL);
   11.24 +	imtk_layout_spacing(10);
   11.25 +
   11.26 +	if(imtk_button(IMUID, "Play", IMTK_AUTO, IMTK_AUTO)) {
   11.27 +		cur_part = game_part;
   11.28 +	}
   11.29 +	if(imtk_button(IMUID, "Quit", IMTK_AUTO, IMTK_AUTO)) {
   11.30 +		exit(0);
   11.31 +	}
   11.32 +
   11.33 +	imtk_end();
   11.34 +}
   11.35 +
   11.36 +void MainMenu::reshape(int x, int y)
   11.37 +{
   11.38 +	imtk_set_viewport(x, y);
   11.39 +	width = x;
   11.40 +	height = y;
   11.41 +}
   11.42 +
   11.43 +void MainMenu::mouse_button(int bn, bool pressed)
   11.44 +{
   11.45 +	imtk_inp_mouse(bn, pressed ? 1 : 0);
   11.46 +}
   11.47 +
   11.48 +void MainMenu::mouse_motion(int x, int y)
   11.49 +{
   11.50 +	imtk_inp_motion(x, y);
   11.51 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/menu_part.h	Mon May 21 19:07:40 2012 +0300
    12.3 @@ -0,0 +1,16 @@
    12.4 +#ifndef MENU_PART_H_
    12.5 +#define MENU_PART_H_
    12.6 +
    12.7 +#include "part.h"
    12.8 +
    12.9 +class MainMenu : public Part {
   12.10 +	~MainMenu();
   12.11 +
   12.12 +	void draw() const;
   12.13 +
   12.14 +	void reshape(int x, int y);
   12.15 +	void mouse_button(int bn, bool pressed);
   12.16 +	void mouse_motion(int x, int y);
   12.17 +};
   12.18 +
   12.19 +#endif	// MENU_PART_H_
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/opengl.h	Mon May 21 19:07:40 2012 +0300
    13.3 @@ -0,0 +1,12 @@
    13.4 +#ifndef OPENGL_H_
    13.5 +#define OPENGL_H_
    13.6 +
    13.7 +#include <GL/glew.h>
    13.8 +
    13.9 +#ifdef __APPLE__
   13.10 +#include <GLUT/glut.h>
   13.11 +#else
   13.12 +#include <GL/glut.h>
   13.13 +#endif
   13.14 +
   13.15 +#endif	/* OPENGL_H_ */
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/part.cc	Mon May 21 19:07:40 2012 +0300
    14.3 @@ -0,0 +1,25 @@
    14.4 +#include "opengl.h"
    14.5 +#include "part.h"
    14.6 +
    14.7 +Part *cur_part, *game_part, *menu_part;
    14.8 +
    14.9 +Part::~Part()
   14.10 +{
   14.11 +	current_time = 0;
   14.12 +}
   14.13 +
   14.14 +void Part::update(unsigned long msec)
   14.15 +{
   14.16 +	current_time = msec;
   14.17 +}
   14.18 +
   14.19 +void Part::reshape(int x, int y)
   14.20 +{
   14.21 +	glViewport(0, 0, x, y);
   14.22 +}
   14.23 +
   14.24 +void Part::key(int key, bool pressed) {}
   14.25 +void Part::mouse_button(int bn, bool pressed) {}
   14.26 +void Part::mouse_motion(int x, int y) {}
   14.27 +void Part::spaceball_motion(int x, int y, int z, int rx, int ry, int rz) {}
   14.28 +void Part::spaceball_button(int bn, bool pressed) {}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/part.h	Mon May 21 19:07:40 2012 +0300
    15.3 @@ -0,0 +1,27 @@
    15.4 +#ifndef GAME_H_
    15.5 +#define GAME_H_
    15.6 +
    15.7 +class Part;
    15.8 +
    15.9 +extern Part *cur_part;
   15.10 +extern Part *game_part, *menu_part;
   15.11 +
   15.12 +class Part {
   15.13 +protected:
   15.14 +	unsigned long current_time;
   15.15 +
   15.16 +public:
   15.17 +	virtual ~Part();
   15.18 +
   15.19 +	virtual void update(unsigned long msec);
   15.20 +	virtual void draw() const = 0;
   15.21 +
   15.22 +	virtual void reshape(int x, int y);
   15.23 +	virtual void key(int key, bool pressed);
   15.24 +	virtual void mouse_button(int bn, bool pressed);
   15.25 +	virtual void mouse_motion(int x, int y);
   15.26 +	virtual void spaceball_motion(int x, int y, int z, int rx, int ry, int rz);
   15.27 +	virtual void spaceball_button(int bn, bool pressed);
   15.28 +};
   15.29 +
   15.30 +#endif	/* GAME_H_ */