tinyxml2.cpp 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. #include "tinyxml2.h"
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <new.h>
  7. //#pragma warning ( disable : 4291 )
  8. using namespace tinyxml2;
  9. static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF
  10. static const char LF = LINE_FEED;
  11. static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
  12. static const char CR = CARRIAGE_RETURN;
  13. static const char SINGLE_QUOTE = '\'';
  14. static const char DOUBLE_QUOTE = '\"';
  15. #define DELETE_NODE( node ) { MemPool* pool = node->memPool; node->~XMLNode(); pool->Free( node ); }
  16. #define DELETE_ATTRIBUTE( attrib ) { MemPool* pool = attrib->memPool; attrib->~XMLAttribute(); pool->Free( attrib ); }
  17. struct Entity {
  18. const char* pattern;
  19. int length;
  20. char value;
  21. };
  22. static const int NUM_ENTITIES = 5;
  23. static const Entity entities[NUM_ENTITIES] =
  24. {
  25. { "quot", 4, DOUBLE_QUOTE },
  26. { "amp", 3, '&' },
  27. { "apos", 4, SINGLE_QUOTE },
  28. { "lt", 2, '<' },
  29. { "gt", 2, '>' }
  30. };
  31. StrPair::~StrPair()
  32. {
  33. Reset();
  34. }
  35. void StrPair::Reset()
  36. {
  37. if ( flags & NEEDS_DELETE ) {
  38. delete [] start;
  39. }
  40. flags = 0;
  41. start = 0;
  42. end = 0;
  43. }
  44. void StrPair::SetStr( const char* str, int flags )
  45. {
  46. Reset();
  47. size_t len = strlen( str );
  48. start = new char[ len+1 ];
  49. memcpy( start, str, len+1 );
  50. end = start + len;
  51. this->flags = flags | NEEDS_DELETE;
  52. }
  53. char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
  54. {
  55. TIXMLASSERT( endTag && *endTag );
  56. char* start = p; // fixme: hides a member
  57. char endChar = *endTag;
  58. int length = strlen( endTag );
  59. // Inner loop of text parsing.
  60. while ( *p ) {
  61. if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
  62. Set( start, p, strFlags );
  63. return p + length;
  64. }
  65. ++p;
  66. }
  67. return p;
  68. }
  69. char* StrPair::ParseName( char* p )
  70. {
  71. char* start = p;
  72. start = p;
  73. if ( !start || !(*start) ) {
  74. return 0;
  75. }
  76. if ( !XMLUtil::IsAlpha( *p ) ) {
  77. return 0;
  78. }
  79. while( *p && (
  80. XMLUtil::IsAlphaNum( (unsigned char) *p )
  81. || *p == '_'
  82. || *p == '-'
  83. || *p == '.'
  84. || *p == ':' ))
  85. {
  86. ++p;
  87. }
  88. if ( p > start ) {
  89. Set( start, p, 0 );
  90. return p;
  91. }
  92. return 0;
  93. }
  94. const char* StrPair::GetStr()
  95. {
  96. if ( flags & NEEDS_FLUSH ) {
  97. *end = 0;
  98. flags ^= NEEDS_FLUSH;
  99. if ( flags ) {
  100. char* p = start;
  101. char* q = start;
  102. while( p < end ) {
  103. if ( (flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
  104. // CR-LF pair becomes LF
  105. // CR alone becomes LF
  106. // LF-CR becomes LF
  107. if ( *(p+1) == LF ) {
  108. p += 2;
  109. }
  110. else {
  111. ++p;
  112. }
  113. *q++ = LF;
  114. }
  115. else if ( (flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
  116. if ( *(p+1) == CR ) {
  117. p += 2;
  118. }
  119. else {
  120. ++p;
  121. }
  122. *q++ = LF;
  123. }
  124. else if ( (flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
  125. int i=0;
  126. for( i=0; i<NUM_ENTITIES; ++i ) {
  127. if ( strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
  128. && *(p+entities[i].length+1) == ';' )
  129. {
  130. // Found an entity convert;
  131. *q = entities[i].value;
  132. ++q;
  133. p += entities[i].length + 2;
  134. break;
  135. }
  136. }
  137. if ( i == NUM_ENTITIES ) {
  138. // fixme: treat as error?
  139. ++p;
  140. ++q;
  141. }
  142. }
  143. else {
  144. *q = *p;
  145. ++p;
  146. ++q;
  147. }
  148. }
  149. *q = 0;
  150. }
  151. flags = (flags & NEEDS_DELETE);
  152. }
  153. return start;
  154. }
  155. // --------- XMLUtil ----------- //
  156. char* XMLDocument::Identify( char* p, XMLNode** node )
  157. {
  158. XMLNode* returnNode = 0;
  159. char* start = p;
  160. p = XMLUtil::SkipWhiteSpace( p );
  161. if( !p || !*p )
  162. {
  163. return 0;
  164. }
  165. // What is this thing?
  166. // - Elements start with a letter or underscore, but xml is reserved.
  167. // - Comments: <!--
  168. // - Decleration: <?xml
  169. // - Everthing else is unknown to tinyxml.
  170. //
  171. static const char* xmlHeader = { "<?xml" };
  172. static const char* commentHeader = { "<!--" };
  173. static const char* dtdHeader = { "<!" };
  174. static const char* cdataHeader = { "<![CDATA[" };
  175. static const char* elementHeader = { "<" }; // and a header for everything else; check last.
  176. static const int xmlHeaderLen = 5;
  177. static const int commentHeaderLen = 4;
  178. static const int dtdHeaderLen = 2;
  179. static const int cdataHeaderLen = 9;
  180. static const int elementHeaderLen = 1;
  181. TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
  182. TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
  183. if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
  184. returnNode = new (commentPool.Alloc()) XMLDeclaration( this );
  185. returnNode->memPool = &commentPool;
  186. p += xmlHeaderLen;
  187. }
  188. else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
  189. returnNode = new (commentPool.Alloc()) XMLComment( this );
  190. returnNode->memPool = &commentPool;
  191. p += commentHeaderLen;
  192. }
  193. else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
  194. XMLText* text = new (textPool.Alloc()) XMLText( this );
  195. returnNode = text;
  196. returnNode->memPool = &textPool;
  197. p += cdataHeaderLen;
  198. text->SetCData( true );
  199. }
  200. else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
  201. returnNode = new (commentPool.Alloc()) XMLUnknown( this );
  202. returnNode->memPool = &commentPool;
  203. p += dtdHeaderLen;
  204. }
  205. else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
  206. returnNode = new (elementPool.Alloc()) XMLElement( this );
  207. returnNode->memPool = &elementPool;
  208. p += elementHeaderLen;
  209. }
  210. else if ( (*p != '<') && XMLUtil::IsAlphaNum( *p ) ) {
  211. returnNode = new (textPool.Alloc()) XMLText( this );
  212. returnNode->memPool = &textPool;
  213. p = start; // Back it up, all the text counts.
  214. }
  215. else {
  216. this->SetError( ERROR_IDENTIFYING_TAG, p, 0 );
  217. p = 0;
  218. returnNode = 0;
  219. }
  220. *node = returnNode;
  221. return p;
  222. }
  223. bool XMLDocument::Accept( XMLVisitor* visitor ) const
  224. {
  225. if ( visitor->VisitEnter( *this ) )
  226. {
  227. for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
  228. {
  229. if ( !node->Accept( visitor ) )
  230. break;
  231. }
  232. }
  233. return visitor->VisitExit( *this );
  234. }
  235. // --------- XMLNode ----------- //
  236. XMLNode::XMLNode( XMLDocument* doc ) :
  237. document( doc ),
  238. parent( 0 ),
  239. firstChild( 0 ), lastChild( 0 ),
  240. prev( 0 ), next( 0 )
  241. {
  242. }
  243. XMLNode::~XMLNode()
  244. {
  245. ClearChildren();
  246. if ( parent ) {
  247. parent->Unlink( this );
  248. }
  249. }
  250. void XMLNode::SetValue( const char* str, bool staticMem )
  251. {
  252. if ( staticMem )
  253. value.SetInternedStr( str );
  254. else
  255. value.SetStr( str );
  256. }
  257. void XMLNode::ClearChildren()
  258. {
  259. while( firstChild ) {
  260. XMLNode* node = firstChild;
  261. Unlink( node );
  262. DELETE_NODE( node );
  263. }
  264. firstChild = lastChild = 0;
  265. }
  266. void XMLNode::Unlink( XMLNode* child )
  267. {
  268. TIXMLASSERT( child->parent == this );
  269. if ( child == firstChild )
  270. firstChild = firstChild->next;
  271. if ( child == lastChild )
  272. lastChild = lastChild->prev;
  273. if ( child->prev ) {
  274. child->prev->next = child->next;
  275. }
  276. if ( child->next ) {
  277. child->next->prev = child->prev;
  278. }
  279. child->parent = 0;
  280. }
  281. XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
  282. {
  283. if ( lastChild ) {
  284. TIXMLASSERT( firstChild );
  285. TIXMLASSERT( lastChild->next == 0 );
  286. lastChild->next = addThis;
  287. addThis->prev = lastChild;
  288. lastChild = addThis;
  289. addThis->next = 0;
  290. }
  291. else {
  292. TIXMLASSERT( firstChild == 0 );
  293. firstChild = lastChild = addThis;
  294. addThis->prev = 0;
  295. addThis->next = 0;
  296. }
  297. addThis->parent = this;
  298. return addThis;
  299. }
  300. XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
  301. {
  302. if ( firstChild ) {
  303. TIXMLASSERT( lastChild );
  304. TIXMLASSERT( firstChild->prev == 0 );
  305. firstChild->prev = addThis;
  306. addThis->next = firstChild;
  307. firstChild = addThis;
  308. addThis->prev = 0;
  309. }
  310. else {
  311. TIXMLASSERT( lastChild == 0 );
  312. firstChild = lastChild = addThis;
  313. addThis->prev = 0;
  314. addThis->next = 0;
  315. }
  316. addThis->parent = this;
  317. return addThis;
  318. }
  319. XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
  320. {
  321. TIXMLASSERT( afterThis->parent == this );
  322. if ( afterThis->parent != this )
  323. return 0;
  324. if ( afterThis->next == 0 ) {
  325. // The last node or the only node.
  326. return InsertEndChild( addThis );
  327. }
  328. addThis->prev = afterThis;
  329. addThis->next = afterThis->next;
  330. afterThis->next->prev = addThis;
  331. afterThis->next = addThis;
  332. addThis->parent = this;
  333. return addThis;
  334. }
  335. const XMLElement* XMLNode::FirstChildElement( const char* value ) const
  336. {
  337. for( XMLNode* node=firstChild; node; node=node->next ) {
  338. XMLElement* element = node->ToElement();
  339. if ( element ) {
  340. if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
  341. return element;
  342. }
  343. }
  344. }
  345. return 0;
  346. }
  347. const XMLElement* XMLNode::LastChildElement( const char* value ) const
  348. {
  349. for( XMLNode* node=lastChild; node; node=node->prev ) {
  350. XMLElement* element = node->ToElement();
  351. if ( element ) {
  352. if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) {
  353. return element;
  354. }
  355. }
  356. }
  357. return 0;
  358. }
  359. void XMLNode::DeleteChild( XMLNode* node )
  360. {
  361. TIXMLASSERT( node->parent == this );
  362. TIXMLASSERT( 0 );
  363. }
  364. char* XMLNode::ParseDeep( char* p )
  365. {
  366. while( p && *p ) {
  367. XMLNode* node = 0;
  368. p = document->Identify( p, &node );
  369. if ( p && node ) {
  370. p = node->ParseDeep( p );
  371. // FIXME: is it the correct closing element?
  372. if ( node->IsClosingElement() ) {
  373. DELETE_NODE( node );
  374. return p;
  375. }
  376. this->InsertEndChild( node );
  377. }
  378. }
  379. return 0;
  380. }
  381. // --------- XMLText ---------- //
  382. char* XMLText::ParseDeep( char* p )
  383. {
  384. if ( this->CData() ) {
  385. p = value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
  386. return p;
  387. }
  388. else {
  389. p = value.ParseText( p, "<", StrPair::TEXT_ELEMENT );
  390. // consumes the end tag.
  391. if ( p && *p ) {
  392. return p-1;
  393. }
  394. }
  395. return 0;
  396. }
  397. bool XMLText::Accept( XMLVisitor* visitor ) const
  398. {
  399. return visitor->Visit( *this );
  400. }
  401. // --------- XMLComment ---------- //
  402. XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
  403. {
  404. }
  405. XMLComment::~XMLComment()
  406. {
  407. //printf( "~XMLComment\n" );
  408. }
  409. char* XMLComment::ParseDeep( char* p )
  410. {
  411. // Comment parses as text.
  412. return value.ParseText( p, "-->", StrPair::COMMENT );
  413. }
  414. bool XMLComment::Accept( XMLVisitor* visitor ) const
  415. {
  416. return visitor->Visit( *this );
  417. }
  418. // --------- XMLDeclaration ---------- //
  419. XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
  420. {
  421. }
  422. XMLDeclaration::~XMLDeclaration()
  423. {
  424. //printf( "~XMLDeclaration\n" );
  425. }
  426. char* XMLDeclaration::ParseDeep( char* p )
  427. {
  428. // Declaration parses as text.
  429. return value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
  430. }
  431. bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
  432. {
  433. return visitor->Visit( *this );
  434. }
  435. // --------- XMLUnknown ---------- //
  436. XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
  437. {
  438. }
  439. XMLUnknown::~XMLUnknown()
  440. {
  441. }
  442. char* XMLUnknown::ParseDeep( char* p )
  443. {
  444. // Unknown parses as text.
  445. return value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
  446. }
  447. bool XMLUnknown::Accept( XMLVisitor* visitor ) const
  448. {
  449. return visitor->Visit( *this );
  450. }
  451. // --------- XMLAttribute ---------- //
  452. char* XMLAttribute::ParseDeep( char* p )
  453. {
  454. p = name.ParseText( p, "=", StrPair::ATTRIBUTE_NAME );
  455. if ( !p || !*p ) return 0;
  456. char endTag[2] = { *p, 0 };
  457. ++p;
  458. p = value.ParseText( p, endTag, StrPair::ATTRIBUTE_VALUE );
  459. if ( value.Empty() ) return 0;
  460. return p;
  461. }
  462. void XMLAttribute::SetName( const char* n )
  463. {
  464. name.SetStr( n );
  465. }
  466. int XMLAttribute::QueryIntAttribute( int* value ) const
  467. {
  468. if ( TIXML_SSCANF( Value(), "%d", value ) == 1 )
  469. return ATTRIBUTE_SUCCESS;
  470. return WRONG_ATTRIBUTE_TYPE;
  471. }
  472. int XMLAttribute::QueryUnsignedAttribute( unsigned int* value ) const
  473. {
  474. if ( TIXML_SSCANF( Value(), "%u", value ) == 1 )
  475. return ATTRIBUTE_SUCCESS;
  476. return WRONG_ATTRIBUTE_TYPE;
  477. }
  478. int XMLAttribute::QueryBoolAttribute( bool* value ) const
  479. {
  480. int ival = -1;
  481. QueryIntAttribute( &ival );
  482. if ( ival > 0 || XMLUtil::StringEqual( Value(), "true" ) ) {
  483. *value = true;
  484. return ATTRIBUTE_SUCCESS;
  485. }
  486. else if ( ival == 0 || XMLUtil::StringEqual( Value(), "false" ) ) {
  487. *value = false;
  488. return ATTRIBUTE_SUCCESS;
  489. }
  490. return WRONG_ATTRIBUTE_TYPE;
  491. }
  492. int XMLAttribute::QueryDoubleAttribute( double* value ) const
  493. {
  494. if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 )
  495. return ATTRIBUTE_SUCCESS;
  496. return WRONG_ATTRIBUTE_TYPE;
  497. }
  498. int XMLAttribute::QueryFloatAttribute( float* value ) const
  499. {
  500. if ( TIXML_SSCANF( Value(), "%f", value ) == 1 )
  501. return ATTRIBUTE_SUCCESS;
  502. return WRONG_ATTRIBUTE_TYPE;
  503. }
  504. void XMLAttribute::SetAttribute( const char* v )
  505. {
  506. value.SetStr( v );
  507. }
  508. void XMLAttribute::SetAttribute( int v )
  509. {
  510. char buf[BUF_SIZE];
  511. TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v );
  512. value.SetStr( buf );
  513. }
  514. void XMLAttribute::SetAttribute( unsigned v )
  515. {
  516. char buf[BUF_SIZE];
  517. TIXML_SNPRINTF( buf, BUF_SIZE-1, "%u", v );
  518. value.SetStr( buf );
  519. }
  520. void XMLAttribute::SetAttribute( bool v )
  521. {
  522. char buf[BUF_SIZE];
  523. TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d", v ? 1 : 0 );
  524. value.SetStr( buf );
  525. }
  526. void XMLAttribute::SetAttribute( double v )
  527. {
  528. char buf[BUF_SIZE];
  529. TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v );
  530. value.SetStr( buf );
  531. }
  532. void XMLAttribute::SetAttribute( float v )
  533. {
  534. char buf[BUF_SIZE];
  535. TIXML_SNPRINTF( buf, BUF_SIZE-1, "%f", v );
  536. value.SetStr( buf );
  537. }
  538. // --------- XMLElement ---------- //
  539. XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
  540. closing( false ),
  541. rootAttribute( 0 )
  542. //lastAttribute( 0 )
  543. {
  544. }
  545. XMLElement::~XMLElement()
  546. {
  547. while( rootAttribute ) {
  548. XMLAttribute* next = rootAttribute->next;
  549. DELETE_ATTRIBUTE( rootAttribute );
  550. rootAttribute = next;
  551. }
  552. }
  553. XMLAttribute* XMLElement::FindAttribute( const char* name )
  554. {
  555. XMLAttribute* a = 0;
  556. for( a=rootAttribute; a; a = a->next ) {
  557. if ( XMLUtil::StringEqual( a->Name(), name ) )
  558. return a;
  559. }
  560. return 0;
  561. }
  562. const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
  563. {
  564. XMLAttribute* a = 0;
  565. for( a=rootAttribute; a; a = a->next ) {
  566. if ( XMLUtil::StringEqual( a->Name(), name ) )
  567. return a;
  568. }
  569. return 0;
  570. }
  571. XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
  572. {
  573. XMLAttribute* attrib = FindAttribute( name );
  574. if ( !attrib ) {
  575. attrib = new (document->attributePool.Alloc() ) XMLAttribute( this );
  576. attrib->memPool = &document->attributePool;
  577. LinkAttribute( attrib );
  578. attrib->SetName( name );
  579. }
  580. return attrib;
  581. }
  582. void XMLElement::LinkAttribute( XMLAttribute* attrib )
  583. {
  584. if ( rootAttribute ) {
  585. XMLAttribute* end = rootAttribute;
  586. while ( end->next )
  587. end = end->next;
  588. end->next = attrib;
  589. }
  590. else {
  591. rootAttribute = attrib;
  592. }
  593. }
  594. char* XMLElement::ParseAttributes( char* p, bool* closedElement )
  595. {
  596. const char* start = p;
  597. *closedElement = false;
  598. // Read the attributes.
  599. while( p ) {
  600. p = XMLUtil::SkipWhiteSpace( p );
  601. if ( !p || !(*p) ) {
  602. document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, Name() );
  603. return 0;
  604. }
  605. // attribute.
  606. if ( XMLUtil::IsAlpha( *p ) ) {
  607. XMLAttribute* attrib = new (document->attributePool.Alloc() ) XMLAttribute( this );
  608. attrib->memPool = &document->attributePool;
  609. p = attrib->ParseDeep( p );
  610. if ( !p ) {
  611. DELETE_ATTRIBUTE( attrib );
  612. document->SetError( XMLDocument::ERROR_PARSING_ATTRIBUTE, start, p );
  613. return 0;
  614. }
  615. LinkAttribute( attrib );
  616. }
  617. // end of the tag
  618. else if ( *p == '/' && *(p+1) == '>' ) {
  619. if ( closing ) {
  620. document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
  621. return 0;
  622. }
  623. *closedElement = true;
  624. return p+2; // done; sealed element.
  625. }
  626. // end of the tag
  627. else if ( *p == '>' ) {
  628. ++p;
  629. break;
  630. }
  631. else {
  632. document->SetError( XMLDocument::ERROR_PARSING_ELEMENT, start, p );
  633. return 0;
  634. }
  635. }
  636. return p;
  637. }
  638. //
  639. // <ele></ele>
  640. // <ele>foo<b>bar</b></ele>
  641. //
  642. char* XMLElement::ParseDeep( char* p )
  643. {
  644. // Read the element name.
  645. p = XMLUtil::SkipWhiteSpace( p );
  646. if ( !p ) return 0;
  647. const char* start = p;
  648. // The closing element is the </element> form. It is
  649. // parsed just like a regular element then deleted from
  650. // the DOM.
  651. if ( *p == '/' ) {
  652. closing = true;
  653. ++p;
  654. }
  655. p = value.ParseName( p );
  656. if ( value.Empty() ) return 0;
  657. bool elementClosed=false;
  658. p = ParseAttributes( p, &elementClosed );
  659. if ( !p || !*p || elementClosed || closing )
  660. return p;
  661. p = XMLNode::ParseDeep( p );
  662. return p;
  663. }
  664. bool XMLElement::Accept( XMLVisitor* visitor ) const
  665. {
  666. if ( visitor->VisitEnter( *this, rootAttribute ) )
  667. {
  668. for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() )
  669. {
  670. if ( !node->Accept( visitor ) )
  671. break;
  672. }
  673. }
  674. return visitor->VisitExit( *this );
  675. }
  676. // --------- XMLDocument ----------- //
  677. XMLDocument::XMLDocument() :
  678. XMLNode( 0 ),
  679. charBuffer( 0 )
  680. {
  681. document = this; // avoid warning about 'this' in initializer list
  682. }
  683. XMLDocument::~XMLDocument()
  684. {
  685. ClearChildren();
  686. delete [] charBuffer;
  687. #if 0
  688. textPool.Trace( "text" );
  689. elementPool.Trace( "element" );
  690. commentPool.Trace( "comment" );
  691. attributePool.Trace( "attribute" );
  692. #endif
  693. TIXMLASSERT( textPool.CurrentAllocs() == 0 );
  694. TIXMLASSERT( elementPool.CurrentAllocs() == 0 );
  695. TIXMLASSERT( commentPool.CurrentAllocs() == 0 );
  696. TIXMLASSERT( attributePool.CurrentAllocs() == 0 );
  697. }
  698. void XMLDocument::InitDocument()
  699. {
  700. errorID = NO_ERROR;
  701. errorStr1 = 0;
  702. errorStr2 = 0;
  703. delete [] charBuffer;
  704. charBuffer = 0;
  705. }
  706. XMLElement* XMLDocument::NewElement( const char* name )
  707. {
  708. XMLElement* ele = new (elementPool.Alloc()) XMLElement( this );
  709. ele->memPool = &elementPool;
  710. ele->SetName( name );
  711. return ele;
  712. }
  713. XMLComment* XMLDocument::NewComment( const char* str )
  714. {
  715. XMLComment* comment = new (commentPool.Alloc()) XMLComment( this );
  716. comment->memPool = &commentPool;
  717. comment->SetValue( str );
  718. return comment;
  719. }
  720. XMLText* XMLDocument::NewText( const char* str )
  721. {
  722. XMLText* text = new (textPool.Alloc()) XMLText( this );
  723. text->memPool = &textPool;
  724. text->SetValue( str );
  725. return text;
  726. }
  727. int XMLDocument::Parse( const char* p )
  728. {
  729. ClearChildren();
  730. InitDocument();
  731. if ( !p || !*p ) {
  732. return true; // correctly parse an empty string?
  733. }
  734. size_t len = strlen( p );
  735. charBuffer = new char[ len+1 ];
  736. memcpy( charBuffer, p, len+1 );
  737. XMLNode* node = 0;
  738. char* q = ParseDeep( charBuffer );
  739. return errorID;
  740. }
  741. void XMLDocument::Print( XMLStreamer* streamer )
  742. {
  743. XMLStreamer stdStreamer( stdout );
  744. if ( !streamer )
  745. streamer = &stdStreamer;
  746. //for( XMLNode* node = firstChild; node; node=node->next ) {
  747. // node->Print( streamer );
  748. //}
  749. Accept( streamer );
  750. }
  751. void XMLDocument::SetError( int error, const char* str1, const char* str2 )
  752. {
  753. errorID = error;
  754. printf( "ERROR: id=%d '%s' '%s'\n", error, str1, str2 ); // fixme: remove
  755. errorStr1 = str1;
  756. errorStr2 = str2;
  757. }
  758. XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false ), textDepth( -1 )
  759. {
  760. for( int i=0; i<ENTITY_RANGE; ++i ) {
  761. entityFlag[i] = false;
  762. }
  763. for( int i=0; i<NUM_ENTITIES; ++i ) {
  764. TIXMLASSERT( entities[i].value < ENTITY_RANGE );
  765. if ( entities[i].value < ENTITY_RANGE ) {
  766. entityFlag[ entities[i].value ] = true;
  767. }
  768. }
  769. }
  770. void XMLStreamer::PrintSpace( int depth )
  771. {
  772. for( int i=0; i<depth; ++i ) {
  773. fprintf( fp, " " );
  774. }
  775. }
  776. void XMLStreamer::PrintString( const char* p )
  777. {
  778. // Look for runs of bytes between entities to print.
  779. const char* q = p;
  780. while ( *q ) {
  781. if ( *q < ENTITY_RANGE ) {
  782. // Check for entities. If one is found, flush
  783. // the stream up until the entity, write the
  784. // entity, and keep looking.
  785. if ( entityFlag[*q] ) {
  786. while ( p < q ) {
  787. fputc( *p, fp );
  788. ++p;
  789. }
  790. for( int i=0; i<NUM_ENTITIES; ++i ) {
  791. if ( entities[i].value == *q ) {
  792. fprintf( fp, "&%s;", entities[i].pattern );
  793. break;
  794. }
  795. }
  796. ++p;
  797. }
  798. }
  799. ++q;
  800. }
  801. // Flush the remaining string. This will be the entire
  802. // string if an entity wasn't found.
  803. if ( q-p > 0 ) {
  804. fprintf( fp, "%s", p );
  805. }
  806. }
  807. void XMLStreamer::OpenElement( const char* name )
  808. {
  809. if ( elementJustOpened ) {
  810. SealElement();
  811. }
  812. stack.Push( name );
  813. if ( textDepth < 0 && depth > 0) {
  814. fprintf( fp, "\n" );
  815. PrintSpace( depth );
  816. }
  817. fprintf( fp, "<%s", name );
  818. elementJustOpened = true;
  819. ++depth;
  820. }
  821. void XMLStreamer::PushAttribute( const char* name, const char* value )
  822. {
  823. TIXMLASSERT( elementJustOpened );
  824. fprintf( fp, " %s=\"", name );
  825. PrintString( value );
  826. fprintf( fp, "\"" );
  827. }
  828. void XMLStreamer::CloseElement()
  829. {
  830. --depth;
  831. const char* name = stack.Pop();
  832. if ( elementJustOpened ) {
  833. fprintf( fp, "/>" );
  834. }
  835. else {
  836. if ( textDepth < 0 ) {
  837. fprintf( fp, "\n" );
  838. PrintSpace( depth );
  839. }
  840. fprintf( fp, "</%s>", name );
  841. }
  842. if ( textDepth == depth )
  843. textDepth = -1;
  844. if ( depth == 0 )
  845. fprintf( fp, "\n" );
  846. elementJustOpened = false;
  847. }
  848. void XMLStreamer::SealElement()
  849. {
  850. elementJustOpened = false;
  851. fprintf( fp, ">" );
  852. }
  853. void XMLStreamer::PushText( const char* text, bool cdata )
  854. {
  855. textDepth = depth-1;
  856. if ( elementJustOpened ) {
  857. SealElement();
  858. }
  859. if ( cdata )
  860. fprintf( fp, "<![CDATA[" );
  861. PrintString( text );
  862. if ( cdata )
  863. fprintf( fp, "]]>" );
  864. }
  865. void XMLStreamer::PushComment( const char* comment )
  866. {
  867. if ( elementJustOpened ) {
  868. SealElement();
  869. }
  870. if ( textDepth < 0 && depth > 0) {
  871. fprintf( fp, "\n" );
  872. PrintSpace( depth );
  873. }
  874. fprintf( fp, "<!--%s-->", comment );
  875. }
  876. bool XMLStreamer::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
  877. {
  878. OpenElement( element.Name() );
  879. while ( attribute ) {
  880. PushAttribute( attribute->Name(), attribute->Value() );
  881. attribute = attribute->Next();
  882. }
  883. return true;
  884. }
  885. bool XMLStreamer::VisitExit( const XMLElement& element )
  886. {
  887. CloseElement();
  888. return true;
  889. }
  890. bool XMLStreamer::Visit( const XMLText& text )
  891. {
  892. PushText( text.Value() );
  893. return true;
  894. }
  895. bool XMLStreamer::Visit( const XMLComment& comment )
  896. {
  897. PushComment( comment.Value() );
  898. return true;
  899. }