Browse Source

Update tinyxml2

mingodad 11 years ago
parent
commit
5d5b4a29cb
2 changed files with 155 additions and 50 deletions
  1. 85 41
      SquiLu-ext/tinyxml2.cpp
  2. 70 9
      SquiLu-ext/tinyxml2.h

+ 85 - 41
SquiLu-ext/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 );
@@ -1702,12 +1758,7 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
 	const char* start = p;
     Clear();
 
-    if ( len == 0 ) {
-        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
-        return _errorID;
-    }
-
-    if ( !p || !*p ) {
+    if ( len == 0 || !p || !*p ) {
         SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
         return _errorID;
     }
@@ -1804,27 +1855,19 @@ void XMLPrinter::Print( const char* format, ... )
         vfprintf( _fp, format, va );
     }
     else {
-        // This seems brutally complex. Haven't figured out a better
-        // way on windows.
-#ifdef _MSC_VER
-        int len = -1;
-        int expand = 1000;
-        while ( len < 0 ) {
-            len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va );
-            if ( len < 0 ) {
-                expand *= 3/2;
-                _accumulator.PushArr( expand );
-            }
-        }
-        char* p = _buffer.PushArr( len ) - 1;
-        memcpy( p, _accumulator.Mem(), len+1 );
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+        int len = _vscprintf( format, va );
 #else
         int len = vsnprintf( 0, 0, format, va );
+#endif
         // Close out and re-start the va-args
         va_end( va );
         va_start( va, format );
-        char* p = _buffer.PushArr( len ) - 1;
-        vsnprintf( p, len+1, format, va );
+        char* p = _buffer.PushArr( len ) - 1;	// back up over the null terminator.
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		vsnprintf_s( p, len+1, _TRUNCATE, format, va );
+#else
+		vsnprintf( p, len+1, format, va );
 #endif
     }
     va_end( va );
@@ -1889,17 +1932,17 @@ void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
 }
 
 
-void XMLPrinter::OpenElement( const char* name )
+void XMLPrinter::OpenElement( const char* name, bool compactMode )
 {
     if ( _elementJustOpened ) {
         SealElement();
     }
     _stack.Push( name );
 
-    if ( _textDepth < 0 && !_firstElement && !_compactMode ) {
+    if ( _textDepth < 0 && !_firstElement && !compactMode ) {
         Print( "\n" );
     }
-    if ( !_compactMode ) {
+    if ( !compactMode ) {
         PrintSpace( _depth );
     }
 
@@ -1951,7 +1994,7 @@ void XMLPrinter::PushAttribute( const char* name, double v )
 }
 
 
-void XMLPrinter::CloseElement()
+void XMLPrinter::CloseElement( bool compactMode )
 {
     --_depth;
     const char* name = _stack.Pop();
@@ -1960,7 +2003,7 @@ void XMLPrinter::CloseElement()
         Print( "/>" );
     }
     else {
-        if ( _textDepth < 0 && !_compactMode) {
+        if ( _textDepth < 0 && !compactMode) {
             Print( "\n" );
             PrintSpace( _depth );
         }
@@ -1970,7 +2013,7 @@ void XMLPrinter::CloseElement()
     if ( _textDepth == _depth ) {
         _textDepth = -1;
     }
-    if ( _depth == 0 && !_compactMode) {
+    if ( _depth == 0 && !compactMode) {
         Print( "\n" );
     }
     _elementJustOpened = false;
@@ -2095,7 +2138,9 @@ bool XMLPrinter::VisitEnter( const XMLDocument& doc )
 
 bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
 {
-    OpenElement( element.Name() );
+	const XMLElement*	parentElem = element.Parent()->ToElement();
+	bool		compactMode = parentElem ? CompactMode(*parentElem) : _compactMode;
+    OpenElement( element.Name(), compactMode );
     while ( attribute ) {
         PushAttribute( attribute->Name(), attribute->Value() );
         attribute = attribute->Next();
@@ -2104,9 +2149,9 @@ bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attr
 }
 
 
-bool XMLPrinter::VisitExit( const XMLElement& )
+bool XMLPrinter::VisitExit( const XMLElement& element )
 {
-    CloseElement();
+    CloseElement( CompactMode(element) );
     return true;
 }
 
@@ -2138,4 +2183,3 @@ bool XMLPrinter::Visit( const XMLUnknown& unknown )
 }
 
 }   // namespace tinyxml2
-

+ 70 - 9
SquiLu-ext/tinyxml2.h

@@ -116,9 +116,12 @@ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
 #define TIXML_SSCANF   sscanf
 #endif
 
-static const int TIXML2_MAJOR_VERSION = 1;
-static const int TIXML2_MINOR_VERSION = 0;
-static const int TIXML2_PATCH_VERSION = 12;
+/* Versioning, past 1.0.14:
+	http://semver.org/
+*/
+static const int TIXML2_MAJOR_VERSION = 2;
+static const int TIXML2_MINOR_VERSION = 1;
+static const int TIXML2_PATCH_VERSION = 0;
 
 namespace tinyxml2
 {
@@ -1321,6 +1324,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.
@@ -1364,6 +1372,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:
@@ -1424,6 +1478,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
@@ -1909,7 +1964,7 @@ public:
     /** If streaming, start writing an element.
         The element must be closed with CloseElement()
     */
-    void OpenElement( const char* name );
+    void OpenElement( const char* name, bool compactMode=false );
     /// If streaming, add an attribute to an open element.
     void PushAttribute( const char* name, const char* value );
     void PushAttribute( const char* name, int value );
@@ -1917,7 +1972,7 @@ public:
     void PushAttribute( const char* name, bool value );
     void PushAttribute( const char* name, double value );
     /// If streaming, close the Element.
-    virtual void CloseElement();
+    virtual void CloseElement( bool compactMode=false );
 
     /// Add a text node.
     void PushText( const char* text, bool cdata=false );
@@ -1976,21 +2031,27 @@ public:
     }
 
 protected:
-    void SealElement();
+	virtual bool CompactMode( const XMLElement& )	{ return _compactMode; }
+
+	/** 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,