Updated tinyxml

This commit is contained in:
PKEuS 2014-03-01 11:15:08 +01:00
parent a41a32ba8a
commit 357f5076db
3 changed files with 168 additions and 37 deletions

View File

@ -422,16 +422,19 @@ void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); 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 ) 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 ) 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? // What is this thing?
// - Elements start with a letter or underscore, but xml is reserved. // These strings define the matching patters:
// - Comments: <!--
// - Declaration: <?
// - Everything else is unknown to tinyxml.
//
static const char* xmlHeader = { "<?" }; static const char* xmlHeader = { "<?" };
static const char* commentHeader = { "<!--" }; static const char* commentHeader = { "<!--" };
static const char* dtdHeader = { "<!" }; 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 XMLError XMLElement::QueryIntText( int* ival ) const
{ {
if ( FirstChild() && FirstChild()->ToText() ) { if ( FirstChild() && FirstChild()->ToText() ) {
@ -1639,6 +1688,13 @@ XMLError XMLDocument::LoadFile( FILE* fp )
{ {
Clear(); 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 ); fseek( fp, 0, SEEK_END );
size_t size = ftell( fp ); size_t size = ftell( fp );
fseek( fp, 0, SEEK_SET ); fseek( fp, 0, SEEK_SET );
@ -1702,7 +1758,7 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
const char* start = p; const char* start = p;
Clear(); Clear();
if ( !p || !*p ) { if ( len == 0 || !p || !*p ) {
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
return _errorID; return _errorID;
} }
@ -1884,17 +1940,17 @@ void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
} }
void XMLPrinter::OpenElement( const char* name ) void XMLPrinter::OpenElement( const char* name, bool compactMode )
{ {
if ( _elementJustOpened ) { if ( _elementJustOpened ) {
SealElement(); SealElement();
} }
_stack.Push( name ); _stack.Push( name );
if ( _textDepth < 0 && !_firstElement && !_compactMode ) { if ( _textDepth < 0 && !_firstElement && !compactMode ) {
Print( "\n" ); Print( "\n" );
} }
if ( !_compactMode ) { if ( !compactMode ) {
PrintSpace( _depth ); PrintSpace( _depth );
} }
@ -1946,7 +2002,7 @@ void XMLPrinter::PushAttribute( const char* name, double v )
} }
void XMLPrinter::CloseElement() void XMLPrinter::CloseElement( bool compactMode )
{ {
--_depth; --_depth;
const char* name = _stack.Pop(); const char* name = _stack.Pop();
@ -1955,7 +2011,7 @@ void XMLPrinter::CloseElement()
Print( "/>" ); Print( "/>" );
} }
else { else {
if ( _textDepth < 0 && !_compactMode) { if ( _textDepth < 0 && !compactMode) {
Print( "\n" ); Print( "\n" );
PrintSpace( _depth ); PrintSpace( _depth );
} }
@ -1965,7 +2021,7 @@ void XMLPrinter::CloseElement()
if ( _textDepth == _depth ) { if ( _textDepth == _depth ) {
_textDepth = -1; _textDepth = -1;
} }
if ( _depth == 0 && !_compactMode) { if ( _depth == 0 && !compactMode) {
Print( "\n" ); Print( "\n" );
} }
_elementJustOpened = false; _elementJustOpened = false;
@ -2090,7 +2146,9 @@ bool XMLPrinter::VisitEnter( const XMLDocument& doc )
bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) 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 ) { while ( attribute ) {
PushAttribute( attribute->Name(), attribute->Value() ); PushAttribute( attribute->Name(), attribute->Value() );
attribute = attribute->Next(); attribute = attribute->Next();
@ -2099,9 +2157,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; return true;
} }

View File

@ -116,9 +116,12 @@ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
#define TIXML_SSCANF sscanf #define TIXML_SSCANF sscanf
#endif #endif
static const int TIXML2_MAJOR_VERSION = 1; /* Versioning, past 1.0.14:
http://semver.org/
*/
static const int TIXML2_MAJOR_VERSION = 2;
static const int TIXML2_MINOR_VERSION = 0; static const int TIXML2_MINOR_VERSION = 0;
static const int TIXML2_PATCH_VERSION = 12; static const int TIXML2_PATCH_VERSION = 0;
namespace tinyxml2 namespace tinyxml2
{ {
@ -216,6 +219,10 @@ public:
} }
} }
void Clear() {
_size = 0;
}
void Push( T t ) { void Push( T t ) {
EnsureCapacity( _size+1 ); EnsureCapacity( _size+1 );
_mem[_size++] = t; _mem[_size++] = t;
@ -1317,6 +1324,11 @@ public:
XMLAttribute* a = FindOrCreateAttribute( name ); XMLAttribute* a = FindOrCreateAttribute( name );
a->SetAttribute( value ); 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. Delete an attribute.
@ -1360,6 +1372,52 @@ public:
*/ */
const char* GetText() const; 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 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: shown by example. Given you have a document is this form:
@ -1420,6 +1478,7 @@ private:
//void LinkAttribute( XMLAttribute* attrib ); //void LinkAttribute( XMLAttribute* attrib );
char* ParseAttributes( char* p ); char* ParseAttributes( char* p );
enum { BUF_SIZE = 200 };
int _closingType; int _closingType;
// The attribute list is ordered; there is no 'lastAttribute' // The attribute list is ordered; there is no 'lastAttribute'
// because the list needs to be scanned for dupes before adding // because the list needs to be scanned for dupes before adding
@ -1905,7 +1964,7 @@ public:
/** If streaming, start writing an element. /** If streaming, start writing an element.
The element must be closed with CloseElement() The element must be closed with CloseElement()
*/ */
void OpenElement( const char* name ); void OpenElement( const char* name, bool compactMode );
/// If streaming, add an attribute to an open element. /// If streaming, add an attribute to an open element.
void PushAttribute( const char* name, const char* value ); void PushAttribute( const char* name, const char* value );
void PushAttribute( const char* name, int value ); void PushAttribute( const char* name, int value );
@ -1913,7 +1972,7 @@ public:
void PushAttribute( const char* name, bool value ); void PushAttribute( const char* name, bool value );
void PushAttribute( const char* name, double value ); void PushAttribute( const char* name, double value );
/// If streaming, close the Element. /// If streaming, close the Element.
virtual void CloseElement(); virtual void CloseElement( bool compactMode );
/// Add a text node. /// Add a text node.
void PushText( const char* text, bool cdata=false ); void PushText( const char* text, bool cdata=false );
@ -1962,16 +2021,30 @@ public:
int CStrSize() const { int CStrSize() const {
return _buffer.Size(); return _buffer.Size();
} }
/**
If in print to memory mode, reset the buffer to the
beginning.
*/
void ClearBuffer() {
_buffer.Clear();
_buffer.Push(0);
}
protected: protected:
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(); void SealElement();
bool _elementJustOpened; bool _elementJustOpened;
DynArray< const char*, 10 > _stack; DynArray< const char*, 10 > _stack;
private: private:
void PrintSpace( int depth );
void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
void Print( const char* format, ... );
bool _firstElement; bool _firstElement;
FILE* _fp; FILE* _fp;

View File

@ -185,14 +185,14 @@ std::string ErrorLogger::ErrorMessage::getXMLHeader(int xml_version)
printer.PushDeclaration("xml version=\"1.0\" encoding=\"UTF-8\""); printer.PushDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
// header // header
printer.OpenElement("results"); printer.OpenElement("results", false);
// version 2 header // version 2 header
if (xml_version == 2) { if (xml_version == 2) {
printer.PushAttribute("version", xml_version); printer.PushAttribute("version", xml_version);
printer.OpenElement("cppcheck"); printer.OpenElement("cppcheck", false);
printer.PushAttribute("version", CppCheck::version()); printer.PushAttribute("version", CppCheck::version());
printer.CloseElement(); printer.CloseElement(false);
printer.OpenElement("errors"); printer.OpenElement("errors", false);
} }
return std::string(printer.CStr()) + '>'; return std::string(printer.CStr()) + '>';
@ -212,7 +212,7 @@ std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const
return ""; return "";
tinyxml2::XMLPrinter printer(0, false, 1); tinyxml2::XMLPrinter printer(0, false, 1);
printer.OpenElement("error"); printer.OpenElement("error", false);
if (!_callStack.empty()) { if (!_callStack.empty()) {
printer.PushAttribute("file", _callStack.back().getfile().c_str()); printer.PushAttribute("file", _callStack.back().getfile().c_str());
printer.PushAttribute("line", _callStack.back().line); printer.PushAttribute("line", _callStack.back().line);
@ -220,14 +220,14 @@ std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const
printer.PushAttribute("id", _id.c_str()); printer.PushAttribute("id", _id.c_str());
printer.PushAttribute("severity", (_severity == Severity::error ? "error" : "style")); printer.PushAttribute("severity", (_severity == Severity::error ? "error" : "style"));
printer.PushAttribute("msg", (verbose ? _verboseMessage : _shortMessage).c_str()); printer.PushAttribute("msg", (verbose ? _verboseMessage : _shortMessage).c_str());
printer.CloseElement(); printer.CloseElement(false);
return printer.CStr(); return printer.CStr();
} }
// The xml format you get when you use --xml-version=2 // The xml format you get when you use --xml-version=2
else if (version == 2) { else if (version == 2) {
tinyxml2::XMLPrinter printer(0, false, 2); tinyxml2::XMLPrinter printer(0, false, 2);
printer.OpenElement("error"); printer.OpenElement("error", false);
printer.PushAttribute("id", _id.c_str()); printer.PushAttribute("id", _id.c_str());
printer.PushAttribute("severity", Severity::toString(_severity).c_str()); printer.PushAttribute("severity", Severity::toString(_severity).c_str());
printer.PushAttribute("msg", _shortMessage.c_str()); printer.PushAttribute("msg", _shortMessage.c_str());
@ -236,12 +236,12 @@ std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const
printer.PushAttribute("inconclusive", "true"); printer.PushAttribute("inconclusive", "true");
for (std::list<FileLocation>::const_reverse_iterator it = _callStack.rbegin(); it != _callStack.rend(); ++it) { for (std::list<FileLocation>::const_reverse_iterator it = _callStack.rbegin(); it != _callStack.rend(); ++it) {
printer.OpenElement("location"); printer.OpenElement("location", false);
printer.PushAttribute("file", (*it).getfile().c_str()); printer.PushAttribute("file", (*it).getfile().c_str());
printer.PushAttribute("line", (*it).line); printer.PushAttribute("line", (*it).line);
printer.CloseElement(); printer.CloseElement(false);
} }
printer.CloseElement(); printer.CloseElement(false);
return printer.CStr(); return printer.CStr();
} }