tinyxml2.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #include "tinyxml2.h"
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. using namespace tinyxml2;
  7. // --------- CharBuffer ----------- //
  8. /*static*/ CharBuffer* CharBuffer::Construct( const char* in )
  9. {
  10. size_t len = strlen( in );
  11. size_t size = len + sizeof( CharBuffer );
  12. CharBuffer* cb = (CharBuffer*) malloc( size );
  13. cb->length = len;
  14. strcpy( cb->mem, in );
  15. return cb;
  16. }
  17. /*static*/ void CharBuffer::Free( CharBuffer* cb )
  18. {
  19. free( cb );
  20. }
  21. // --------- XMLNode ----------- //
  22. XMLNode::XMLNode( XMLDocument* doc ) :
  23. document( doc ),
  24. parent( 0 ),
  25. firstChild( 0 ), lastChild( 0 ),
  26. prev( 0 ), next( 0 )
  27. {
  28. }
  29. XMLNode::~XMLNode()
  30. {
  31. XMLNode* node=firstChild;
  32. while( node ) {
  33. XMLNode* temp = node->next;
  34. delete node;
  35. node = temp;
  36. }
  37. }
  38. XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
  39. {
  40. if ( lastChild ) {
  41. TIXMLASSERT( firstChild );
  42. TIXMLASSERT( lastChild->next == 0 );
  43. lastChild->next = addThis;
  44. addThis->prev = lastChild;
  45. lastChild = addThis;
  46. addThis->parent = this;
  47. addThis->next = 0;
  48. }
  49. else {
  50. TIXMLASSERT( firstChild == 0 );
  51. firstChild = lastChild = addThis;
  52. addThis->parent = this;
  53. addThis->prev = 0;
  54. addThis->next = 0;
  55. }
  56. return addThis;
  57. }
  58. void XMLNode::Print( FILE* fp, int depth )
  59. {
  60. for( XMLNode* node = firstChild; node; node=node->next ) {
  61. node->Print( fp, depth );
  62. }
  63. }
  64. void XMLNode::PrintSpace( FILE* fp, int depth )
  65. {
  66. for( int i=0; i<depth; ++i ) {
  67. fprintf( fp, " " );
  68. }
  69. }
  70. const char* XMLNode::ParseText( char* p, const char* endTag, char** next )
  71. {
  72. TIXMLASSERT( endTag && *endTag );
  73. char* start = SkipWhiteSpace( p );
  74. if ( !start )
  75. return 0;
  76. char endChar = *endTag;
  77. p = start;
  78. int length = strlen( endTag );
  79. while ( *p ) {
  80. if ( *p == endChar ) {
  81. if ( strncmp( p, endTag, length ) == 0 ) {
  82. *p = 0;
  83. *next = p + length;
  84. return start;
  85. }
  86. }
  87. ++p;
  88. }
  89. return 0;
  90. }
  91. // --------- XMLComment ---------- //
  92. XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
  93. {
  94. }
  95. XMLComment::~XMLComment()
  96. {
  97. }
  98. void XMLComment::Print( FILE* fp, int depth )
  99. {
  100. XMLNode::Print( fp, depth );
  101. fprintf( fp, "<!-- %s -->\n", value );
  102. }
  103. char* XMLComment::ParseDeep( char* p )
  104. {
  105. // Comment parses as text.
  106. value = ParseText( p, "-->", &p );
  107. return p;
  108. }
  109. // --------- XMLDocument ----------- //
  110. XMLDocument::XMLDocument() :
  111. charBuffer( 0 )
  112. {
  113. root = new XMLNode( this );
  114. }
  115. XMLDocument::~XMLDocument()
  116. {
  117. delete root;
  118. delete charBuffer;
  119. }
  120. bool XMLDocument::Parse( const char* p )
  121. {
  122. charBuffer = CharBuffer::Construct( p );
  123. XMLNode* node = 0;
  124. char* q = Identify( charBuffer->mem, &node );
  125. root->InsertEndChild( node );
  126. node->ParseDeep( q );
  127. return true;
  128. }
  129. void XMLDocument::Print( FILE* fp, int depth )
  130. {
  131. for( XMLNode* node = root->firstChild; node; node=node->next ) {
  132. node->Print( fp, depth );
  133. }
  134. }
  135. char* XMLDocument::Identify( char* p, XMLNode** node )
  136. {
  137. XMLNode* returnNode = 0;
  138. p = XMLNode::SkipWhiteSpace( p );
  139. if( !p || !*p || *p != '<' )
  140. {
  141. return 0;
  142. }
  143. // What is this thing?
  144. // - Elements start with a letter or underscore, but xml is reserved.
  145. // - Comments: <!--
  146. // - Decleration: <?xml
  147. // - Everthing else is unknown to tinyxml.
  148. //
  149. static const char* xmlHeader = { "<?xml" };
  150. static const char* commentHeader = { "<!--" };
  151. static const char* dtdHeader = { "<!" };
  152. static const char* cdataHeader = { "<![CDATA[" };
  153. static const int xmlHeaderLen = 5;
  154. static const int commentHeaderLen = 4;
  155. static const int dtdHeaderLen = 2;
  156. static const int cdataHeaderLen = 9;
  157. if ( XMLNode::StringEqual( p, commentHeader, commentHeaderLen ) ) {
  158. returnNode = new XMLComment( this );
  159. p += commentHeaderLen;
  160. }
  161. else {
  162. TIXMLASSERT( 0 );
  163. }
  164. *node = returnNode;
  165. return p;
  166. }