| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- #ifndef TINYXML2_INCLUDED
- #define TINYXML2_INCLUDED
- /*
- TODO
- - const and non-const versions of API
- - memory pool the class construction
- - attribute accessors
- - node navigation
- - handles
- - visit pattern - change streamer?
- - make constructors protected
- - hide copy constructor
- - hide = operator
- */
- #include <limits.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <memory.h>
- #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 <android/log.h>
- #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
- #else
- #include <assert.h>
- #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;
- 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; }
- void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
- private:
- enum {
- NEEDS_FLUSH = 0x100
- };
- // After parsing, if *end != 0, it can be set to zero.
- int flags;
- char* start;
- char* end;
- };
- template <class T, int INIT>
- 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;
- }
- bool Empty() const { return size == 0; }
- T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
- const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
- 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 StringPool
- {
- public:
- enum { INIT_SIZE=20 };
- StringPool() : size( 0 ) {
- const char** mem = pool.PushArr( INIT_SIZE );
- memset( (void*)mem, 0, sizeof(char)*INIT_SIZE );
- }
- ~StringPool() {}
- const char* Intern( const char* str );
- private:
- // FNV hash
- int Hash( const char* s ) {
- #define FNV_32_PRIME ((int)0x01000193)
- int hval = 0;
- while (*s) {
- hval *= FNV_32_PRIME;
- hval ^= (int)*s++;
- }
- return hval;
- }
- int size;
- DynArray< const char*, INIT_SIZE > pool; // the hash table
- StringStack store; // memory for the interned strings
- };
- */
- 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<nChar ) {
- ++p; ++q; ++n;
- }
- if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
- return true;
- }
- return false;
- }
- inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
- inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
- inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
- char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
- char* ParseName( char* in, StrPair* pair );
- char* Identify( XMLDocument* document, char* p, XMLNode** node );
- };
- class XMLNode : public XMLBase
- {
- friend class XMLDocument;
- friend class XMLElement;
- public:
- virtual ~XMLNode();
- XMLNode* InsertEndChild( XMLNode* addThis );
- virtual void Print( XMLStreamer* streamer );
- const char* Value() const { return value.GetStr(); }
- void SetValue( const char* val ) { value.SetInternedStr( val ); }
- virtual XMLElement* ToElement() { return 0; }
- virtual XMLText* ToText() { return 0; }
- virtual XMLComment* ToComment() { return 0; }
- XMLNode* FirstChild() { return firstChild; }
- XMLElement* FirstChildElement( const char* value=0 );
- // fixme: guarentee null terminator to avoid internal checks
- virtual char* ParseDeep( char* );
- void SetTextParent() { isTextParent = true; }
- bool IsTextParent() const { return isTextParent; }
- virtual bool IsClosingElement() const { return false; }
- protected:
- XMLNode( XMLDocument* );
- void ClearChildren();
- XMLDocument* document;
- XMLNode* parent;
- bool isTextParent;
- mutable StrPair value;
- XMLNode* firstChild;
- XMLNode* lastChild;
- XMLNode* prev;
- XMLNode* next;
- private:
- void Unlink( XMLNode* child );
- };
- class XMLText : public XMLNode
- {
- friend class XMLBase;
- friend class XMLDocument;
- public:
- virtual ~XMLText() {}
- virtual void Print( XMLStreamer* streamer );
- const char* Value() { return value.GetStr(); }
- void SetValue( const char* );
- virtual XMLText* ToText() { return this; }
- char* ParseDeep( char* );
- protected:
- XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
- private:
- };
- class XMLComment : public XMLNode
- {
- friend class XMLBase;
- friend class XMLDocument;
- public:
- virtual ~XMLComment();
- virtual void Print( XMLStreamer* );
- virtual XMLComment* ToComment() { return this; }
- const char* Value() { return value.GetStr(); }
- char* ParseDeep( char* );
- protected:
- XMLComment( XMLDocument* doc );
- private:
- };
- class XMLAttribute : public XMLBase
- {
- friend class XMLElement;
- public:
- XMLAttribute( XMLElement* element ) : next( 0 ) {}
- virtual ~XMLAttribute() {}
- virtual void Print( XMLStreamer* streamer );
- private:
- char* ParseDeep( char* p );
- StrPair name;
- StrPair value;
- XMLAttribute* next;
- };
- class XMLElement : public XMLNode
- {
- friend class XMLBase;
- friend class XMLDocument;
- public:
- virtual ~XMLElement();
- const char* Name() const { return Value(); }
- void SetName( const char* str ) { SetValue( str ); }
- virtual void Print( XMLStreamer* );
- virtual XMLElement* ToElement() { return this; }
- // internal:
- virtual bool IsClosingElement() const { return closing; }
- char* ParseDeep( char* p );
- protected:
- XMLElement( XMLDocument* doc );
- private:
- char* ParseAttributes( char* p, bool *closedElement );
- mutable StrPair name;
- bool closing;
- XMLAttribute* rootAttribute;
- XMLAttribute* lastAttribute;
- };
- class XMLDocument : public XMLNode
- {
- public:
- XMLDocument();
- ~XMLDocument();
- int Parse( const char* );
- int Load( const char* );
- int Load( FILE* );
- void Print( XMLStreamer* streamer=0 );
- XMLElement* NewElement( const char* name );
- enum {
- NO_ERROR = 0,
- ERROR_ELEMENT_MISMATCH,
- ERROR_PARSING_ELEMENT,
- ERROR_PARSING_ATTRIBUTE
- };
- void SetError( int error, const char* str1, const char* str2 );
-
- bool Error() const { return errorID != NO_ERROR; }
- int GetErrorID() const { return errorID; }
- const char* GetErrorStr1() const { return errorStr1; }
- const char* GetErrorStr2() const { return errorStr2; }
- // const char* Intern( const char* );
- private:
- XMLDocument( const XMLDocument& ); // intentionally not implemented
- void InitDocument();
- int errorID;
- const char* errorStr1;
- const char* errorStr2;
- char* charBuffer;
- //StringStack stringPool;
- };
- 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.
- bool TextOnStack() const {
- for( int i=0; i<text.Size(); ++i ) {
- if ( text[i] == 'T' )
- return true;
- }
- return false;
- }
- FILE* fp;
- int depth;
- bool elementJustOpened;
- enum {
- ENTITY_RANGE = 64
- };
- bool entityFlag[ENTITY_RANGE];
- DynArray< const char*, 10 > stack;
- DynArray< char, 10 > text;
- };
- }; // tinyxml2
- #endif // TINYXML2_INCLUDED
|