tinyxml2.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #ifndef TINYXML2_INCLUDED
  2. #define TINYXML2_INCLUDED
  3. #include <limits.h>
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
  7. #ifndef DEBUG
  8. #define DEBUG
  9. #endif
  10. #endif
  11. #if defined(DEBUG)
  12. #if defined(_MSC_VER)
  13. #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
  14. #elif defined (ANDROID_NDK)
  15. #include <android/log.h>
  16. #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
  17. #else
  18. #include <assert.h>
  19. #define TIXMLASSERT assert
  20. #endif
  21. #else
  22. #define TIXMLASSERT( x ) {}
  23. #endif
  24. namespace tinyxml2
  25. {
  26. class XMLDocument;
  27. class XMLElement;
  28. class XMLAttribute;
  29. class XMLComment;
  30. class XMLNode;
  31. class XMLText;
  32. class XMLStreamer;
  33. /*
  34. // internal - move to separate namespace
  35. struct CharBuffer
  36. {
  37. size_t length;
  38. char mem[1];
  39. static CharBuffer* Construct( const char* in );
  40. static void Free( CharBuffer* );
  41. };
  42. */
  43. class StrPair
  44. {
  45. public:
  46. enum {
  47. NEEDS_ENTITY_PROCESSING = 0x01,
  48. NEEDS_NEWLINE_NORMALIZATION = 0x02,
  49. TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
  50. ATTRIBUTE_NAME = 0,
  51. ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
  52. COMMENT = NEEDS_NEWLINE_NORMALIZATION,
  53. };
  54. StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
  55. void Set( char* start, char* end, int flags ) {
  56. this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
  57. }
  58. const char* GetStr();
  59. bool Empty() const { return start == end; }
  60. private:
  61. enum {
  62. NEEDS_FLUSH = 0x100
  63. };
  64. // After parsing, if *end != 0, it can be set to zero.
  65. int flags;
  66. char* start;
  67. char* end;
  68. };
  69. class XMLBase
  70. {
  71. public:
  72. XMLBase() {}
  73. virtual ~XMLBase() {}
  74. protected:
  75. static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; }
  76. static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
  77. inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
  78. int n = 0;
  79. if ( p == q ) {
  80. return true;
  81. }
  82. while( *p && *q && *p == *q && n<nChar ) {
  83. ++p; ++q; ++n;
  84. }
  85. if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
  86. return true;
  87. }
  88. return false;
  89. }
  90. inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
  91. inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
  92. inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
  93. char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
  94. char* ParseName( char* in, StrPair* pair );
  95. char* Identify( XMLDocument* document, char* p, XMLNode** node );
  96. };
  97. class XMLNode : public XMLBase
  98. {
  99. friend class XMLDocument;
  100. friend class XMLElement;
  101. public:
  102. virtual ~XMLNode();
  103. XMLNode* InsertEndChild( XMLNode* addThis );
  104. virtual void Print( XMLStreamer* streamer );
  105. virtual XMLElement* ToElement() { return 0; }
  106. virtual XMLText* ToText() { return 0; }
  107. virtual XMLComment* ToComment() { return 0; }
  108. // fixme: guarentee null terminator to avoid internal checks
  109. virtual char* ParseDeep( char* );
  110. void SetTextParent() { isTextParent = true; }
  111. bool IsTextParent() const { return isTextParent; }
  112. virtual bool IsClosingElement() const { return false; }
  113. protected:
  114. XMLNode( XMLDocument* );
  115. void ClearChildren();
  116. XMLDocument* document;
  117. XMLNode* parent;
  118. bool isTextParent;
  119. XMLNode* firstChild;
  120. XMLNode* lastChild;
  121. XMLNode* prev;
  122. XMLNode* next;
  123. private:
  124. void Unlink( XMLNode* child );
  125. };
  126. class XMLText : public XMLNode
  127. {
  128. public:
  129. XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
  130. virtual ~XMLText() {}
  131. virtual void Print( XMLStreamer* streamer );
  132. const char* Value() { return value.GetStr(); }
  133. virtual XMLText* ToText() { return this; }
  134. char* ParseDeep( char* );
  135. protected:
  136. private:
  137. StrPair value;
  138. };
  139. class XMLComment : public XMLNode
  140. {
  141. public:
  142. XMLComment( XMLDocument* doc );
  143. virtual ~XMLComment();
  144. virtual void Print( XMLStreamer* );
  145. virtual XMLComment* ToComment() { return this; }
  146. const char* Value() { return value.GetStr(); }
  147. char* ParseDeep( char* );
  148. protected:
  149. private:
  150. StrPair value;
  151. };
  152. class XMLAttribute : public XMLBase
  153. {
  154. friend class XMLElement;
  155. public:
  156. XMLAttribute( XMLElement* element ) : next( 0 ) {}
  157. virtual ~XMLAttribute() {}
  158. virtual void Print( XMLStreamer* streamer );
  159. private:
  160. char* ParseDeep( char* p );
  161. StrPair name;
  162. StrPair value;
  163. XMLAttribute* next;
  164. };
  165. class XMLElement : public XMLNode
  166. {
  167. public:
  168. XMLElement( XMLDocument* doc );
  169. virtual ~XMLElement();
  170. const char* Name() { return name.GetStr(); }
  171. virtual void Print( XMLStreamer* );
  172. virtual XMLElement* ToElement() { return this; }
  173. virtual bool IsClosingElement() const { return closing; }
  174. char* ParseDeep( char* p );
  175. protected:
  176. private:
  177. char* ParseAttributes( char* p, bool *closedElement );
  178. StrPair name;
  179. bool closing;
  180. XMLAttribute* rootAttribute;
  181. XMLAttribute* lastAttribute;
  182. };
  183. class XMLDocument : public XMLNode
  184. {
  185. public:
  186. XMLDocument();
  187. ~XMLDocument();
  188. int Parse( const char* );
  189. int Load( const char* );
  190. int Load( FILE* );
  191. void Print( XMLStreamer* streamer=0 );
  192. enum {
  193. NO_ERROR = 0,
  194. ERROR_ELEMENT_MISMATCH,
  195. ERROR_PARSING_ELEMENT,
  196. ERROR_PARSING_ATTRIBUTE
  197. };
  198. void SetError( int error, const char* str1, const char* str2 );
  199. bool Error() const { return errorID != NO_ERROR; }
  200. int GetErrorID() const { return errorID; }
  201. const char* GetErrorStr1() const { return errorStr1; }
  202. const char* GetErrorStr2() const { return errorStr2; }
  203. private:
  204. XMLDocument( const XMLDocument& ); // intentionally not implemented
  205. void InitDocument();
  206. int errorID;
  207. const char* errorStr1;
  208. const char* errorStr2;
  209. char* charBuffer;
  210. };
  211. class StringStack
  212. {
  213. public:
  214. StringStack();
  215. ~StringStack();
  216. void Push( const char* str );
  217. const char* Pop();
  218. int NumPositive() const { return nPositive; }
  219. private:
  220. enum {
  221. INIT=10 // fixme, super small for testing
  222. };
  223. char* mem;
  224. char pool[INIT];
  225. int inUse; // includes null
  226. int allocated; // bytes allocated
  227. int nPositive; // number of strings with len > 0
  228. };
  229. class StringPtrStack
  230. {
  231. public:
  232. StringPtrStack();
  233. ~StringPtrStack();
  234. void Push( const char* str );
  235. const char* Pop();
  236. int NumPositive() const { return nPositive; }
  237. private:
  238. enum {
  239. INIT=10 // fixme, super small for testing
  240. };
  241. char** mem;
  242. char* pool[INIT];
  243. int inUse;
  244. int allocated; // bytes allocated
  245. int nPositive; // number of non-null pointers
  246. };
  247. class XMLStreamer
  248. {
  249. public:
  250. XMLStreamer( FILE* file );
  251. ~XMLStreamer() {}
  252. void OpenElement( const char* name, bool textParent );
  253. void PushAttribute( const char* name, const char* value );
  254. void CloseElement();
  255. void PushText( const char* text );
  256. void PushComment( const char* comment );
  257. private:
  258. void SealElement();
  259. void PrintSpace( int depth );
  260. void PrintString( const char* ); // prints out, after detecting entities.
  261. FILE* fp;
  262. int depth;
  263. bool elementJustOpened;
  264. enum {
  265. ENTITY_RANGE = 64
  266. };
  267. bool entityFlag[ENTITY_RANGE];
  268. StringPtrStack stack;
  269. StringStack text;
  270. };
  271. }; // tinyxml2
  272. #endif // TINYXML2_INCLUDED