diff --git a/CMakeLists.txt b/CMakeLists.txt index e9b44d5..0261048 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,9 @@ IF(BIICODE) ENDIF(BIICODE) cmake_minimum_required(VERSION 2.6 FATAL_ERROR) cmake_policy(VERSION 2.6) -if(POLICY CMP0063) - cmake_policy(SET CMP0063 OLD) -endif() +if(POLICY CMP0063) + cmake_policy(SET CMP0063 OLD) +endif() project(tinyxml2) include(GNUInstallDirs) @@ -29,25 +29,6 @@ set(GENERIC_LIB_SOVERSION "4") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/.") -################################ -# Add custom target to copy all data - -set(TARGET_DATA_COPY DATA_COPY) -set(DATA_COPY_FILES) -if(NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) - foreach(data dream.xml empty.xml utf8test.xml utf8testverify.xml) - set(DATA_COPY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources/${data}) - set(DATA_COPY_DEST ${CMAKE_CURRENT_BINARY_DIR}/resources/${data}) - add_custom_command( - OUTPUT ${DATA_COPY_DEST} - COMMAND ${CMAKE_COMMAND} - ARGS -E copy ${DATA_COPY_SRC} ${DATA_COPY_DEST} - DEPENDS ${DATA_COPY_SRC}) - list(APPEND DATA_COPY_FILES ${DATA_COPY_DEST}) - endforeach(data) -endif(NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) -add_custom_target(${TARGET_DATA_COPY} DEPENDS ${DATA_COPY_FILES}) - ################################ # Add definitions @@ -61,15 +42,21 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # Add targets # By Default shared libray is being built # To build static libs also - Do cmake . -DBUILD_STATIC_LIBS:BOOL=ON -# User can choose not to build shared library by using cmake -BUILD_SHARED_LIBS:BOOL:OFF +# User can choose not to build shared library by using cmake -DBUILD_SHARED_LIBS:BOOL=OFF # To build only static libs use cmake . -DBUILD_SHARED_LIBS:BOOL=OFF -DBUILD_STATIC_LIBS:BOOL=ON +# To build the tests, use cmake . -DBUILD_TESTS:BOOL=ON +# To disable the building of the tests, use cmake . -DBUILD_TESTS:BOOL=OFF option(BUILD_SHARED_LIBS "build as shared library" ON) option(BUILD_STATIC_LIBS "build as static library" OFF) +option(BUILD_TESTS "build xmltest" ON) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) +# to distinguish between debug and release lib +set(CMAKE_DEBUG_POSTFIX "d") + if(BUILD_SHARED_LIBS) add_library(tinyxml2 SHARED tinyxml2.cpp tinyxml2.h) @@ -106,17 +93,23 @@ install(TARGETS tinyxml2_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() -add_executable(xmltest xmltest.cpp) -if(BUILD_SHARED_LIBS) - add_dependencies(xmltest tinyxml2) - add_dependencies(xmltest ${TARGET_DATA_COPY}) - target_link_libraries(xmltest tinyxml2) -else(BUILD_STATIC_LIBS) - add_dependencies(xmltest tinyxml2_static) - add_dependencies(xmltest ${TARGET_DATA_COPY}) - target_link_libraries(xmltest tinyxml2_static) +if(BUILD_TESTS) + add_executable(xmltest xmltest.cpp) + if(BUILD_SHARED_LIBS) + add_dependencies(xmltest tinyxml2) + target_link_libraries(xmltest tinyxml2) + else(BUILD_STATIC_LIBS) + add_dependencies(xmltest tinyxml2_static) + target_link_libraries(xmltest tinyxml2_static) + endif() + + # Copy test resources and create test output directory + add_custom_command(TARGET xmltest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources $/resources + COMMAND ${CMAKE_COMMAND} -E make_directory $/resources/out + COMMENT "Configuring xmltest resources directory: ${CMAKE_BINARY_DIR}/resources" + ) endif() -install(TARGETS DESTINATION ${CMAKE_INSTALL_BINDIR}) install(FILES tinyxml2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) @@ -130,8 +123,6 @@ endforeach() configure_file(tinyxml2.pc.in tinyxml2.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/tinyxml2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -#add_test(xmltest ${SAMPLE_NAME} COMMAND $) - # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" diff --git a/appveyor.yml b/appveyor.yml index aac8867..0c60b67 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,5 +3,5 @@ before_build: build_script: - msbuild tinyxml2.sln /m /p:Configuration=Release /t:ALL_BUILD - - copy Release\xmltest.exe .\ && copy Release\tinyxml2.dll .\ + - cd Release - xmltest.exe diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 819382b..ded9d36 100755 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -368,6 +368,19 @@ const char* StrPair::GetStr() // --------- XMLUtil ----------- // +const char* XMLUtil::writeBoolTrue = "true"; +const char* XMLUtil::writeBoolFalse = "false"; + +void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) +{ + static const char* defTrue = "true"; + static const char* defFalse = "false"; + + writeBoolTrue = (writeTrue) ? writeTrue : defTrue; + writeBoolFalse = (writeFalse) ? writeFalse : defFalse; +} + + const char* XMLUtil::ReadBOM( const char* p, bool* bom ) { TIXMLASSERT( p ); @@ -545,7 +558,7 @@ void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) { - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? "true" : "false" ); + TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); } /* @@ -665,46 +678,34 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool XMLNode* returnNode = 0; if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLDeclaration( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += xmlHeaderLen; } else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += commentHeaderLen; } else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - XMLText* text = new (_textPool.Alloc()) XMLText( this ); + XMLText* text = CreateUnlinkedNode( _textPool ); returnNode = text; returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_textPool; p += cdataHeaderLen; text->SetCData( true ); } else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += dtdHeaderLen; } else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); - returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode = CreateUnlinkedNode( _elementPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_elementPool; p += elementHeaderLen; } else { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - returnNode = new (_textPool.Alloc()) XMLText( this ); - returnNode->_memPool = &_textPool; + returnNode = CreateUnlinkedNode( _textPool ); returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character p = start; // Back it up, all the text counts. _parseCurLineNum = startLine; @@ -966,7 +967,7 @@ const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const } -char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) +char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) { // This is a recursive method, but thinking about it "at the current level" // it is a pretty simple flat list: @@ -1031,8 +1032,8 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) if ( ele ) { // We read the end tag. Return it to the parent. if ( ele->ClosingType() == XMLElement::CLOSING ) { - if ( parentEnd ) { - ele->_value.TransferTo( parentEnd ); + if ( parentEndTag ) { + ele->_value.TransferTo( parentEndTag ); } node->_memPool->SetTracked(); // created and then immediately deleted. DeleteNode( node ); @@ -1144,6 +1145,7 @@ XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const bool XMLText::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLText* text = compare->ToText(); return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); } @@ -1459,7 +1461,7 @@ void XMLAttribute::SetAttribute( float v ) // --------- XMLElement ---------- // XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( 0 ), + _closingType( OPEN ), _rootAttribute( 0 ) { } @@ -1849,6 +1851,7 @@ XMLAttribute* XMLElement::CreateAttribute() { TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + TIXMLASSERT( attrib ); attrib->_memPool = &_document->_attributePool; attrib->_memPool->SetTracked(); return attrib; @@ -1858,7 +1861,7 @@ XMLAttribute* XMLElement::CreateAttribute() // // foobar // -char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr ) +char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) { // Read the element name. p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); @@ -1877,11 +1880,11 @@ char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr ) } p = ParseAttributes( p, curLineNumPtr ); - if ( !p || !*p || _closingType ) { + if ( !p || !*p || _closingType != OPEN ) { return p; } - p = XMLNode::ParseDeep( p, strPair, curLineNumPtr ); + p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); return p; } @@ -1967,12 +1970,12 @@ const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { }; -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : XMLNode( 0 ), _writeBOM( false ), _processEntities( processEntities ), _errorID(XML_SUCCESS), - _whitespace( whitespace ), + _whitespaceMode( whitespaceMode ), _errorLineNum( 0 ), _charBuffer( 0 ), _parseCurLineNum( 0 ) @@ -2031,9 +2034,7 @@ void XMLDocument::DeepCopy(XMLDocument* target) XMLElement* XMLDocument::NewElement( const char* name ) { - TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); - XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); - ele->_memPool = &_elementPool; + XMLElement* ele = CreateUnlinkedNode( _elementPool ); ele->SetName( name ); return ele; } @@ -2041,9 +2042,7 @@ XMLElement* XMLDocument::NewElement( const char* name ) XMLComment* XMLDocument::NewComment( const char* str ) { - TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); - XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); - comment->_memPool = &_commentPool; + XMLComment* comment = CreateUnlinkedNode( _commentPool ); comment->SetValue( str ); return comment; } @@ -2051,9 +2050,7 @@ XMLComment* XMLDocument::NewComment( const char* str ) XMLText* XMLDocument::NewText( const char* str ) { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - XMLText* text = new (_textPool.Alloc()) XMLText( this ); - text->_memPool = &_textPool; + XMLText* text = CreateUnlinkedNode( _textPool ); text->SetValue( str ); return text; } @@ -2061,9 +2058,7 @@ XMLText* XMLDocument::NewText( const char* str ) XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) { - TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); - XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); - dec->_memPool = &_commentPool; + XMLDeclaration* dec = CreateUnlinkedNode( _commentPool ); dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); return dec; } @@ -2071,9 +2066,7 @@ XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) XMLUnknown* XMLDocument::NewUnknown( const char* str ) { - TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); - XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); - unk->_memPool = &_commentPool; + XMLUnknown* unk = CreateUnlinkedNode( _commentPool ); unk->SetValue( str ); return unk; } diff --git a/tinyxml2.h b/tinyxml2.h index 473a6f1..c9b7124 100755 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -284,6 +284,7 @@ private: TIXMLASSERT( cap <= INT_MAX / 2 ); int newAllocated = cap * 2; T* newMem = new T[newAllocated]; + TIXMLASSERT( newAllocated >= _size ); memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs if ( _mem != _pool ) { delete [] _mem; @@ -527,7 +528,7 @@ enum XMLError { /* Utility functionality. */ -class XMLUtil +class TINYXML2_LIB XMLUtil { public: static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { @@ -605,6 +606,17 @@ public: static bool ToFloat( const char* str, float* value ); static bool ToDouble( const char* str, double* value ); static bool ToInt64(const char* str, int64_t* value); + + // Changes what is serialized for a boolean value. + // Default to "true" and "false". Shouldn't be changed + // unless you have a special testing or compatibility need. + // Be careful: static, global, & not thread safe. + // Be sure to set static const memory as parameters. + static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); + +private: + static const char* writeBoolTrue; + static const char* writeBoolFalse; }; @@ -910,7 +922,7 @@ protected: XMLNode( XMLDocument* ); virtual ~XMLNode(); - virtual char* ParseDeep( char*, StrPair*, int* ); + virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); XMLDocument* _document; XMLNode* _parent; @@ -978,7 +990,7 @@ protected: XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} virtual ~XMLText() {} - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: bool _isCData; @@ -1009,7 +1021,7 @@ protected: XMLComment( XMLDocument* doc ); virtual ~XMLComment(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); private: XMLComment( const XMLComment& ); // not supported @@ -1048,7 +1060,7 @@ protected: XMLDeclaration( XMLDocument* doc ); virtual ~XMLDeclaration(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLDeclaration( const XMLDeclaration& ); // not supported @@ -1083,7 +1095,7 @@ protected: XMLUnknown( XMLDocument* doc ); virtual ~XMLUnknown(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLUnknown( const XMLUnknown& ); // not supported @@ -1191,7 +1203,7 @@ public: private: enum { BUF_SIZE = 200 }; - XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} virtual ~XMLAttribute() {} XMLAttribute( const XMLAttribute& ); // not supported @@ -1562,19 +1574,19 @@ public: float FloatText(float defaultValue = 0) const; // internal: - enum { + enum ElementClosingType { OPEN, // CLOSED, // CLOSING // }; - int ClosingType() const { + ElementClosingType ClosingType() const { return _closingType; } virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - char* ParseDeep( char* p, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLElement( XMLDocument* doc ); @@ -1592,7 +1604,7 @@ private: XMLAttribute* CreateAttribute(); enum { BUF_SIZE = 200 }; - int _closingType; + ElementClosingType _closingType; // The attribute list is ordered; there is no 'lastAttribute' // because the list needs to be scanned for dupes before adding // a new attribute. @@ -1616,7 +1628,7 @@ class TINYXML2_LIB XMLDocument : public XMLNode friend class XMLElement; public: /// constructor - XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); ~XMLDocument(); virtual XMLDocument* ToDocument() { @@ -1680,7 +1692,7 @@ public: return _processEntities; } Whitespace WhitespaceMode() const { - return _whitespace; + return _whitespaceMode; } /** @@ -1828,7 +1840,7 @@ private: bool _writeBOM; bool _processEntities; XMLError _errorID; - Whitespace _whitespace; + Whitespace _whitespaceMode; mutable StrPair _errorStr1; mutable StrPair _errorStr2; int _errorLineNum; @@ -1843,8 +1855,21 @@ private: static const char* _errorNames[XML_ERROR_COUNT]; void Parse(); + + template + NodeType* CreateUnlinkedNode( MemPoolT& pool ); }; +template +inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT& pool ) +{ + TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); + TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); + NodeType* returnNode = new (pool.Alloc()) NodeType( this ); + TIXMLASSERT( returnNode ); + returnNode->_memPool = &pool; + return returnNode; +} /** A XMLHandle is a class that wraps a node pointer with null checks; this is diff --git a/xmltest.cpp b/xmltest.cpp index 499d626..f1dc97d 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -10,16 +10,10 @@ #include #if defined( _MSC_VER ) - #include // _mkdir #include #define WIN32_LEAN_AND_MEAN #include _CrtMemState startMemState; - _CrtMemState endMemState; -#elif defined(MINGW32) || defined(__MINGW32__) - #include // mkdir -#else - #include // mkdir #endif using namespace tinyxml2; @@ -299,17 +293,6 @@ int main( int argc, const char ** argv ) _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); #endif - #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__) - #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR - //MINGW64: both 32 and 64-bit - mkdir( "resources/out/" ); - #else - _mkdir( "resources/out/" ); - #endif - #else - mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - #endif - { TIXMLASSERT( true ); } @@ -752,6 +735,18 @@ int main( int argc, const char ** argv ) XMLTest("Attribute: bool", true, v, true); XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true); } + { + element->SetAttribute("attrib", true); + const char* result = element->Attribute("attrib"); + XMLTest("Bool true is 'true'", "true", result); + + XMLUtil::SetBoolSerialization("1", "0"); + element->SetAttribute("attrib", true); + result = element->Attribute("attrib"); + XMLTest("Bool true is '1'", "1", result); + + XMLUtil::SetBoolSerialization(0, 0); + } { element->SetAttribute("attrib", 100.0); double v = 0;