blob: c90e181d390c632ebdfac7f8161e4d517625f4b9 [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
Lee Thomason18d68bd2012-01-26 18:17:26 -080041/*
U-Lama\Lee560bd472011-12-28 19:42:49 -080042// internal - move to separate namespace
43struct CharBuffer
44{
45 size_t length;
46 char mem[1];
47
48 static CharBuffer* Construct( const char* in );
49 static void Free( CharBuffer* );
50};
Lee Thomason18d68bd2012-01-26 18:17:26 -080051*/
U-Lama\Lee560bd472011-12-28 19:42:49 -080052
Lee Thomason39ede242012-01-20 11:27:56 -080053class StrPair
54{
Lee Thomasond34f52c2012-01-20 12:55:24 -080055public:
Lee Thomason39ede242012-01-20 11:27:56 -080056 enum {
Lee Thomasone4422302012-01-20 17:59:50 -080057 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -080058 NEEDS_NEWLINE_NORMALIZATION = 0x02,
59
60 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
61 ATTRIBUTE_NAME = 0,
62 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
63 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -080064 };
65
66 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomasone4422302012-01-20 17:59:50 -080067 void Set( char* start, char* end, int flags ) {
Lee Thomason39ede242012-01-20 11:27:56 -080068 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
69 }
70 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -080071 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -080072
73private:
Lee Thomasone4422302012-01-20 17:59:50 -080074 enum {
75 NEEDS_FLUSH = 0x100
76 };
77
Lee Thomason39ede242012-01-20 11:27:56 -080078 // After parsing, if *end != 0, it can be set to zero.
79 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -080080 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -080081 char* end;
82};
83
U-Lama\Lee560bd472011-12-28 19:42:49 -080084
Lee Thomason8a5dfee2012-01-18 17:43:40 -080085class XMLBase
U-Lama\Leee13c3e62011-12-28 14:36:55 -080086{
87public:
Lee Thomason8a5dfee2012-01-18 17:43:40 -080088 XMLBase() {}
89 virtual ~XMLBase() {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080090
91protected:
Lee Thomason3f57d272012-01-11 15:30:03 -080092 static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; }
93 static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -080094
95 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
96 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -080097 if ( p == q ) {
98 return true;
99 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800100 while( *p && *q && *p == *q && n<nChar ) {
101 ++p; ++q; ++n;
102 }
103 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
104 return true;
105 }
106 return false;
107 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
109 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
110 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800111
Lee Thomason18d68bd2012-01-26 18:17:26 -0800112 char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
Lee Thomason39ede242012-01-20 11:27:56 -0800113 char* ParseName( char* in, StrPair* pair );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800114 char* Identify( XMLDocument* document, char* p, XMLNode** node );
115};
116
Lee Thomason5cae8972012-01-24 18:03:07 -0800117
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800118class XMLNode : public XMLBase
119{
120 friend class XMLDocument;
121 friend class XMLElement;
122public:
123 virtual ~XMLNode();
124
125 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason5cae8972012-01-24 18:03:07 -0800126 virtual void Print( XMLStreamer* streamer );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800127
Lee Thomason5492a1c2012-01-23 15:32:10 -0800128 virtual XMLElement* ToElement() { return 0; }
129 virtual XMLText* ToText() { return 0; }
130 virtual XMLComment* ToComment() { return 0; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800131
Lee Thomason67d61312012-01-24 16:01:51 -0800132 // fixme: guarentee null terminator to avoid internal checks
133 virtual char* ParseDeep( char* );
134
135 void SetTextParent() { isTextParent = true; }
136 bool IsTextParent() const { return isTextParent; }
137 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800138
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800139protected:
140 XMLNode( XMLDocument* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800141 void ClearChildren();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800142
Lee Thomason3f57d272012-01-11 15:30:03 -0800143 XMLDocument* document;
144 XMLNode* parent;
Lee Thomason67d61312012-01-24 16:01:51 -0800145 bool isTextParent;
Lee Thomason3f57d272012-01-11 15:30:03 -0800146
147 XMLNode* firstChild;
148 XMLNode* lastChild;
149
150 XMLNode* prev;
151 XMLNode* next;
152
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800153private:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800154 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800155};
156
157
Lee Thomason5492a1c2012-01-23 15:32:10 -0800158class XMLText : public XMLNode
159{
160public:
161 XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
162 virtual ~XMLText() {}
163
Lee Thomason5cae8972012-01-24 18:03:07 -0800164 virtual void Print( XMLStreamer* streamer );
Lee Thomason5492a1c2012-01-23 15:32:10 -0800165 const char* Value() { return value.GetStr(); }
166 virtual XMLText* ToText() { return this; }
167
168 char* ParseDeep( char* );
169
170protected:
171
172private:
173 StrPair value;
174};
175
176
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800177class XMLComment : public XMLNode
178{
Lee Thomason3f57d272012-01-11 15:30:03 -0800179public:
180 XMLComment( XMLDocument* doc );
181 virtual ~XMLComment();
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800182
Lee Thomason5cae8972012-01-24 18:03:07 -0800183 virtual void Print( XMLStreamer* );
Lee Thomason5492a1c2012-01-23 15:32:10 -0800184 virtual XMLComment* ToComment() { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800185
Lee Thomasond34f52c2012-01-20 12:55:24 -0800186 const char* Value() { return value.GetStr(); }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800187
Lee Thomasonce0763e2012-01-11 15:43:54 -0800188 char* ParseDeep( char* );
189
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800190protected:
191
Lee Thomason3f57d272012-01-11 15:30:03 -0800192private:
Lee Thomasond34f52c2012-01-20 12:55:24 -0800193 StrPair value;
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800194};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800195
196
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800197class XMLAttribute : public XMLBase
198{
199 friend class XMLElement;
200public:
Lee Thomasond34f52c2012-01-20 12:55:24 -0800201 XMLAttribute( XMLElement* element ) : next( 0 ) {}
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800202 virtual ~XMLAttribute() {}
Lee Thomason5cae8972012-01-24 18:03:07 -0800203 virtual void Print( XMLStreamer* streamer );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800204
205private:
206 char* ParseDeep( char* p );
207
Lee Thomason22aead12012-01-23 13:29:35 -0800208 StrPair name;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800209 StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800210 XMLAttribute* next;
211};
212
213
214class XMLElement : public XMLNode
215{
216public:
217 XMLElement( XMLDocument* doc );
218 virtual ~XMLElement();
219
Lee Thomasond34f52c2012-01-20 12:55:24 -0800220 const char* Name() { return name.GetStr(); }
Lee Thomason5cae8972012-01-24 18:03:07 -0800221 virtual void Print( XMLStreamer* );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800222
223 virtual XMLElement* ToElement() { return this; }
Lee Thomason67d61312012-01-24 16:01:51 -0800224 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800225
226 char* ParseDeep( char* p );
227
228protected:
229
230private:
Lee Thomason67d61312012-01-24 16:01:51 -0800231 char* ParseAttributes( char* p, bool *closedElement );
232
Lee Thomasond34f52c2012-01-20 12:55:24 -0800233 StrPair name;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800234 bool closing;
235 XMLAttribute* rootAttribute;
236 XMLAttribute* lastAttribute;
237};
238
239
Lee Thomason67d61312012-01-24 16:01:51 -0800240class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800241{
242public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800243 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800244 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800245
246 bool Parse( const char* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800247 bool Load( const char* );
248 bool Load( FILE* );
249
Lee Thomason5cae8972012-01-24 18:03:07 -0800250 void Print( XMLStreamer* streamer=0 );
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800251
Lee Thomason67d61312012-01-24 16:01:51 -0800252 /*
Lee Thomason3f57d272012-01-11 15:30:03 -0800253 XMLNode* Root() { return root; }
254 XMLNode* RootElement();
Lee Thomason67d61312012-01-24 16:01:51 -0800255 */
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800256 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800257 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800258 ERROR_ELEMENT_MISMATCH,
259 ERROR_PARSING_ELEMENT,
260 ERROR_PARSING_ATTRIBUTE
261 };
Lee Thomason67d61312012-01-24 16:01:51 -0800262 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800263
264 int GetErrorID() const { return errorID; }
265 const char* GetErrorStr1() const { return errorStr1; }
266 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800267
Lee Thomason3f57d272012-01-11 15:30:03 -0800268private:
269 XMLDocument( const XMLDocument& ); // intentionally not implemented
Lee Thomason18d68bd2012-01-26 18:17:26 -0800270 void InitDocument();
271
272 bool errorID;
273 const char* errorStr1;
274 const char* errorStr2;
275 char* charBuffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800276};
277
278
Lee Thomason24767b02012-01-25 17:16:23 -0800279// FIXME: break out into string pointer stack
Lee Thomason5cae8972012-01-24 18:03:07 -0800280class StringStack
281{
282public:
283 StringStack();
Lee Thomason24767b02012-01-25 17:16:23 -0800284 ~StringStack();
Lee Thomason5cae8972012-01-24 18:03:07 -0800285
286 void Push( const char* str );
287 const char* Pop();
288
289 int NumPositive() const { return nPositive; }
290
291private:
292 enum {
293 INIT=10 // fixme, super small for testing
294 };
295 char* mem;
Lee Thomason24767b02012-01-25 17:16:23 -0800296 char pool[INIT];
Lee Thomason5cae8972012-01-24 18:03:07 -0800297 int inUse; // includes null
298 int allocated; // bytes allocated
299 int nPositive; // number of strings with len > 0
300};
301
Lee Thomason5cae8972012-01-24 18:03:07 -0800302class XMLStreamer
303{
304public:
305 XMLStreamer( FILE* file );
306 ~XMLStreamer() {}
307
308 void OpenElement( const char* name, bool textParent );
309 void PushAttribute( const char* name, const char* value );
310 void CloseElement();
311
312 void PushText( const char* text );
313 void PushComment( const char* comment );
314
315private:
316 void SealElement();
317 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800318 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason5cae8972012-01-24 18:03:07 -0800319
320 FILE* fp;
321 int depth;
322 bool elementJustOpened;
Lee Thomason857b8682012-01-25 17:50:25 -0800323 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800324 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800325 };
326 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800327
328 StringStack stack;
329 StringStack text;
330};
331
332
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800333}; // tinyxml2
334
U-Lama\Lee560bd472011-12-28 19:42:49 -0800335
336
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800337#endif // TINYXML2_INCLUDED