blob: 7356dc5b64df8b935aa0a80303da0066222baf74 [file] [log] [blame]
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001#ifndef TINYXML2_INCLUDED
2#define TINYXML2_INCLUDED
3
U-Lama\Lee4cee6112011-12-31 14:58:18 -08004#include <limits.h>
Lee Thomasonce0763e2012-01-11 15:43:54 -08005#include <ctype.h>
6#include <stdio.h>
U-Lama\Lee4cee6112011-12-31 14:58:18 -08007
8#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
9 #ifndef DEBUG
10 #define DEBUG
11 #endif
12#endif
13
14
15#if defined(DEBUG)
16 #if defined(_MSC_VER)
17 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
18 #elif defined (ANDROID_NDK)
19 #include <android/log.h>
20 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
21 #else
22 #include <assert.h>
23 #define TIXMLASSERT assert
24 #endif
25#else
26 #define TIXMLASSERT( x ) {}
27#endif
28
U-Lama\Leee13c3e62011-12-28 14:36:55 -080029
30namespace tinyxml2
31{
Lee Thomasonce0763e2012-01-11 15:43:54 -080032class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080033class XMLElement;
34class XMLAttribute;
35class XMLComment;
36class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080037class XMLText;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080038
Lee Thomason5cae8972012-01-24 18:03:07 -080039class XMLStreamer;
40
U-Lama\Lee560bd472011-12-28 19:42:49 -080041// internal - move to separate namespace
42struct CharBuffer
43{
44 size_t length;
45 char mem[1];
46
47 static CharBuffer* Construct( const char* in );
48 static void Free( CharBuffer* );
49};
50
Lee Thomason39ede242012-01-20 11:27:56 -080051// FIXME: refactor to be the basis for all string handling.
52class StrPair
53{
Lee Thomasond34f52c2012-01-20 12:55:24 -080054public:
Lee Thomason39ede242012-01-20 11:27:56 -080055 enum {
Lee Thomasone4422302012-01-20 17:59:50 -080056 NEEDS_ENTITY_PROCESSING = 0x01,
57 NEEDS_NEWLINE_NORMALIZATION = 0x02
Lee Thomason39ede242012-01-20 11:27:56 -080058 };
59
60 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomasone4422302012-01-20 17:59:50 -080061 void Set( char* start, char* end, int flags ) {
Lee Thomason39ede242012-01-20 11:27:56 -080062 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
63 }
64 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -080065 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -080066
67private:
Lee Thomasone4422302012-01-20 17:59:50 -080068 enum {
69 NEEDS_FLUSH = 0x100
70 };
71
Lee Thomason39ede242012-01-20 11:27:56 -080072 // After parsing, if *end != 0, it can be set to zero.
73 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -080074 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -080075 char* end;
76};
77
U-Lama\Lee560bd472011-12-28 19:42:49 -080078
Lee Thomason8a5dfee2012-01-18 17:43:40 -080079class XMLBase
U-Lama\Leee13c3e62011-12-28 14:36:55 -080080{
81public:
Lee Thomason8a5dfee2012-01-18 17:43:40 -080082 XMLBase() {}
83 virtual ~XMLBase() {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080084
85protected:
Lee Thomason3f57d272012-01-11 15:30:03 -080086 static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; }
87 static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -080088
89 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
90 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -080091 if ( p == q ) {
92 return true;
93 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -080094 while( *p && *q && *p == *q && n<nChar ) {
95 ++p; ++q; ++n;
96 }
97 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
98 return true;
99 }
100 return false;
101 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800102 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
103 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
104 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800105
Lee Thomasone4422302012-01-20 17:59:50 -0800106 char* ParseText( char* in, StrPair* pair, const char* endTag );
Lee Thomason39ede242012-01-20 11:27:56 -0800107 char* ParseName( char* in, StrPair* pair );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108 char* Identify( XMLDocument* document, char* p, XMLNode** node );
109};
110
Lee Thomason5cae8972012-01-24 18:03:07 -0800111
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800112class XMLNode : public XMLBase
113{
114 friend class XMLDocument;
115 friend class XMLElement;
116public:
117 virtual ~XMLNode();
118
119 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason5cae8972012-01-24 18:03:07 -0800120 virtual void Print( XMLStreamer* streamer );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800121
Lee Thomason5492a1c2012-01-23 15:32:10 -0800122 virtual XMLElement* ToElement() { return 0; }
123 virtual XMLText* ToText() { return 0; }
124 virtual XMLComment* ToComment() { return 0; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800125
Lee Thomason67d61312012-01-24 16:01:51 -0800126 // fixme: guarentee null terminator to avoid internal checks
127 virtual char* ParseDeep( char* );
128
129 void SetTextParent() { isTextParent = true; }
130 bool IsTextParent() const { return isTextParent; }
131 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800132
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800133protected:
134 XMLNode( XMLDocument* );
Lee Thomasond923c672012-01-23 08:44:25 -0800135 void Unlink( XMLNode* child );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800136
Lee Thomason3f57d272012-01-11 15:30:03 -0800137 XMLDocument* document;
138 XMLNode* parent;
Lee Thomason67d61312012-01-24 16:01:51 -0800139 bool isTextParent;
Lee Thomason3f57d272012-01-11 15:30:03 -0800140
141 XMLNode* firstChild;
142 XMLNode* lastChild;
143
144 XMLNode* prev;
145 XMLNode* next;
146
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800147private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800148};
149
150
Lee Thomason5492a1c2012-01-23 15:32:10 -0800151class XMLText : public XMLNode
152{
153public:
154 XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
155 virtual ~XMLText() {}
156
Lee Thomason5cae8972012-01-24 18:03:07 -0800157 virtual void Print( XMLStreamer* streamer );
Lee Thomason5492a1c2012-01-23 15:32:10 -0800158 const char* Value() { return value.GetStr(); }
159 virtual XMLText* ToText() { return this; }
160
161 char* ParseDeep( char* );
162
163protected:
164
165private:
166 StrPair value;
167};
168
169
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800170class XMLComment : public XMLNode
171{
Lee Thomason3f57d272012-01-11 15:30:03 -0800172public:
173 XMLComment( XMLDocument* doc );
174 virtual ~XMLComment();
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800175
Lee Thomason5cae8972012-01-24 18:03:07 -0800176 virtual void Print( XMLStreamer* );
Lee Thomason5492a1c2012-01-23 15:32:10 -0800177 virtual XMLComment* ToComment() { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800178
Lee Thomasond34f52c2012-01-20 12:55:24 -0800179 const char* Value() { return value.GetStr(); }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800180
Lee Thomasonce0763e2012-01-11 15:43:54 -0800181 char* ParseDeep( char* );
182
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800183protected:
184
Lee Thomason3f57d272012-01-11 15:30:03 -0800185private:
Lee Thomasond34f52c2012-01-20 12:55:24 -0800186 StrPair value;
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800187};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800188
189
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800190class XMLAttribute : public XMLBase
191{
192 friend class XMLElement;
193public:
Lee Thomasond34f52c2012-01-20 12:55:24 -0800194 XMLAttribute( XMLElement* element ) : next( 0 ) {}
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800195 virtual ~XMLAttribute() {}
Lee Thomason5cae8972012-01-24 18:03:07 -0800196 virtual void Print( XMLStreamer* streamer );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800197
198private:
199 char* ParseDeep( char* p );
200
Lee Thomason22aead12012-01-23 13:29:35 -0800201 StrPair name;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800202 StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800203 XMLAttribute* next;
204};
205
206
207class XMLElement : public XMLNode
208{
209public:
210 XMLElement( XMLDocument* doc );
211 virtual ~XMLElement();
212
Lee Thomasond34f52c2012-01-20 12:55:24 -0800213 const char* Name() { return name.GetStr(); }
Lee Thomason5cae8972012-01-24 18:03:07 -0800214 virtual void Print( XMLStreamer* );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800215
216 virtual XMLElement* ToElement() { return this; }
Lee Thomason67d61312012-01-24 16:01:51 -0800217 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800218
219 char* ParseDeep( char* p );
220
221protected:
222
223private:
Lee Thomason67d61312012-01-24 16:01:51 -0800224 char* ParseAttributes( char* p, bool *closedElement );
225
Lee Thomasond34f52c2012-01-20 12:55:24 -0800226 StrPair name;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800227 bool closing;
228 XMLAttribute* rootAttribute;
229 XMLAttribute* lastAttribute;
230};
231
232
Lee Thomason67d61312012-01-24 16:01:51 -0800233class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800234{
235public:
236 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800237 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800238
239 bool Parse( const char* );
Lee Thomason5cae8972012-01-24 18:03:07 -0800240 void Print( XMLStreamer* streamer=0 );
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800241
Lee Thomason67d61312012-01-24 16:01:51 -0800242 /*
Lee Thomason3f57d272012-01-11 15:30:03 -0800243 XMLNode* Root() { return root; }
244 XMLNode* RootElement();
Lee Thomason67d61312012-01-24 16:01:51 -0800245 */
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800246 enum {
247 ERROR_ELEMENT_MISMATCH,
248 ERROR_PARSING_ELEMENT,
249 ERROR_PARSING_ATTRIBUTE
250 };
Lee Thomason67d61312012-01-24 16:01:51 -0800251 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800252
Lee Thomason3f57d272012-01-11 15:30:03 -0800253private:
254 XMLDocument( const XMLDocument& ); // intentionally not implemented
U-Lama\Lee560bd472011-12-28 19:42:49 -0800255 CharBuffer* charBuffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800256};
257
258
Lee Thomason24767b02012-01-25 17:16:23 -0800259// FIXME: break out into string pointer stack
Lee Thomason5cae8972012-01-24 18:03:07 -0800260class StringStack
261{
262public:
263 StringStack();
Lee Thomason24767b02012-01-25 17:16:23 -0800264 ~StringStack();
Lee Thomason5cae8972012-01-24 18:03:07 -0800265
266 void Push( const char* str );
267 const char* Pop();
268
269 int NumPositive() const { return nPositive; }
270
271private:
272 enum {
273 INIT=10 // fixme, super small for testing
274 };
275 char* mem;
Lee Thomason24767b02012-01-25 17:16:23 -0800276 char pool[INIT];
Lee Thomason5cae8972012-01-24 18:03:07 -0800277 int inUse; // includes null
278 int allocated; // bytes allocated
279 int nPositive; // number of strings with len > 0
280};
281
Lee Thomason5cae8972012-01-24 18:03:07 -0800282class XMLStreamer
283{
284public:
285 XMLStreamer( FILE* file );
286 ~XMLStreamer() {}
287
288 void OpenElement( const char* name, bool textParent );
289 void PushAttribute( const char* name, const char* value );
290 void CloseElement();
291
292 void PushText( const char* text );
293 void PushComment( const char* comment );
294
295private:
296 void SealElement();
297 void PrintSpace( int depth );
298
299 FILE* fp;
300 int depth;
301 bool elementJustOpened;
302
303 StringStack stack;
304 StringStack text;
305};
306
307
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800308}; // tinyxml2
309
U-Lama\Lee560bd472011-12-28 19:42:49 -0800310
311
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800312#endif // TINYXML2_INCLUDED