tinyxml2.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. // internal - move to separate namespace
  34. struct CharBuffer
  35. {
  36. size_t length;
  37. char mem[1];
  38. static CharBuffer* Construct( const char* in );
  39. static void Free( CharBuffer* );
  40. };
  41. // FIXME: refactor to be the basis for all string handling.
  42. class StrPair
  43. {
  44. public:
  45. enum {
  46. NEEDS_ENTITY_PROCESSING = 0x01,
  47. NEEDS_NEWLINE_NORMALIZATION = 0x02
  48. };
  49. StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
  50. void Set( char* start, char* end, int flags ) {
  51. this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
  52. }
  53. const char* GetStr();
  54. bool Empty() const { return start == end; }
  55. private:
  56. enum {
  57. NEEDS_FLUSH = 0x100
  58. };
  59. // After parsing, if *end != 0, it can be set to zero.
  60. int flags;
  61. char* start;
  62. char* end;
  63. };
  64. class XMLBase
  65. {
  66. public:
  67. XMLBase() {}
  68. virtual ~XMLBase() {}
  69. protected:
  70. static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; }
  71. static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
  72. inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
  73. int n = 0;
  74. if ( p == q ) {
  75. return true;
  76. }
  77. while( *p && *q && *p == *q && n<nChar ) {
  78. ++p; ++q; ++n;
  79. }
  80. if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
  81. return true;
  82. }
  83. return false;
  84. }
  85. inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
  86. inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
  87. inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
  88. char* ParseText( char* in, StrPair* pair, const char* endTag );
  89. char* ParseName( char* in, StrPair* pair );
  90. char* Identify( XMLDocument* document, char* p, XMLNode** node );
  91. };
  92. class XMLNode : public XMLBase
  93. {
  94. friend class XMLDocument;
  95. friend class XMLElement;
  96. public:
  97. virtual ~XMLNode();
  98. XMLNode* InsertEndChild( XMLNode* addThis );
  99. virtual void Print( XMLStreamer* streamer );
  100. virtual XMLElement* ToElement() { return 0; }
  101. virtual XMLText* ToText() { return 0; }
  102. virtual XMLComment* ToComment() { return 0; }
  103. // fixme: guarentee null terminator to avoid internal checks
  104. virtual char* ParseDeep( char* );
  105. void SetTextParent() { isTextParent = true; }
  106. bool IsTextParent() const { return isTextParent; }
  107. virtual bool IsClosingElement() const { return false; }
  108. protected:
  109. XMLNode( XMLDocument* );
  110. void Unlink( XMLNode* child );
  111. XMLDocument* document;
  112. XMLNode* parent;
  113. bool isTextParent;
  114. XMLNode* firstChild;
  115. XMLNode* lastChild;
  116. XMLNode* prev;
  117. XMLNode* next;
  118. private:
  119. };
  120. class XMLText : public XMLNode
  121. {
  122. public:
  123. XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
  124. virtual ~XMLText() {}
  125. virtual void Print( XMLStreamer* streamer );
  126. const char* Value() { return value.GetStr(); }
  127. virtual XMLText* ToText() { return this; }
  128. char* ParseDeep( char* );
  129. protected:
  130. private:
  131. StrPair value;
  132. };
  133. class XMLComment : public XMLNode
  134. {
  135. public:
  136. XMLComment( XMLDocument* doc );
  137. virtual ~XMLComment();
  138. virtual void Print( XMLStreamer* );
  139. virtual XMLComment* ToComment() { return this; }
  140. const char* Value() { return value.GetStr(); }
  141. char* ParseDeep( char* );
  142. protected:
  143. private:
  144. StrPair value;
  145. };
  146. class XMLAttribute : public XMLBase
  147. {
  148. friend class XMLElement;
  149. public:
  150. XMLAttribute( XMLElement* element ) : next( 0 ) {}
  151. virtual ~XMLAttribute() {}
  152. virtual void Print( XMLStreamer* streamer );
  153. private:
  154. char* ParseDeep( char* p );
  155. StrPair name;
  156. StrPair value;
  157. XMLAttribute* next;
  158. };
  159. class XMLElement : public XMLNode
  160. {
  161. public:
  162. XMLElement( XMLDocument* doc );
  163. virtual ~XMLElement();
  164. const char* Name() { return name.GetStr(); }
  165. virtual void Print( XMLStreamer* );
  166. virtual XMLElement* ToElement() { return this; }
  167. virtual bool IsClosingElement() const { return closing; }
  168. char* ParseDeep( char* p );
  169. protected:
  170. private:
  171. char* ParseAttributes( char* p, bool *closedElement );
  172. StrPair name;
  173. bool closing;
  174. XMLAttribute* rootAttribute;
  175. XMLAttribute* lastAttribute;
  176. };
  177. class XMLDocument : public XMLNode
  178. {
  179. public:
  180. XMLDocument();
  181. ~XMLDocument();
  182. bool Parse( const char* );
  183. void Print( XMLStreamer* streamer=0 );
  184. /*
  185. XMLNode* Root() { return root; }
  186. XMLNode* RootElement();
  187. */
  188. enum {
  189. ERROR_ELEMENT_MISMATCH,
  190. ERROR_PARSING_ELEMENT,
  191. ERROR_PARSING_ATTRIBUTE
  192. };
  193. void SetError( int error, const char* str1, const char* str2 );
  194. private:
  195. XMLDocument( const XMLDocument& ); // intentionally not implemented
  196. CharBuffer* charBuffer;
  197. };
  198. // FIXME: break out into string pointer stack
  199. class StringStack
  200. {
  201. public:
  202. StringStack();
  203. ~StringStack();
  204. void Push( const char* str );
  205. const char* Pop();
  206. int NumPositive() const { return nPositive; }
  207. private:
  208. enum {
  209. INIT=10 // fixme, super small for testing
  210. };
  211. char* mem;
  212. char pool[INIT];
  213. int inUse; // includes null
  214. int allocated; // bytes allocated
  215. int nPositive; // number of strings with len > 0
  216. };
  217. class XMLStreamer
  218. {
  219. public:
  220. XMLStreamer( FILE* file );
  221. ~XMLStreamer() {}
  222. void OpenElement( const char* name, bool textParent );
  223. void PushAttribute( const char* name, const char* value );
  224. void CloseElement();
  225. void PushText( const char* text );
  226. void PushComment( const char* comment );
  227. private:
  228. void SealElement();
  229. void PrintSpace( int depth );
  230. void PrintString( const char* ); // prints out, after detecting entities.
  231. FILE* fp;
  232. int depth;
  233. bool elementJustOpened;
  234. enum {
  235. ENTITY_RANGE = 64
  236. };
  237. bool entityFlag[ENTITY_RANGE];
  238. StringStack stack;
  239. StringStack text;
  240. };
  241. }; // tinyxml2
  242. #endif // TINYXML2_INCLUDED