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 + // 中 or 中 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_ */