tinyxml2.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. #ifndef TINYXML2_INCLUDED
  2. #define TINYXML2_INCLUDED
  3. /*
  4. TODO
  5. - const and non-const versions of API
  6. X memory pool the class construction
  7. - attribute accessors
  8. - node navigation
  9. - handles
  10. - visit pattern - change streamer?
  11. - make constructors protected
  12. - hide copy constructor
  13. - hide = operator
  14. - UTF8 support: isAlpha, etc.
  15. */
  16. #include <limits.h>
  17. #include <ctype.h>
  18. #include <stdio.h>
  19. #include <memory.h>
  20. #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
  21. #ifndef DEBUG
  22. #define DEBUG
  23. #endif
  24. #endif
  25. #if defined(DEBUG)
  26. #if defined(_MSC_VER)
  27. #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
  28. #elif defined (ANDROID_NDK)
  29. #include <android/log.h>
  30. #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
  31. #else
  32. #include <assert.h>
  33. #define TIXMLASSERT assert
  34. #endif
  35. #else
  36. #define TIXMLASSERT( x ) {}
  37. #endif
  38. namespace tinyxml2
  39. {
  40. class XMLDocument;
  41. class XMLElement;
  42. class XMLAttribute;
  43. class XMLComment;
  44. class XMLNode;
  45. class XMLText;
  46. class XMLStreamer;
  47. class StrPair
  48. {
  49. public:
  50. enum {
  51. NEEDS_ENTITY_PROCESSING = 0x01,
  52. NEEDS_NEWLINE_NORMALIZATION = 0x02,
  53. TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
  54. ATTRIBUTE_NAME = 0,
  55. ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
  56. COMMENT = NEEDS_NEWLINE_NORMALIZATION,
  57. };
  58. StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
  59. void Set( char* start, char* end, int flags ) {
  60. this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
  61. }
  62. const char* GetStr();
  63. bool Empty() const { return start == end; }
  64. void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
  65. private:
  66. enum {
  67. NEEDS_FLUSH = 0x100
  68. };
  69. // After parsing, if *end != 0, it can be set to zero.
  70. int flags;
  71. char* start;
  72. char* end;
  73. };
  74. template <class T, int INIT>
  75. class DynArray
  76. {
  77. public:
  78. DynArray< T, INIT >()
  79. {
  80. mem = pool;
  81. allocated = INIT;
  82. size = 0;
  83. }
  84. ~DynArray()
  85. {
  86. if ( mem != pool ) {
  87. delete mem;
  88. }
  89. }
  90. void Push( T t )
  91. {
  92. EnsureCapacity( size+1 );
  93. mem[size++] = t;
  94. }
  95. T* PushArr( int count )
  96. {
  97. EnsureCapacity( size+count );
  98. T* ret = &mem[size];
  99. size += count;
  100. return ret;
  101. }
  102. T Pop() {
  103. return mem[--size];
  104. }
  105. void PopArr( int count )
  106. {
  107. TIXMLASSERT( size >= count );
  108. size -= count;
  109. }
  110. bool Empty() const { return size == 0; }
  111. T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
  112. const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
  113. int Size() const { return size; }
  114. const T* Mem() const { return mem; }
  115. T* Mem() { return mem; }
  116. private:
  117. void EnsureCapacity( int cap ) {
  118. if ( cap > allocated ) {
  119. int newAllocated = cap * 2;
  120. T* newMem = new T[newAllocated];
  121. memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
  122. if ( mem != pool ) delete [] mem;
  123. mem = newMem;
  124. allocated = newAllocated;
  125. }
  126. }
  127. T* mem;
  128. T pool[INIT];
  129. int allocated; // objects allocated
  130. int size; // number objects in use
  131. };
  132. class MemPool
  133. {
  134. public:
  135. MemPool() {}
  136. virtual ~MemPool() {}
  137. virtual int ItemSize() const = 0;
  138. virtual void* Alloc() = 0;
  139. virtual void Free( void* ) = 0;
  140. };
  141. template< int SIZE >
  142. class MemPoolT : public MemPool
  143. {
  144. public:
  145. MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
  146. ~MemPoolT() {
  147. // Delete the blocks.
  148. for( int i=0; i<blockPtrs.Size(); ++i ) {
  149. delete blockPtrs[i];
  150. }
  151. }
  152. virtual int ItemSize() const { return SIZE; }
  153. int CurrentAllocs() const { return currentAllocs; }
  154. virtual void* Alloc() {
  155. if ( !root ) {
  156. // Need a new block.
  157. Block* block = new Block();
  158. blockPtrs.Push( block );
  159. for( int i=0; i<COUNT-1; ++i ) {
  160. block->chunk[i].next = &block->chunk[i+1];
  161. }
  162. block->chunk[COUNT-1].next = 0;
  163. root = block->chunk;
  164. }
  165. void* result = root;
  166. root = root->next;
  167. ++currentAllocs;
  168. if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
  169. nAllocs++;
  170. return result;
  171. }
  172. virtual void Free( void* mem ) {
  173. if ( !mem ) return;
  174. --currentAllocs;
  175. Chunk* chunk = (Chunk*)mem;
  176. memset( chunk, 0xfe, sizeof(Chunk) );
  177. chunk->next = root;
  178. root = chunk;
  179. }
  180. void Trace( const char* name ) {
  181. printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
  182. name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
  183. }
  184. private:
  185. enum { COUNT = 1024/SIZE };
  186. union Chunk {
  187. Chunk* next;
  188. char mem[SIZE];
  189. };
  190. struct Block {
  191. Chunk chunk[COUNT];
  192. };
  193. DynArray< Block*, 10 > blockPtrs;
  194. Chunk* root;
  195. int currentAllocs;
  196. int nAllocs;
  197. int maxAllocs;
  198. };
  199. /*
  200. class StringStack
  201. {
  202. public:
  203. StringStack();
  204. virtual ~StringStack();
  205. void Push( const char* str );
  206. const char* Pop();
  207. int NumPositive() const { return nPositive; }
  208. private:
  209. DynArray< char, 50 > mem;
  210. int nPositive; // number of strings with len > 0
  211. };
  212. */
  213. /*
  214. class StringPool
  215. {
  216. public:
  217. enum { INIT_SIZE=20 };
  218. StringPool() : size( 0 ) {
  219. const char** mem = pool.PushArr( INIT_SIZE );
  220. memset( (void*)mem, 0, sizeof(char)*INIT_SIZE );
  221. }
  222. ~StringPool() {}
  223. const char* Intern( const char* str );
  224. private:
  225. // FNV hash
  226. int Hash( const char* s ) {
  227. #define FNV_32_PRIME ((int)0x01000193)
  228. int hval = 0;
  229. while (*s) {
  230. hval *= FNV_32_PRIME;
  231. hval ^= (int)*s++;
  232. }
  233. return hval;
  234. }
  235. int size;
  236. DynArray< const char*, INIT_SIZE > pool; // the hash table
  237. StringStack store; // memory for the interned strings
  238. };
  239. */
  240. class XMLBase
  241. {
  242. public:
  243. public:
  244. XMLBase() {}
  245. virtual ~XMLBase() {}
  246. static const char* SkipWhiteSpace( const char* p ) { while( isspace( *p ) ) { ++p; } return p; }
  247. static char* SkipWhiteSpace( char* p ) { while( isspace( *p ) ) { ++p; } return p; }
  248. inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
  249. int n = 0;
  250. if ( p == q ) {
  251. return true;
  252. }
  253. while( *p && *q && *p == *q && n<nChar ) {
  254. ++p; ++q; ++n;
  255. }
  256. if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
  257. return true;
  258. }
  259. return false;
  260. }
  261. inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
  262. inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalnum( anyByte ) : 1; }
  263. inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte <= 127 ) ? isalpha( anyByte ) : 1; }
  264. static char* ParseText( char* in, StrPair* pair, const char* endTag, int strFlags );
  265. static char* ParseName( char* in, StrPair* pair );
  266. private:
  267. };
  268. class XMLNode
  269. {
  270. friend class XMLDocument;
  271. friend class XMLElement;
  272. public:
  273. //void* operator new( size_t size, MemPool* pool );
  274. //void operator delete( void* mem, MemPool* pool );
  275. XMLNode* InsertEndChild( XMLNode* addThis );
  276. virtual void Print( XMLStreamer* streamer );
  277. const char* Value() const { return value.GetStr(); }
  278. void SetValue( const char* val ) { value.SetInternedStr( val ); }
  279. virtual XMLElement* ToElement() { return 0; }
  280. virtual XMLText* ToText() { return 0; }
  281. virtual XMLComment* ToComment() { return 0; }
  282. XMLNode* FirstChild() { return firstChild; }
  283. XMLElement* FirstChildElement( const char* value=0 );
  284. // fixme: guarentee null terminator to avoid internal checks
  285. virtual char* ParseDeep( char* );
  286. void SetTextParent() { isTextParent = true; }
  287. bool IsTextParent() const { return isTextParent; }
  288. virtual bool IsClosingElement() const { return false; }
  289. protected:
  290. XMLNode( XMLDocument* );
  291. virtual ~XMLNode();
  292. void ClearChildren();
  293. XMLDocument* document;
  294. XMLNode* parent;
  295. bool isTextParent;
  296. mutable StrPair value;
  297. XMLNode* firstChild;
  298. XMLNode* lastChild;
  299. XMLNode* prev;
  300. XMLNode* next;
  301. private:
  302. MemPool* memPool;
  303. void Unlink( XMLNode* child );
  304. };
  305. class XMLText : public XMLNode
  306. {
  307. friend class XMLBase;
  308. friend class XMLDocument;
  309. public:
  310. virtual void Print( XMLStreamer* streamer );
  311. const char* Value() { return value.GetStr(); }
  312. void SetValue( const char* );
  313. virtual XMLText* ToText() { return this; }
  314. char* ParseDeep( char* );
  315. protected:
  316. XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
  317. virtual ~XMLText() {}
  318. private:
  319. };
  320. class XMLComment : public XMLNode
  321. {
  322. friend class XMLBase;
  323. friend class XMLDocument;
  324. public:
  325. virtual void Print( XMLStreamer* );
  326. virtual XMLComment* ToComment() { return this; }
  327. const char* Value() { return value.GetStr(); }
  328. char* ParseDeep( char* );
  329. protected:
  330. XMLComment( XMLDocument* doc );
  331. virtual ~XMLComment();
  332. private:
  333. };
  334. class XMLAttribute : public XMLBase
  335. {
  336. friend class XMLElement;
  337. public:
  338. virtual void Print( XMLStreamer* streamer );
  339. private:
  340. XMLAttribute( XMLElement* element ) : next( 0 ) {}
  341. virtual ~XMLAttribute() {}
  342. char* ParseDeep( char* p );
  343. StrPair name;
  344. StrPair value;
  345. XMLAttribute* next;
  346. MemPool* memPool;
  347. };
  348. class XMLElement : public XMLNode
  349. {
  350. friend class XMLBase;
  351. friend class XMLDocument;
  352. public:
  353. const char* Name() const { return Value(); }
  354. void SetName( const char* str ) { SetValue( str ); }
  355. virtual void Print( XMLStreamer* );
  356. virtual XMLElement* ToElement() { return this; }
  357. // internal:
  358. virtual bool IsClosingElement() const { return closing; }
  359. char* ParseDeep( char* p );
  360. protected:
  361. XMLElement( XMLDocument* doc );
  362. virtual ~XMLElement();
  363. private:
  364. char* ParseAttributes( char* p, bool *closedElement );
  365. bool closing;
  366. XMLAttribute* rootAttribute;
  367. XMLAttribute* lastAttribute;
  368. };
  369. class XMLDocument : public XMLNode
  370. {
  371. friend class XMLElement;
  372. public:
  373. XMLDocument();
  374. ~XMLDocument();
  375. int Parse( const char* );
  376. int Load( const char* );
  377. int Load( FILE* );
  378. void Print( XMLStreamer* streamer=0 );
  379. XMLElement* NewElement( const char* name );
  380. enum {
  381. NO_ERROR = 0,
  382. ERROR_ELEMENT_MISMATCH,
  383. ERROR_PARSING_ELEMENT,
  384. ERROR_PARSING_ATTRIBUTE
  385. };
  386. void SetError( int error, const char* str1, const char* str2 );
  387. bool Error() const { return errorID != NO_ERROR; }
  388. int GetErrorID() const { return errorID; }
  389. const char* GetErrorStr1() const { return errorStr1; }
  390. const char* GetErrorStr2() const { return errorStr2; }
  391. char* Identify( char* p, XMLNode** node );
  392. private:
  393. XMLDocument( const XMLDocument& ); // intentionally not implemented
  394. void InitDocument();
  395. int errorID;
  396. const char* errorStr1;
  397. const char* errorStr2;
  398. char* charBuffer;
  399. //StringStack stringPool;
  400. MemPoolT< sizeof(XMLElement) > elementPool;
  401. MemPoolT< sizeof(XMLAttribute) > attributePool;
  402. MemPoolT< sizeof(XMLText) > textPool;
  403. MemPoolT< sizeof(XMLComment) > commentPool;
  404. };
  405. class XMLStreamer
  406. {
  407. public:
  408. XMLStreamer( FILE* file );
  409. ~XMLStreamer() {}
  410. void OpenElement( const char* name, bool textParent );
  411. void PushAttribute( const char* name, const char* value );
  412. void CloseElement();
  413. void PushText( const char* text );
  414. void PushComment( const char* comment );
  415. private:
  416. void SealElement();
  417. void PrintSpace( int depth );
  418. void PrintString( const char* ); // prints out, after detecting entities.
  419. bool TextOnStack() const {
  420. for( int i=0; i<text.Size(); ++i ) {
  421. if ( text[i] == 'T' )
  422. return true;
  423. }
  424. return false;
  425. }
  426. FILE* fp;
  427. int depth;
  428. bool elementJustOpened;
  429. enum {
  430. ENTITY_RANGE = 64
  431. };
  432. bool entityFlag[ENTITY_RANGE];
  433. DynArray< const char*, 10 > stack;
  434. DynArray< char, 10 > text;
  435. };
  436. }; // tinyxml2
  437. #endif // TINYXML2_INCLUDED