diff --git a/tinyxml2.cpp b/tinyxml2.cpp index f45ae74..2241fd2 100644 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -344,6 +344,51 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) } +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + if ( firstChild ) { + TIXMLASSERT( lastChild ); + TIXMLASSERT( firstChild->prev == 0 ); + + firstChild->prev = addThis; + addThis->next = firstChild; + firstChild = addThis; + + addThis->parent = this; + addThis->prev = 0; + } + else { + TIXMLASSERT( lastChild == 0 ); + firstChild = lastChild = addThis; + + addThis->parent = this; + addThis->prev = 0; + addThis->next = 0; + } + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( afterThis->parent == this ); + if ( afterThis->parent != this ) + return 0; + + if ( afterThis->next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + addThis->prev = afterThis; + addThis->next = afterThis->next; + afterThis->next->prev = addThis; + afterThis->next = addThis; + return addThis; +} + + + + const XMLElement* XMLNode::FirstChildElement( const char* value ) const { for( XMLNode* node=firstChild; node; node=node->next ) { @@ -510,6 +555,70 @@ char* XMLAttribute::ParseDeep( char* p ) } +int XMLAttribute::QueryIntAttribute( int* value ) const +{ + if ( TIXML_SSCANF( Value(), "%d", value ) == 1 ) + return ATTRIBUTE_SUCCESS; + return WRONG_ATTRIBUTE_TYPE; +} + + +int XMLAttribute::QueryUnsignedAttribute( unsigned int* value ) const +{ + if ( TIXML_SSCANF( Value(), "%u", value ) == 1 ) + return ATTRIBUTE_SUCCESS; + return WRONG_ATTRIBUTE_TYPE; +} + + +int XMLAttribute::QueryBoolAttribute( bool* value ) const +{ + int ival = -1; + QueryIntAttribute( &ival ); + + if ( ival > 0 || XMLUtil::StringEqual( Value(), "true" ) ) { + *value = true; + return ATTRIBUTE_SUCCESS; + } + else if ( ival == 0 || XMLUtil::StringEqual( Value(), "false" ) ) { + *value = false; + return ATTRIBUTE_SUCCESS; + } + return WRONG_ATTRIBUTE_TYPE; +} + + +int XMLAttribute::QueryDoubleAttribute( double* value ) const +{ + if ( TIXML_SSCANF( Value(), "%lf", value ) == 1 ) + return ATTRIBUTE_SUCCESS; + return WRONG_ATTRIBUTE_TYPE; +} + + +int XMLAttribute::QueryFloatAttribute( float* value ) const +{ + if ( TIXML_SSCANF( Value(), "%f", value ) == 1 ) + return ATTRIBUTE_SUCCESS; + return WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + value.SetInternedStr( v ); +} + + +/* +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + TIXML_SNPRINTF( buf, BUF_SIZE-1, "%d" ); + + value.SetInternedStr( v ); +} +*/ // --------- XMLElement ---------- // XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), @@ -683,6 +792,25 @@ XMLElement* XMLDocument::NewElement( const char* name ) } +XMLComment* XMLDocument::NewComment( const char* str ) +{ + XMLComment* comment = new (commentPool.Alloc()) XMLComment( this ); + comment->memPool = &commentPool; + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + XMLText* Text = new (textPool.Alloc()) XMLText( this ); + Text->memPool = &textPool; + Text->SetValue( str ); + return Text; +} + + + int XMLDocument::Parse( const char* p ) { ClearChildren(); diff --git a/tinyxml2.h b/tinyxml2.h index 066e38d..0cf859b 100644 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -13,7 +13,11 @@ X hide copy constructor X hide = operator X UTF8 support: isAlpha, etc. + - string buffer for sets. (Grr.) + - MS BOM + - print to memory buffer - tests from xml1 + - xml1 tests especially UTF-8 - perf test: xml1 - perf test: xenowar */ @@ -45,6 +49,31 @@ #endif +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s +#elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf +#else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf +#endif + + namespace tinyxml2 { class XMLDocument; @@ -365,8 +394,20 @@ public: const XMLNode* NextSiblingElement( const char* value=0 ) const; XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast(const_cast(this)->NextSiblingElement( value ) ); } + /** + + Tests: Programmatic DOM + */ XMLNode* InsertEndChild( XMLNode* addThis ); + /** + + Tests: Programmatic DOM + */ XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + + Tests: Programmatic DOM + */ XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); void ClearChildren(); @@ -485,6 +526,13 @@ protected: }; +enum { + ATTRIBUTE_SUCCESS, + NO_ATTRIBUTE, + WRONG_ATTRIBUTE_TYPE +}; + + class XMLAttribute { friend class XMLElement; @@ -493,17 +541,21 @@ public: const char* Value() const { return value.GetStr(); } const XMLAttribute* Next() const { return next; } - int QueryIntAttribute( const char* name, int* value ) const; - int QueryUnsignedAttribute( const char* name, unsigned int* value ) const; - int QueryBoolAttribute( const char* name, bool* value ) const; - int QueryDoubleAttribute( const char* name, double* _value ) const; - int QueryFloatAttribute( const char* name, float* _value ) const; + int QueryIntAttribute( int* value ) const; + int QueryUnsignedAttribute( unsigned int* value ) const; + int QueryBoolAttribute( bool* value ) const; + int QueryDoubleAttribute( double* value ) const; + int QueryFloatAttribute( float* value ) const; - void SetAttribute( const char* name, const char* value ); - void SetAttribute( const char* name, int value ); - void SetAttribute( const char* name, unsigned value ); - void SetAttribute( const char* name, bool value ); - void SetAttribute( const char* name, double value ); + void SetAttribute( const char* value ); + + // NOTE: other sets aren't supported...need to deal with memory model? + /* + void SetAttribute( int value ); + void SetAttribute( unsigned value ); + void SetAttribute( bool value ); + void SetAttribute( double value ); + */ private: XMLAttribute( XMLElement* element ) : next( 0 ) {} @@ -587,7 +639,18 @@ public: void Print( XMLStreamer* streamer=0 ); virtual bool Accept( XMLVisitor* visitor ) const; + /** + Testing: Programmatic DOM + */ XMLElement* NewElement( const char* name ); + /** + Testing: Programmatic DOM + */ + XMLComment* NewComment( const char* comment ); + /** + Testing: Programmatic DOM + */ + XMLText* NewText( const char* text ); enum { NO_ERROR = 0, diff --git a/xmltest.cpp b/xmltest.cpp index b2c2047..cfb2183 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -4,63 +4,63 @@ #include #include -#if defined( WIN32 ) - #include - _CrtMemState startMemState; - _CrtMemState endMemState; -#endif +#if defined( WIN32 ) + #include + _CrtMemState startMemState; + _CrtMemState endMemState; +#endif using namespace tinyxml2; int gPass = 0; int gFail = 0; -bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho ) -{ - bool pass = !strcmp( expected, found ); - if ( pass ) - printf ("[pass]"); - else - printf ("[fail]"); - - if ( noEcho ) - printf (" %s\n", testString); - else - printf (" %s [%s][%s]\n", testString, expected, found); - - if ( pass ) - ++gPass; - else - ++gFail; - return pass; -} - - -bool XmlTest( const char* testString, int expected, int found, bool noEcho ) -{ - bool pass = ( expected == found ); - if ( pass ) - printf ("[pass]"); - else - printf ("[fail]"); - - if ( noEcho ) - printf (" %s\n", testString); - else - printf (" %s [%d][%d]\n", testString, expected, found); - - if ( pass ) - ++gPass; - else - ++gFail; - return pass; -} +bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho ) +{ + bool pass = !strcmp( expected, found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%s][%s]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +bool XmlTest( const char* testString, int expected, int found, bool noEcho ) +{ + bool pass = ( expected == found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%d][%d]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} int main( int argc, const char* argv ) { - #if defined( WIN32 ) - _CrtMemCheckpoint( &startMemState ); - #endif + #if defined( WIN32 ) + _CrtMemCheckpoint( &startMemState ); + #endif #if 0 { @@ -120,29 +120,40 @@ int main( int argc, const char* argv ) } #endif { + // Test: Programmatic DOM // Build: // // // // - // + // With Text! // XMLDocument* doc = new XMLDocument(); - doc->InsertEndChild( doc->NewElement( "element" ) ); + XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) ); + + XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) }; + for( int i=0; i<3; ++i ) { + sub[i]->SetAttribute( "attrib", i ); + } + element->InsertEndChild( sub[2] ); + XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) ); + element->InsertAfterChild( comment, sub[0] ); + element->InsertAfterChild( sub[0], sub[1] ); + sub[2]->InsertFirstChild( doc->NewText( "With Text!" )); doc->Print(); delete doc; } - #if defined( WIN32 ) - _CrtMemCheckpoint( &endMemState ); - //_CrtMemDumpStatistics( &endMemState ); - - _CrtMemState diffMemState; - _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); - _CrtMemDumpStatistics( &diffMemState ); - #endif - - printf ("\nPass %d, Fail %d\n", gPass, gFail); + #if defined( WIN32 ) + _CrtMemCheckpoint( &endMemState ); + //_CrtMemDumpStatistics( &endMemState ); + + _CrtMemState diffMemState; + _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); + _CrtMemDumpStatistics( &diffMemState ); + #endif + + printf ("\nPass %d, Fail %d\n", gPass, gFail); return 0; } \ No newline at end of file