#ifndef TINYXML2_INCLUDED #define TINYXML2_INCLUDED #include #include #include #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) #ifndef DEBUG #define DEBUG #endif #endif #if defined(DEBUG) #if defined(_MSC_VER) #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak() #elif defined (ANDROID_NDK) #include #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } #else #include #define TIXMLASSERT assert #endif #else #define TIXMLASSERT( x ) {} #endif namespace tinyxml2 { class XMLDocument; class XMLElement; class XMLAttribute; class XMLComment; class XMLNode; class XMLText; class XMLStreamer; /* // internal - move to separate namespace struct CharBuffer { size_t length; char mem[1]; static CharBuffer* Construct( const char* in ); static void Free( CharBuffer* ); }; */ class StrPair { public: enum { NEEDS_ENTITY_PROCESSING = 0x01, NEEDS_NEWLINE_NORMALIZATION = 0x02, TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, ATTRIBUTE_NAME = 0, ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, COMMENT = NEEDS_NEWLINE_NORMALIZATION, }; StrPair() : flags( 0 ), start( 0 ), end( 0 ) {} void Set( char* start, char* end, int flags ) { this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH; } const char* GetStr(); bool Empty() const { return start == end; } private: enum { NEEDS_FLUSH = 0x100 }; // After parsing, if *end != 0, it can be set to zero. int flags; char* start; char* end; }; class XMLBase { public: XMLBase() {} virtual ~XMLBase() {} protected: static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; } static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; } inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { int n = 0; if ( p == q ) { return true; } while( *p && *q && *p == *q && n class DynArray { public: DynArray< T, INIT >() { mem = pool; allocated = INIT; size = 0; } ~DynArray() { if ( mem != pool ) { delete mem; } } void Push( T t ) { EnsureCapacity( size+1 ); mem[size++] = t; } T* PushArr( int count ) { EnsureCapacity( size+count ); T* ret = &mem[size]; size += count; return ret; } T Pop() { return mem[--size]; } void PopArr( int count ) { TIXMLASSERT( size >= count ); size -= count; } int Size() const { return size; } const T* Mem() const { return mem; } T* Mem() { return mem; } private: void EnsureCapacity( int cap ) { if ( cap > allocated ) { int newAllocated = cap * 2; T* newMem = new T[newAllocated]; memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs if ( mem != pool ) delete [] mem; mem = newMem; allocated = newAllocated; } } T* mem; T pool[INIT]; int allocated; // objects allocated int size; // number objects in use }; class StringStack { public: StringStack(); virtual ~StringStack(); void Push( const char* str ); const char* Pop(); int NumPositive() const { return nPositive; } private: DynArray< char, 50 > mem; int nPositive; // number of strings with len > 0 }; class XMLStreamer { public: XMLStreamer( FILE* file ); ~XMLStreamer() {} void OpenElement( const char* name, bool textParent ); void PushAttribute( const char* name, const char* value ); void CloseElement(); void PushText( const char* text ); void PushComment( const char* comment ); private: void SealElement(); void PrintSpace( int depth ); void PrintString( const char* ); // prints out, after detecting entities. FILE* fp; int depth; bool elementJustOpened; enum { ENTITY_RANGE = 64 }; bool entityFlag[ENTITY_RANGE]; DynArray< const char*, 40 > stack; StringStack text; }; }; // tinyxml2 #endif // TINYXML2_INCLUDED