Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

Lee Thomason 12 anni fa
parent
commit
7de26f7dc7
6 ha cambiato i file con 273 aggiunte e 53 eliminazioni
  1. 3 2
      CMakeLists.txt
  2. 1 1
      dox
  3. 7 7
      readme.md
  4. 65 9
      tinyxml2.cpp
  5. 80 6
      tinyxml2.h
  6. 117 28
      xmltest.cpp

+ 3 - 2
CMakeLists.txt

@@ -10,8 +10,8 @@ include(GNUInstallDirs)
 ################################
 # set lib version here
 
-set(GENERIC_LIB_VERSION "1.0.12")
-set(GENERIC_LIB_SOVERSION "1")
+set(GENERIC_LIB_VERSION "1.0.14")
+set(GENERIC_LIB_SOVERSION "1")
 
 
 ################################
@@ -53,6 +53,7 @@ if(BUILD_STATIC_LIBS)
 endif(BUILD_STATIC_LIBS)
 add_library(tinyxml2 SHARED tinyxml2.cpp tinyxml2.h)
 set_target_properties(tinyxml2 PROPERTIES
+        COMPILE_DEFINITIONS "TINYXML2_EXPORT"
 	VERSION "${GENERIC_LIB_VERSION}"
 	SOVERSION "${GENERIC_LIB_SOVERSION}")
 

+ 1 - 1
dox

@@ -32,7 +32,7 @@ PROJECT_NAME           = "TinyXML-2"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER = 1.0.12
+PROJECT_NUMBER = 1.0.14
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer

+ 7 - 7
readme.md

@@ -51,11 +51,10 @@ What it doesn't do.
 
 TinyXML-2 doesn't parse or use DTDs (Document Type Definitions) or XSLs
 (eXtensible Stylesheet Language.) There are other parsers out there 
-that are much more fully
-featured. But they are also much bigger, take longer to set up in
-your project, have a higher learning curve, and often have a more
-restrictive license. If you are working with browsers or have more
-complete XML needs, TinyXML-2 is not the parser for you.
+that are much more fully featured. But they are also much bigger, 
+take longer to set up in your project, have a higher learning curve, 
+and often have a more restrictive license. If you are working with 
+browsers or have more complete XML needs, TinyXML-2 is not the parser for you.
 
 TinyXML-1 vs. TinyXML-2
 -----------------------
@@ -309,8 +308,9 @@ in shaping what is a very successful library. Extra thanks to Yves
 Berquin and Andrew Ellerton who were key contributors.
 
 TinyXML-2 grew from that effort. Lee Thomason is the original author
-of TinyXML-2 (and TinyXML-1) but hopefully TinyXML-2 will be improved
+of TinyXML-2 (and TinyXML-1) but TinyXML-2 has been and is being improved
 by many contributors.
 
-Thanks to John Mackay for the TinyXML-2 logo.
+Thanks to John Mackay at http://john.mackay.rosalilastudio.com for the TinyXML-2 logo!
+
 

+ 65 - 9
tinyxml2.cpp

@@ -422,16 +422,19 @@ void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
     TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
 }
 
-
+/*
+	ToStr() of a number is a very tricky topic.
+	https://github.com/leethomason/tinyxml2/issues/106
+*/
 void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
 {
-    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
+    TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v );
 }
 
 
 void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
 {
-    TIXML_SNPRINTF( buffer, bufferSize, "%f", v );
+    TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v );
 }
 
 
@@ -497,12 +500,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
     }
 
     // What is this thing?
-    // - Elements start with a letter or underscore, but xml is reserved.
-    // - Comments: <!--
-    // - Declaration: <?
-    // - Everything else is unknown to tinyxml.
-    //
-
+	// These strings define the matching patters:
     static const char* xmlHeader		= { "<?" };
     static const char* commentHeader	= { "<!--" };
     static const char* dtdHeader		= { "<!" };
@@ -1262,6 +1260,57 @@ const char* XMLElement::GetText() const
 }
 
 
+void	XMLElement::SetText( const char* inText )
+{
+	if ( FirstChild() && FirstChild()->ToText() )
+		FirstChild()->SetValue( inText );
+	else {
+		XMLText*	theText = GetDocument()->NewText( inText );
+		InsertFirstChild( theText );
+	}
+}
+
+
+void XMLElement::SetText( int v ) 
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    SetText( buf );
+}
+
+
+void XMLElement::SetText( unsigned v ) 
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    SetText( buf );
+}
+
+
+void XMLElement::SetText( bool v ) 
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    SetText( buf );
+}
+
+
+void XMLElement::SetText( float v ) 
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    SetText( buf );
+}
+
+
+void XMLElement::SetText( double v ) 
+{
+    char buf[BUF_SIZE];
+    XMLUtil::ToStr( v, buf, BUF_SIZE );
+    SetText( buf );
+}
+
+
 XMLError XMLElement::QueryIntText( int* ival ) const
 {
     if ( FirstChild() && FirstChild()->ToText() ) {
@@ -1639,6 +1688,13 @@ XMLError XMLDocument::LoadFile( FILE* fp )
 {
     Clear();
 
+    fseek( fp, 0, SEEK_SET );
+    fgetc( fp );
+    if ( ferror( fp ) != 0 ) {
+        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
+        return _errorID;
+    }
+
     fseek( fp, 0, SEEK_END );
     size_t size = ftell( fp );
     fseek( fp, 0, SEEK_SET );

+ 80 - 6
tinyxml2.h

@@ -116,9 +116,15 @@ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
 #define TIXML_SSCANF   sscanf
 #endif
 
+/* Versioning, past 1.0.14:
+
+	A backwards-incompatible change or API change bumps the major version.
+	An API addition or a backwards-compatible change, bumps the minor version.
+	Simple bug fixes bump the build number.
+*/
 static const int TIXML2_MAJOR_VERSION = 1;
-static const int TIXML2_MINOR_VERSION = 0;
-static const int TIXML2_PATCH_VERSION = 12;
+static const int TIXML2_MINOR_VERSION = 1;
+static const int TIXML2_PATCH_VERSION = 0;
 
 namespace tinyxml2
 {
@@ -216,6 +222,10 @@ public:
         }
     }
 
+    void Clear() {
+        _size = 0;
+    }
+
     void Push( T t ) {
         EnsureCapacity( _size+1 );
         _mem[_size++] = t;
@@ -1317,6 +1327,11 @@ public:
         XMLAttribute* a = FindOrCreateAttribute( name );
         a->SetAttribute( value );
     }
+    /// Sets the named attribute to value.
+    void SetAttribute( const char* name, float value )		{
+        XMLAttribute* a = FindOrCreateAttribute( name );
+        a->SetAttribute( value );
+    }
 
     /**
     	Delete an attribute.
@@ -1360,6 +1375,52 @@ public:
     */
     const char* GetText() const;
 
+    /** Convenience function for easy access to the text inside an element. Although easy
+    	and concise, SetText() is limited compared to creating an XMLText child
+    	and mutating it directly.
+
+    	If the first child of 'this' is a XMLText, SetText() sets its value to
+		the given string, otherwise it will create a first child that is an XMLText.
+
+    	This is a convenient method for setting the text of simple contained text:
+    	@verbatim
+    	<foo>This is text</foo>
+    		fooElement->SetText( "Hullaballoo!" );
+     	<foo>Hullaballoo!</foo>
+		@endverbatim
+
+    	Note that this function can be misleading. If the element foo was created from
+    	this XML:
+    	@verbatim
+    		<foo><b>This is text</b></foo>
+    	@endverbatim
+
+    	then it will not change "This is text", but rather prefix it with a text element:
+    	@verbatim
+    		<foo>Hullaballoo!<b>This is text</b></foo>
+    	@endverbatim
+		
+		For this XML:
+    	@verbatim
+    		<foo />
+    	@endverbatim
+    	SetText() will generate
+    	@verbatim
+    		<foo>Hullaballoo!</foo>
+    	@endverbatim
+    */
+	void SetText( const char* inText );
+    /// Convenience method for setting text inside and element. See SetText() for important limitations.
+    void SetText( int value );
+    /// Convenience method for setting text inside and element. See SetText() for important limitations.
+    void SetText( unsigned value );  
+    /// Convenience method for setting text inside and element. See SetText() for important limitations.
+    void SetText( bool value );  
+    /// Convenience method for setting text inside and element. See SetText() for important limitations.
+    void SetText( double value );  
+    /// Convenience method for setting text inside and element. See SetText() for important limitations.
+    void SetText( float value );  
+
     /**
     	Convenience method to query the value of a child text node. This is probably best
     	shown by example. Given you have a document is this form:
@@ -1420,6 +1481,7 @@ private:
     //void LinkAttribute( XMLAttribute* attrib );
     char* ParseAttributes( char* p );
 
+    enum { BUF_SIZE = 200 };
     int _closingType;
     // The attribute list is ordered; there is no 'lastAttribute'
     // because the list needs to be scanned for dupes before adding
@@ -1962,23 +2024,35 @@ public:
     int CStrSize() const {
         return _buffer.Size();
     }
+    /**
+    	If in print to memory mode, reset the buffer to the
+    	beginning.
+    */
+    void ClearBuffer() {
+        _buffer.Clear();
+        _buffer.Push(0);
+    }
 
 protected:
-    void SealElement();
+	/** Prints out the space before an element. You may override to change
+	    the space and tabs used. A PrintSpace() override should call Print().
+	*/
+    virtual void PrintSpace( int depth );
+    void Print( const char* format, ... );
+
+	void SealElement();
     bool _elementJustOpened;
     DynArray< const char*, 10 > _stack;
 
 private:
-    void PrintSpace( int depth );
     void PrintString( const char*, bool restrictedEntitySet );	// prints out, after detecting entities.
-    void Print( const char* format, ... );
 
     bool _firstElement;
     FILE* _fp;
     int _depth;
     int _textDepth;
     bool _processEntities;
-    bool _compactMode;
+	bool _compactMode;
 
     enum {
         ENTITY_RANGE = 64,

+ 117 - 28
xmltest.cpp

@@ -617,6 +617,61 @@ int main( int argc, const char ** argv )
 	}
 
 
+	// --------SetText()-----------
+	{
+		const char* str = "<foo></foo>";
+		XMLDocument doc;
+		doc.Parse( str );
+		XMLElement* element = doc.RootElement();
+
+		element->SetText("darkness.");
+		XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
+
+		element->SetText("blue flame.");
+		XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
+
+		str = "<foo/>";
+		doc.Parse( str );
+		element = doc.RootElement();
+
+		element->SetText("The driver");
+		XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
+
+		element->SetText("<b>horses</b>");
+		XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
+		//doc.Print();
+
+		str = "<foo><bar>Text in nested element</bar></foo>";
+		doc.Parse( str );
+		element = doc.RootElement();
+		
+		element->SetText("wolves");
+		XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
+
+		str = "<foo/>";
+		doc.Parse( str );
+		element = doc.RootElement();
+		
+		element->SetText( "str" );
+		XMLTest( "SetText types", "str", element->GetText() );
+
+		element->SetText( 1 );
+		XMLTest( "SetText types", "1", element->GetText() );
+
+		element->SetText( 1U );
+		XMLTest( "SetText types", "1", element->GetText() );
+
+		element->SetText( true );
+		XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
+
+		element->SetText( 1.5f );
+		XMLTest( "SetText types", "1.5", element->GetText() );
+
+		element->SetText( 1.5 );
+		XMLTest( "SetText types", "1.5", element->GetText() );
+	}
+
+
 	// ---------- CDATA ---------------
 	{
 		const char* str =	"<xmlElement>"
@@ -1139,18 +1194,6 @@ int main( int argc, const char ** argv )
 		XMLTest( "Whitespace  all space", true, 0 == doc.FirstChildElement()->FirstChild() );
 	}
 
-#if 0		// the question being explored is what kind of print to use: 
-			// https://github.com/leethomason/tinyxml2/issues/63
-	{
-		const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9'/>";
-		XMLDocument doc;
-		doc.Parse( xml );
-		doc.FirstChildElement()->SetAttribute( "attrA", 123456789.123456789 );
-		doc.FirstChildElement()->SetAttribute( "attrB", 1.001e9 );
-		doc.Print();
-	}
-#endif
-
 	{
 		// An assert should not fire.
 		const char* xml = "<element/>";
@@ -1240,39 +1283,85 @@ int main( int argc, const char ** argv )
 			"</root>";
 
 		XMLDocument doc;
-		doc.Parse( xml );
+		doc.Parse(xml);
 		XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
 		XMLElement* two = doc.RootElement()->FirstChildElement("two");
 		two->InsertFirstChild(subtree);
-		XMLPrinter printer1( 0, true );
-		doc.Accept( &printer1 );
-		XMLTest( "Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
+		XMLPrinter printer1(0, true);
+		doc.Accept(&printer1);
+		XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
 
-		doc.Parse( xml );
+		doc.Parse(xml);
 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
 		two = doc.RootElement()->FirstChildElement("two");
 		doc.RootElement()->InsertAfterChild(two, subtree);
-		XMLPrinter printer2( 0, true );
-		doc.Accept( &printer2 );
-		XMLTest( "Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false );
+		XMLPrinter printer2(0, true);
+		doc.Accept(&printer2);
+		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
 
-		doc.Parse( xml );
+		doc.Parse(xml);
 		XMLNode* one = doc.RootElement()->FirstChildElement("one");
 		subtree = one->FirstChildElement("subtree");
 		doc.RootElement()->InsertAfterChild(one, subtree);
-		XMLPrinter printer3( 0, true );
-		doc.Accept( &printer3 );
-		XMLTest( "Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false );
+		XMLPrinter printer3(0, true);
+		doc.Accept(&printer3);
+		XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
 
-		doc.Parse( xml );
+		doc.Parse(xml);
 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
 		two = doc.RootElement()->FirstChildElement("two");
 		doc.RootElement()->InsertEndChild(subtree);
-		XMLPrinter printer4( 0, true );
-		doc.Accept( &printer4 );
-		XMLTest( "Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false );
+		XMLPrinter printer4(0, true);
+		doc.Accept(&printer4);
+		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
 	}
 
+	{
+		const char* xml = "<svg width = \"128\" height = \"128\">"
+			"	<text> </text>"
+			"</svg>";
+		XMLDocument doc;
+		doc.Parse(xml);
+		doc.Print();
+	}
+
+#if 1
+		// the question being explored is what kind of print to use: 
+		// https://github.com/leethomason/tinyxml2/issues/63
+	{
+		//const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
+		const char* xml = "<element/>";
+		XMLDocument doc;
+		doc.Parse( xml );
+		doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
+		doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
+		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
+		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
+		doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
+		doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
+
+		doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
+		doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
+		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
+		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
+		doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
+		doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
+
+		doc.Print();
+
+		/* The result of this test is platform, compiler, and library version dependent. :("
+		XMLPrinter printer;
+		doc.Print( &printer );
+		XMLTest( "Float and double formatting.", 
+			"<element attrA-f64=\"123456789.12345679\" attrB-f64=\"1001000000\" attrC-f64=\"1e+20\" attrD-f64=\"0.123456789\" attrA-f32=\"1.2345679e+08\" attrB-f32=\"1.001e+09\" attrC-f32=\"1e+20\" attrD-f32=\"0.12345679\"/>\n",
+			printer.CStr(), 
+			true );
+		*/
+	}
+#endif
+
+
+
 	// ----------- Performance tracking --------------
 	{
 #if defined( _MSC_VER )