Updated TinyXML and simplecpp

This commit is contained in:
PKEuS 2016-12-29 11:28:25 +01:00
parent 24332b540d
commit b86a39d38a
3 changed files with 536 additions and 226 deletions

View File

@ -73,7 +73,7 @@ namespace {
long long stringToLL(const std::string &s)
{
long long ret;
bool hex = (s.compare(0, 2, "0x") == 0);
const bool hex = (s.length()>2 && s.compare(0, 2, "0x") == 0);
std::istringstream istr(hex ? s.substr(2) : s);
if (hex)
istr >> std::hex;
@ -84,7 +84,7 @@ namespace {
unsigned long long stringToULL(const std::string &s)
{
unsigned long long ret;
bool hex = (s.compare(0, 2, "0x") == 0);
const bool hex = (s.length()>2 && s.compare(0, 2, "0x") == 0);
std::istringstream istr(hex ? s.substr(2) : s);
if (hex)
istr >> std::hex;
@ -504,11 +504,11 @@ void simplecpp::TokenList::readfile(std::istream &istr, const std::string &filen
if (ch == '\"' && cback() && cback()->op == 'R') {
std::string delim;
ch = readChar(istr,bom);
while (istr.good() && ch != '(' && ch != '\"' && ch != '\n') {
while (istr.good() && ch != '(' && ch != '\n') {
delim += ch;
ch = readChar(istr,bom);
}
if (!istr.good() || ch == '\"' || ch == '\n')
if (!istr.good() || ch == '\n')
// TODO report
return;
currentToken = '\"';

View File

@ -149,6 +149,7 @@ void StrPair::TransferTo( StrPair* other )
// This in effect implements the assignment operator by "moving"
// ownership (as in auto_ptr).
TIXMLASSERT( other != 0 );
TIXMLASSERT( other->_flags == 0 );
TIXMLASSERT( other->_start == 0 );
TIXMLASSERT( other->_end == 0 );
@ -188,9 +189,11 @@ void StrPair::SetStr( const char* str, int flags )
}
char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr )
{
TIXMLASSERT( p );
TIXMLASSERT( endTag && *endTag );
TIXMLASSERT(curLineNumPtr);
char* start = p;
char endChar = *endTag;
@ -201,8 +204,11 @@ char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
Set( start, p, strFlags );
return p + length;
} else if (*p == '\n') {
++(*curLineNumPtr);
}
++p;
TIXMLASSERT( p );
}
return 0;
}
@ -233,15 +239,15 @@ void StrPair::CollapseWhitespace()
// Adjusting _start would cause undefined behavior on delete[]
TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );
// Trim leading space.
_start = XMLUtil::SkipWhiteSpace( _start );
_start = XMLUtil::SkipWhiteSpace( _start, 0 );
if ( *_start ) {
char* p = _start; // the read pointer
const char* p = _start; // the read pointer
char* q = _start; // the write pointer
while( *p ) {
if ( XMLUtil::IsWhiteSpace( *p )) {
p = XMLUtil::SkipWhiteSpace( p );
p = XMLUtil::SkipWhiteSpace( p, 0 );
if ( *p == 0 ) {
break; // don't write to q; this trims the trailing space.
}
@ -266,7 +272,7 @@ const char* StrPair::GetStr()
_flags ^= NEEDS_FLUSH;
if ( _flags ) {
char* p = _start; // the read pointer
const char* p = _start; // the read pointer
char* q = _start; // the write pointer
while( p < _end ) {
@ -280,7 +286,8 @@ const char* StrPair::GetStr()
else {
++p;
}
*q++ = LF;
*q = LF;
++q;
}
else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
if ( *(p+1) == CR ) {
@ -289,7 +296,8 @@ const char* StrPair::GetStr()
else {
++p;
}
*q++ = LF;
*q = LF;
++q;
}
else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
// Entities handled by tinyXML2:
@ -537,7 +545,7 @@ void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
{
TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? "true" : "false" );
}
/*
@ -556,6 +564,13 @@ void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
}
void XMLUtil::ToStr(int64_t v, char* buffer, int bufferSize)
{
// horrible syntax trick to make the compiler happy about %lld
TIXML_SNPRINTF(buffer, bufferSize, "%lld", (long long)v);
}
bool XMLUtil::ToInt( const char* str, int* value )
{
if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
@ -599,6 +614,7 @@ bool XMLUtil::ToFloat( const char* str, float* value )
return false;
}
bool XMLUtil::ToDouble( const char* str, double* value )
{
if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
@ -608,12 +624,24 @@ bool XMLUtil::ToDouble( const char* str, double* value )
}
bool XMLUtil::ToInt64(const char* str, int64_t* value)
{
long long v = 0; // horrible syntax trick to make the compiler happy about %lld
if (TIXML_SSCANF(str, "%lld", &v) == 1) {
*value = (int64_t)v;
return true;
}
return false;
}
char* XMLDocument::Identify( char* p, XMLNode** node )
{
TIXMLASSERT( node );
TIXMLASSERT( p );
char* const start = p;
p = XMLUtil::SkipWhiteSpace( p );
int const startLine = _parseCurLineNum;
p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );
if( !*p ) {
*node = 0;
TIXMLASSERT( p );
@ -639,12 +667,14 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );
returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
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->_parseLineNum = _parseCurLineNum;
returnNode->_memPool = &_commentPool;
p += commentHeaderLen;
}
@ -652,6 +682,7 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );
XMLText* text = new (_textPool.Alloc()) XMLText( this );
returnNode = text;
returnNode->_parseLineNum = _parseCurLineNum;
returnNode->_memPool = &_textPool;
p += cdataHeaderLen;
text->SetCData( true );
@ -659,12 +690,14 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() );
returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
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->_parseLineNum = _parseCurLineNum;
returnNode->_memPool = &_elementPool;
p += elementHeaderLen;
}
@ -672,7 +705,9 @@ char* XMLDocument::Identify( char* p, XMLNode** node )
TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );
returnNode = new (_textPool.Alloc()) XMLText( this );
returnNode->_memPool = &_textPool;
returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character
p = start; // Back it up, all the text counts.
_parseCurLineNum = startLine;
}
TIXMLASSERT( returnNode );
@ -701,8 +736,10 @@ bool XMLDocument::Accept( XMLVisitor* visitor ) const
XMLNode::XMLNode( XMLDocument* doc ) :
_document( doc ),
_parent( 0 ),
_parseLineNum( 0 ),
_firstChild( 0 ), _lastChild( 0 ),
_prev( 0 ), _next( 0 ),
_userData( 0 ),
_memPool( 0 )
{
}
@ -718,7 +755,7 @@ XMLNode::~XMLNode()
const char* XMLNode::Value() const
{
// Catch an edge case: XMLDocuments don't have a a Value. Carefully return nullptr.
// Edge case: XMLDocuments don't have a Value. Return null.
if ( this->ToDocument() )
return 0;
return _value.GetStr();
@ -739,11 +776,7 @@ void XMLNode::DeleteChildren()
{
while( _firstChild ) {
TIXMLASSERT( _lastChild );
TIXMLASSERT( _firstChild->_document == _document );
XMLNode* node = _firstChild;
Unlink( node );
DeleteNode( node );
DeleteChild( _firstChild );
}
_firstChild = _lastChild = 0;
}
@ -876,11 +909,9 @@ XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
const XMLElement* XMLNode::FirstChildElement( const char* name ) const
{
for( const XMLNode* node = _firstChild; node; node = node->_next ) {
const XMLElement* element = node->ToElement();
const XMLElement* element = node->ToElementWithName( name );
if ( element ) {
if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {
return element;
}
return element;
}
}
return 0;
@ -890,11 +921,9 @@ const XMLElement* XMLNode::FirstChildElement( const char* name ) const
const XMLElement* XMLNode::LastChildElement( const char* name ) const
{
for( const XMLNode* node = _lastChild; node; node = node->_prev ) {
const XMLElement* element = node->ToElement();
const XMLElement* element = node->ToElementWithName( name );
if ( element ) {
if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {
return element;
}
return element;
}
}
return 0;
@ -904,9 +933,8 @@ const XMLElement* XMLNode::LastChildElement( const char* name ) const
const XMLElement* XMLNode::NextSiblingElement( const char* name ) const
{
for( const XMLNode* node = _next; node; node = node->_next ) {
const XMLElement* element = node->ToElement();
if ( element
&& (!name || XMLUtil::StringEqual( name, element->Name() ))) {
const XMLElement* element = node->ToElementWithName( name );
if ( element ) {
return element;
}
}
@ -917,9 +945,8 @@ const XMLElement* XMLNode::NextSiblingElement( const char* name ) const
const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const
{
for( const XMLNode* node = _prev; node; node = node->_prev ) {
const XMLElement* element = node->ToElement();
if ( element
&& (!name || XMLUtil::StringEqual( name, element->Name() ))) {
const XMLElement* element = node->ToElementWithName( name );
if ( element ) {
return element;
}
}
@ -927,7 +954,7 @@ const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const
}
char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr )
{
// This is a recursive method, but thinking about it "at the current level"
// it is a pretty simple flat list:
@ -950,29 +977,42 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
XMLNode* node = 0;
p = _document->Identify( p, &node );
TIXMLASSERT( p );
if ( node == 0 ) {
break;
}
int initialLineNum = node->_parseLineNum;
StrPair endTag;
p = node->ParseDeep( p, &endTag );
p = node->ParseDeep( p, &endTag, curLineNumPtr );
if ( !p ) {
DeleteNode( node );
if ( !_document->Error() ) {
_document->SetError( XML_ERROR_PARSING, 0, 0 );
_document->SetError( XML_ERROR_PARSING, 0, 0, initialLineNum);
}
break;
}
XMLDeclaration* decl = node->ToDeclaration();
if ( decl ) {
// A declaration can only be the first child of a document.
// Set error, if document already has children.
if ( !_document->NoChildren() ) {
_document->SetError( XML_ERROR_PARSING_DECLARATION, decl->Value(), 0);
DeleteNode( decl );
// Declarations are only allowed at document level
bool wellLocated = ( ToDocument() != 0 );
if ( wellLocated ) {
// Multiple declarations are allowed but all declarations
// must occur before anything else
for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) {
if ( !existingNode->ToDeclaration() ) {
wellLocated = false;
break;
}
}
}
if ( !wellLocated ) {
_document->SetError( XML_ERROR_PARSING_DECLARATION, decl->Value(), 0, initialLineNum);
DeleteNode( node );
break;
}
}
XMLElement* ele = node->ToElement();
@ -1004,7 +1044,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
}
}
if ( mismatch ) {
_document->SetError( XML_ERROR_MISMATCHED_ELEMENT, ele->Name(), 0 );
_document->SetError( XML_ERROR_MISMATCHED_ELEMENT, ele->Name(), 0, initialLineNum);
DeleteNode( node );
break;
}
@ -1035,14 +1075,29 @@ void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const
insertThis->_memPool->SetTracked();
}
const XMLElement* XMLNode::ToElementWithName( const char* name ) const
{
const XMLElement* element = this->ToElement();
if ( element == 0 ) {
return 0;
}
if ( name == 0 ) {
return element;
}
if ( XMLUtil::StringEqual( element->Name(), name ) ) {
return element;
}
return 0;
}
// --------- XMLText ---------- //
char* XMLText::ParseDeep( char* p, StrPair* )
char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
{
const char* start = p;
if ( this->CData() ) {
p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
if ( !p ) {
_document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );
_document->SetError( XML_ERROR_PARSING_CDATA, start, 0, _parseLineNum );
}
return p;
}
@ -1052,12 +1107,12 @@ char* XMLText::ParseDeep( char* p, StrPair* )
flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING;
}
p = _value.ParseText( p, "<", flags );
p = _value.ParseText( p, "<", flags, curLineNumPtr );
if ( p && *p ) {
return p-1;
}
if ( !p ) {
_document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );
_document->SetError( XML_ERROR_PARSING_TEXT, start, 0, _parseLineNum );
}
}
return 0;
@ -1101,13 +1156,13 @@ XMLComment::~XMLComment()
}
char* XMLComment::ParseDeep( char* p, StrPair* )
char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
{
// Comment parses as text.
const char* start = p;
p = _value.ParseText( p, "-->", StrPair::COMMENT );
p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr );
if ( p == 0 ) {
_document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );
_document->SetError( XML_ERROR_PARSING_COMMENT, start, 0, _parseLineNum );
}
return p;
}
@ -1151,13 +1206,13 @@ XMLDeclaration::~XMLDeclaration()
}
char* XMLDeclaration::ParseDeep( char* p, StrPair* )
char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
{
// Declaration parses as text.
const char* start = p;
p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );
p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
if ( p == 0 ) {
_document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );
_document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0, _parseLineNum );
}
return p;
}
@ -1200,14 +1255,14 @@ XMLUnknown::~XMLUnknown()
}
char* XMLUnknown::ParseDeep( char* p, StrPair* )
char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
{
// Unknown parses as text.
const char* start = p;
p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );
p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
if ( !p ) {
_document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );
_document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0, _parseLineNum );
}
return p;
}
@ -1249,7 +1304,7 @@ const char* XMLAttribute::Value() const
return _value.GetStr();
}
char* XMLAttribute::ParseDeep( char* p, bool processEntities )
char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr )
{
// Parse using the name rules: bug fix, was using ParseText before
p = _name.ParseName( p );
@ -1258,13 +1313,13 @@ char* XMLAttribute::ParseDeep( char* p, bool processEntities )
}
// Skip white space before =
p = XMLUtil::SkipWhiteSpace( p );
p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
if ( *p != '=' ) {
return 0;
}
++p; // move up to opening quote
p = XMLUtil::SkipWhiteSpace( p );
p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
if ( *p != '\"' && *p != '\'' ) {
return 0;
}
@ -1272,7 +1327,7 @@ char* XMLAttribute::ParseDeep( char* p, bool processEntities )
char endTag[2] = { *p, 0 };
++p; // move past opening quote
p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );
p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr );
return p;
}
@ -1301,6 +1356,15 @@ XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
}
XMLError XMLAttribute::QueryInt64Value(int64_t* value) const
{
if (XMLUtil::ToInt64(Value(), value)) {
return XML_SUCCESS;
}
return XML_WRONG_ATTRIBUTE_TYPE;
}
XMLError XMLAttribute::QueryBoolValue( bool* value ) const
{
if ( XMLUtil::ToBool( Value(), value )) {
@ -1350,6 +1414,15 @@ void XMLAttribute::SetAttribute( unsigned v )
}
void XMLAttribute::SetAttribute(int64_t v)
{
char buf[BUF_SIZE];
XMLUtil::ToStr(v, buf, BUF_SIZE);
_value.SetStr(buf);
}
void XMLAttribute::SetAttribute( bool v )
{
char buf[BUF_SIZE];
@ -1413,6 +1486,47 @@ const char* XMLElement::Attribute( const char* name, const char* value ) const
return 0;
}
int XMLElement::IntAttribute(const char* name, int defaultValue) const
{
int i = defaultValue;
QueryIntAttribute(name, &i);
return i;
}
unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const
{
unsigned i = defaultValue;
QueryUnsignedAttribute(name, &i);
return i;
}
int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const
{
int64_t i = defaultValue;
QueryInt64Attribute(name, &i);
return i;
}
bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const
{
bool b = defaultValue;
QueryBoolAttribute(name, &b);
return b;
}
double XMLElement::DoubleAttribute(const char* name, double defaultValue) const
{
double d = defaultValue;
QueryDoubleAttribute(name, &d);
return d;
}
float XMLElement::FloatAttribute(const char* name, float defaultValue) const
{
float f = defaultValue;
QueryFloatAttribute(name, &f);
return f;
}
const char* XMLElement::GetText() const
{
@ -1450,7 +1564,15 @@ void XMLElement::SetText( unsigned v )
}
void XMLElement::SetText( bool v )
void XMLElement::SetText(int64_t 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 );
@ -1500,6 +1622,19 @@ XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
}
XMLError XMLElement::QueryInt64Text(int64_t* ival) const
{
if (FirstChild() && FirstChild()->ToText()) {
const char* t = FirstChild()->Value();
if (XMLUtil::ToInt64(t, ival)) {
return XML_SUCCESS;
}
return XML_CAN_NOT_CONVERT_TEXT;
}
return XML_NO_TEXT_NODE;
}
XMLError XMLElement::QueryBoolText( bool* bval ) const
{
if ( FirstChild() && FirstChild()->ToText() ) {
@ -1538,6 +1673,47 @@ XMLError XMLElement::QueryFloatText( float* fval ) const
return XML_NO_TEXT_NODE;
}
int XMLElement::IntText(int defaultValue) const
{
int i = defaultValue;
QueryIntText(&i);
return i;
}
unsigned XMLElement::UnsignedText(unsigned defaultValue) const
{
unsigned i = defaultValue;
QueryUnsignedText(&i);
return i;
}
int64_t XMLElement::Int64Text(int64_t defaultValue) const
{
int64_t i = defaultValue;
QueryInt64Text(&i);
return i;
}
bool XMLElement::BoolText(bool defaultValue) const
{
bool b = defaultValue;
QueryBoolText(&b);
return b;
}
double XMLElement::DoubleText(double defaultValue) const
{
double d = defaultValue;
QueryDoubleText(&d);
return d;
}
float XMLElement::FloatText(float defaultValue) const
{
float f = defaultValue;
QueryFloatText(&f);
return f;
}
XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
@ -1552,17 +1728,17 @@ XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
}
}
if ( !attrib ) {
TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
attrib->_memPool = &_document->_attributePool;
attrib = CreateAttribute();
TIXMLASSERT( attrib );
if ( last ) {
TIXMLASSERT( last->_next == 0 );
last->_next = attrib;
}
else {
TIXMLASSERT( _rootAttribute == 0 );
_rootAttribute = attrib;
}
attrib->SetName( name );
attrib->_memPool->SetTracked(); // always created and linked.
}
return attrib;
}
@ -1587,30 +1763,31 @@ void XMLElement::DeleteAttribute( const char* name )
}
char* XMLElement::ParseAttributes( char* p )
char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )
{
const char* start = p;
XMLAttribute* prevAttribute = 0;
// Read the attributes.
while( p ) {
p = XMLUtil::SkipWhiteSpace( p );
p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
if ( !(*p) ) {
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name(), _parseLineNum );
return 0;
}
// attribute.
if (XMLUtil::IsNameStartChar( *p ) ) {
TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
attrib->_memPool = &_document->_attributePool;
attrib->_memPool->SetTracked();
XMLAttribute* attrib = CreateAttribute();
TIXMLASSERT( attrib );
attrib->_parseLineNum = _document->_parseCurLineNum;
p = attrib->ParseDeep( p, _document->ProcessEntities() );
int attrLineNum = attrib->_parseLineNum;
p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr );
if ( !p || Attribute( attrib->Name() ) ) {
DeleteAttribute( attrib );
_document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );
_document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p, attrLineNum );
return 0;
}
// There is a minor bug here: if the attribute in the source xml
@ -1619,9 +1796,11 @@ char* XMLElement::ParseAttributes( char* p )
// avoids re-scanning the attribute list. Preferring performance for
// now, may reconsider in the future.
if ( prevAttribute ) {
TIXMLASSERT( prevAttribute->_next == 0 );
prevAttribute->_next = attrib;
}
else {
TIXMLASSERT( _rootAttribute == 0 );
_rootAttribute = attrib;
}
prevAttribute = attrib;
@ -1637,7 +1816,7 @@ char* XMLElement::ParseAttributes( char* p )
return p+2; // done; sealed element.
}
else {
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );
_document->SetError( XML_ERROR_PARSING_ELEMENT, start, p, _parseLineNum );
return 0;
}
}
@ -1654,14 +1833,23 @@ void XMLElement::DeleteAttribute( XMLAttribute* attribute )
pool->Free( attribute );
}
XMLAttribute* XMLElement::CreateAttribute()
{
TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
attrib->_memPool = &_document->_attributePool;
attrib->_memPool->SetTracked();
return attrib;
}
//
// <ele></ele>
// <ele>foo<b>bar</b></ele>
//
char* XMLElement::ParseDeep( char* p, StrPair* strPair )
char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr )
{
// Read the element name.
p = XMLUtil::SkipWhiteSpace( p );
p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
// The closing element is the </element> form. It is
// parsed just like a regular element then deleted from
@ -1676,12 +1864,12 @@ char* XMLElement::ParseDeep( char* p, StrPair* strPair )
return 0;
}
p = ParseAttributes( p );
p = ParseAttributes( p, curLineNumPtr );
if ( !p || !*p || _closingType ) {
return p;
}
p = XMLNode::ParseDeep( p, strPair );
p = XMLNode::ParseDeep( p, strPair, curLineNumPtr );
return p;
}
@ -1773,8 +1961,6 @@ XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
_processEntities( processEntities ),
_errorID(XML_SUCCESS),
_whitespace( whitespace ),
_errorStr1( 0 ),
_errorStr2( 0 ),
_charBuffer( 0 )
{
// avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
@ -1795,9 +1981,7 @@ void XMLDocument::Clear()
#ifdef DEBUG
const bool hadError = Error();
#endif
_errorID = XML_SUCCESS;
_errorStr1 = 0;
_errorStr2 = 0;
ClearError();
delete [] _charBuffer;
_charBuffer = 0;
@ -1908,7 +2092,7 @@ XMLError XMLDocument::LoadFile( const char* filename )
Clear();
FILE* fp = callfopen( filename, "rb" );
if ( !fp ) {
SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0, 0 );
return _errorID;
}
LoadFile( fp );
@ -1932,10 +2116,12 @@ struct LongFitsIntoSizeTMinusOne {
};
template <>
bool LongFitsIntoSizeTMinusOne<false>::Fits( unsigned long /*value*/ )
{
return true;
}
struct LongFitsIntoSizeTMinusOne<false> {
static bool Fits( unsigned long )
{
return true;
}
};
XMLError XMLDocument::LoadFile( FILE* fp )
{
@ -1943,7 +2129,7 @@ XMLError XMLDocument::LoadFile( FILE* fp )
fseek( fp, 0, SEEK_SET );
if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0, 0 );
return _errorID;
}
@ -1951,19 +2137,19 @@ XMLError XMLDocument::LoadFile( FILE* fp )
const long filelength = ftell( fp );
fseek( fp, 0, SEEK_SET );
if ( filelength == -1L ) {
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0, 0 );
return _errorID;
}
TIXMLASSERT( filelength >= 0 );
if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {
// Cannot handle files which won't fit in buffer together with null terminator
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0, 0 );
return _errorID;
}
if ( filelength == 0 ) {
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0, 0 );
return _errorID;
}
@ -1972,7 +2158,7 @@ XMLError XMLDocument::LoadFile( FILE* fp )
_charBuffer = new char[size+1];
size_t read = fread( _charBuffer, 1, size, fp );
if ( read != size ) {
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
SetError( XML_ERROR_FILE_READ_ERROR, 0, 0, 0 );
return _errorID;
}
@ -1987,7 +2173,7 @@ XMLError XMLDocument::SaveFile( const char* filename, bool compact )
{
FILE* fp = callfopen( filename, "w" );
if ( !fp ) {
SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );
SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0, 0 );
return _errorID;
}
SaveFile(fp, compact);
@ -2000,7 +2186,7 @@ XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
{
// Clear any error from the last save, otherwise it will get reported
// for *this* call.
SetError(XML_SUCCESS, 0, 0);
ClearError();
XMLPrinter stream( fp, compact );
Print( &stream );
return _errorID;
@ -2012,7 +2198,7 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
Clear();
if ( len == 0 || !p || !*p ) {
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0, 0 );
return _errorID;
}
if ( len == (size_t)(-1) ) {
@ -2050,20 +2236,32 @@ void XMLDocument::Print( XMLPrinter* streamer ) const
}
void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
void XMLDocument::SetError( XMLError error, const char* str1, const char* str2, int lineNum )
{
TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
_errorID = error;
_errorStr1 = str1;
_errorStr2 = str2;
_errorStr1.Reset();
_errorStr2.Reset();
_errorLineNum = lineNum;
if (str1)
_errorStr1.SetStr(str1);
if (str2)
_errorStr2.SetStr(str2);
}
/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)
{
TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );
const char* errorName = _errorNames[errorID];
TIXMLASSERT( errorName && errorName[0] );
return errorName;
}
const char* XMLDocument::ErrorName() const
{
TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT );
const char* errorName = _errorNames[_errorID];
TIXMLASSERT( errorName && errorName[0] );
return errorName;
return ErrorIDToName(_errorID);
}
void XMLDocument::PrintError() const
@ -2073,18 +2271,18 @@ void XMLDocument::PrintError() const
char buf1[LEN] = { 0 };
char buf2[LEN] = { 0 };
if ( _errorStr1 ) {
TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
if ( !_errorStr1.Empty() ) {
TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1.GetStr() );
}
if ( _errorStr2 ) {
TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
if ( !_errorStr2.Empty() ) {
TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2.GetStr() );
}
// Should check INT_MIN <= _errorID && _errorId <= INT_MAX, but that
// causes a clang "always true" -Wtautological-constant-out-of-range-compare warning
TIXMLASSERT( 0 <= _errorID && XML_ERROR_COUNT - 1 <= INT_MAX );
printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n",
static_cast<int>( _errorID ), ErrorName(), buf1, buf2 );
printf( "XMLDocument error id=%d '%s' str1=%s str2=%s line=%d\n",
static_cast<int>( _errorID ), ErrorName(), buf1, buf2, _errorLineNum );
}
}
@ -2092,14 +2290,16 @@ void XMLDocument::Parse()
{
TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
TIXMLASSERT( _charBuffer );
_parseCurLineNum = 1;
_parseLineNum = 1;
char* p = _charBuffer;
p = XMLUtil::SkipWhiteSpace( p );
p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );
p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
if ( !*p ) {
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0, 0 );
return;
}
ParseDeep(p, 0 );
ParseDeep(p, 0, &_parseCurLineNum );
}
XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
@ -2117,7 +2317,7 @@ XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
}
for( int i=0; i<NUM_ENTITIES; ++i ) {
const char entityValue = entities[i].value;
TIXMLASSERT( 0 <= entityValue && entityValue < ENTITY_RANGE );
TIXMLASSERT( ((unsigned char)entityValue) < ENTITY_RANGE );
_entityFlag[ (unsigned char)entityValue ] = true;
}
_restrictedEntityFlag[(unsigned char)'&'] = true;
@ -2263,6 +2463,14 @@ void XMLPrinter::PushAttribute( const char* name, unsigned v )
}
void XMLPrinter::PushAttribute(const char* name, int64_t v)
{
char buf[BUF_SIZE];
XMLUtil::ToStr(v, buf, BUF_SIZE);
PushAttribute(name, buf);
}
void XMLPrinter::PushAttribute( const char* name, bool v )
{
char buf[BUF_SIZE];
@ -2328,6 +2536,13 @@ void XMLPrinter::PushText( const char* text, bool cdata )
}
}
void XMLPrinter::PushText( int64_t value )
{
char buf[BUF_SIZE];
XMLUtil::ToStr( value, buf, BUF_SIZE );
PushText( buf, false );
}
void XMLPrinter::PushText( int value )
{
char buf[BUF_SIZE];

View File

@ -40,6 +40,7 @@ distribution.
# include <cstdlib>
# include <cstring>
#endif
#include <stdint.h>
/*
TODO: intern strings instead of allocation.
@ -71,6 +72,8 @@ distribution.
# else
# define TINYXML2_LIB
# endif
#elif __GNUC__ >= 4
# define TINYXML2_LIB __attribute__((visibility("default")))
#else
# define TINYXML2_LIB
#endif
@ -95,9 +98,9 @@ distribution.
/* Versioning, past 1.0.14:
http://semver.org/
*/
static const int TIXML2_MAJOR_VERSION = 3;
static const int TIXML2_MAJOR_VERSION = 4;
static const int TIXML2_MINOR_VERSION = 0;
static const int TIXML2_PATCH_VERSION = 0;
static const int TIXML2_PATCH_VERSION = 1;
namespace tinyxml2
{
@ -124,18 +127,20 @@ public:
NEEDS_NEWLINE_NORMALIZATION = 0x02,
NEEDS_WHITESPACE_COLLAPSING = 0x04,
TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
ATTRIBUTE_NAME = 0,
ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
COMMENT = NEEDS_NEWLINE_NORMALIZATION
ATTRIBUTE_NAME = 0,
ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
COMMENT = NEEDS_NEWLINE_NORMALIZATION
};
StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
~StrPair();
void Set( char* start, char* end, int flags ) {
TIXMLASSERT( start );
TIXMLASSERT( end );
Reset();
_start = start;
_end = end;
@ -155,13 +160,13 @@ public:
void SetStr( const char* str, int flags=0 );
char* ParseText( char* in, const char* endTag, int strFlags );
char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
char* ParseName( char* in );
void TransferTo( StrPair* other );
void Reset();
private:
void Reset();
void CollapseWhitespace();
enum {
@ -206,7 +211,8 @@ public:
void Push( T t ) {
TIXMLASSERT( _size < INT_MAX );
EnsureCapacity( _size+1 );
_mem[_size++] = t;
_mem[_size] = t;
++_size;
}
T* PushArr( int count ) {
@ -220,7 +226,8 @@ public:
T Pop() {
TIXMLASSERT( _size > 0 );
return _mem[--_size];
--_size;
return _mem[_size];
}
void PopArr( int count ) {
@ -314,7 +321,7 @@ public:
/*
Template child class to create pools of the correct type.
*/
template< int SIZE >
template< int ITEM_SIZE >
class MemPoolT : public MemPool
{
public:
@ -337,7 +344,7 @@ public:
}
virtual int ItemSize() const {
return SIZE;
return ITEM_SIZE;
}
int CurrentAllocs() const {
return _currentAllocs;
@ -349,21 +356,23 @@ public:
Block* block = new Block();
_blockPtrs.Push( block );
for( int i=0; i<COUNT-1; ++i ) {
block->chunk[i].next = &block->chunk[i+1];
Item* blockItems = block->items;
for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
blockItems[i].next = &(blockItems[i + 1]);
}
block->chunk[COUNT-1].next = 0;
_root = block->chunk;
blockItems[ITEMS_PER_BLOCK - 1].next = 0;
_root = blockItems;
}
void* result = _root;
Item* const result = _root;
TIXMLASSERT( result != 0 );
_root = _root->next;
++_currentAllocs;
if ( _currentAllocs > _maxAllocs ) {
_maxAllocs = _currentAllocs;
}
_nAllocs++;
_nUntracked++;
++_nAllocs;
++_nUntracked;
return result;
}
@ -372,20 +381,21 @@ public:
return;
}
--_currentAllocs;
Chunk* chunk = static_cast<Chunk*>( mem );
Item* item = static_cast<Item*>( mem );
#ifdef DEBUG
memset( chunk, 0xfe, sizeof(Chunk) );
memset( item, 0xfe, sizeof( *item ) );
#endif
chunk->next = _root;
_root = chunk;
item->next = _root;
_root = item;
}
void Trace( const char* name ) {
printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
}
void SetTracked() {
_nUntracked--;
--_nUntracked;
}
int Untracked() const {
@ -401,21 +411,23 @@ public:
// 16k: 5200
// 32k: 4300
// 64k: 4000 21000
enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
// Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
// in private part if ITEMS_PER_BLOCK is private
enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
private:
MemPoolT( const MemPoolT& ); // not supported
void operator=( const MemPoolT& ); // not supported
union Chunk {
Chunk* next;
char mem[SIZE];
union Item {
Item* next;
char itemData[ITEM_SIZE];
};
struct Block {
Chunk chunk[COUNT];
Item items[ITEMS_PER_BLOCK];
};
DynArray< Block*, 10 > _blockPtrs;
Chunk* _root;
Item* _root;
int _currentAllocs;
int _nAllocs;
@ -518,16 +530,20 @@ enum XMLError {
class XMLUtil
{
public:
static const char* SkipWhiteSpace( const char* p ) {
static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) {
TIXMLASSERT( p );
while( IsWhiteSpace(*p) ) {
if (curLineNumPtr && *p == '\n') {
++(*curLineNumPtr);
}
++p;
}
TIXMLASSERT( p );
return p;
}
static char* SkipWhiteSpace( char* p ) {
return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
static char* SkipWhiteSpace( char* p, int* curLineNumPtr ) {
return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
}
// Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
@ -558,6 +574,9 @@ public:
if ( p == q ) {
return true;
}
TIXMLASSERT( p );
TIXMLASSERT( q );
TIXMLASSERT( nChar >= 0 );
return strncmp( p, q, nChar ) == 0;
}
@ -577,6 +596,7 @@ public:
static void ToStr( bool v, char* buffer, int bufferSize );
static void ToStr( float v, char* buffer, int bufferSize );
static void ToStr( double v, char* buffer, int bufferSize );
static void ToStr(int64_t v, char* buffer, int bufferSize);
// converts strings to primitive types
static bool ToInt( const char* str, int* value );
@ -584,6 +604,7 @@ public:
static bool ToBool( const char* str, bool* value );
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);
};
@ -689,6 +710,9 @@ public:
*/
void SetValue( const char* val, bool staticMem=false );
/// Gets the line number the node is in, if the document was parsed from a file.
int GetLineNum() const { return _parseLineNum; }
/// Get the parent of this node on the DOM.
const XMLNode* Parent() const {
return _parent;
@ -854,15 +878,30 @@ public:
*/
virtual bool Accept( XMLVisitor* visitor ) const = 0;
/**
Set user data into the XMLNode. TinyXML-2 in
no way processes or interprets user data.
It is initially 0.
*/
void SetUserData(void* userData) { _userData = userData; }
/**
Get user data set into the XMLNode. TinyXML-2 in
no way processes or interprets user data.
It is initially 0.
*/
void* GetUserData() const { return _userData; }
protected:
XMLNode( XMLDocument* );
virtual ~XMLNode();
virtual char* ParseDeep( char*, StrPair* );
virtual char* ParseDeep( char*, StrPair*, int* );
XMLDocument* _document;
XMLNode* _parent;
mutable StrPair _value;
int _parseLineNum;
XMLNode* _firstChild;
XMLNode* _lastChild;
@ -870,11 +909,14 @@ protected:
XMLNode* _prev;
XMLNode* _next;
void* _userData;
private:
MemPool* _memPool;
void Unlink( XMLNode* child );
static void DeleteNode( XMLNode* node );
void InsertChildPreamble( XMLNode* insertThis ) const;
const XMLElement* ToElementWithName( const char* name ) const;
XMLNode( const XMLNode& ); // not supported
XMLNode& operator=( const XMLNode& ); // not supported
@ -922,7 +964,7 @@ protected:
XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
virtual ~XMLText() {}
char* ParseDeep( char*, StrPair* endTag );
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
private:
bool _isCData;
@ -953,7 +995,7 @@ protected:
XMLComment( XMLDocument* doc );
virtual ~XMLComment();
char* ParseDeep( char*, StrPair* endTag );
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr);
private:
XMLComment( const XMLComment& ); // not supported
@ -992,7 +1034,7 @@ protected:
XMLDeclaration( XMLDocument* doc );
virtual ~XMLDeclaration();
char* ParseDeep( char*, StrPair* endTag );
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
private:
XMLDeclaration( const XMLDeclaration& ); // not supported
@ -1027,7 +1069,7 @@ protected:
XMLUnknown( XMLDocument* doc );
virtual ~XMLUnknown();
char* ParseDeep( char*, StrPair* endTag );
char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
private:
XMLUnknown( const XMLUnknown& ); // not supported
@ -1052,6 +1094,9 @@ public:
/// The value of the attribute.
const char* Value() const;
/// Gets the line number the attribute is in, if the document was parsed from a file.
int GetLineNum() const { return _parseLineNum; }
/// The next attribute in the list.
const XMLAttribute* Next() const {
return _next;
@ -1061,11 +1106,18 @@ public:
If the value isn't an integer, 0 will be returned. There is no error checking;
use QueryIntValue() if you need error checking.
*/
int IntValue() const {
int i=0;
QueryIntValue( &i );
return i;
}
int IntValue() const {
int i = 0;
QueryIntValue(&i);
return i;
}
int64_t Int64Value() const {
int64_t i = 0;
QueryInt64Value(&i);
return i;
}
/// Query as an unsigned integer. See IntValue()
unsigned UnsignedValue() const {
unsigned i=0;
@ -1092,13 +1144,15 @@ public:
}
/** QueryIntValue interprets the attribute as an integer, and returns the value
in the provided parameter. The function will return XML_NO_ERROR on success,
in the provided parameter. The function will return XML_SUCCESS on success,
and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
*/
XMLError QueryIntValue( int* value ) const;
/// See QueryIntValue
XMLError QueryUnsignedValue( unsigned int* value ) const;
/// See QueryIntValue
/// See QueryIntValue
XMLError QueryInt64Value(int64_t* value) const;
/// See QueryIntValue
XMLError QueryBoolValue( bool* value ) const;
/// See QueryIntValue
XMLError QueryDoubleValue( double* value ) const;
@ -1111,7 +1165,9 @@ public:
void SetAttribute( int value );
/// Set the attribute to value.
void SetAttribute( unsigned value );
/// Set the attribute to value.
/// Set the attribute to value.
void SetAttribute(int64_t value);
/// Set the attribute to value.
void SetAttribute( bool value );
/// Set the attribute to value.
void SetAttribute( double value );
@ -1128,10 +1184,11 @@ private:
void operator=( const XMLAttribute& ); // not supported
void SetName( const char* name );
char* ParseDeep( char* p, bool processEntities );
char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );
mutable StrPair _name;
mutable StrPair _value;
int _parseLineNum;
XMLAttribute* _next;
MemPool* _memPool;
};
@ -1188,42 +1245,25 @@ public:
const char* Attribute( const char* name, const char* value=0 ) const;
/** Given an attribute name, IntAttribute() returns the value
of the attribute interpreted as an integer. 0 will be
returned if there is an error. For a method with error
checking, see QueryIntAttribute()
of the attribute interpreted as an integer. The default
value will be returned if the attribute isn't present,
or if there is an error. (For a method with error
checking, see QueryIntAttribute()).
*/
int IntAttribute( const char* name ) const {
int i=0;
QueryIntAttribute( name, &i );
return i;
}
int IntAttribute(const char* name, int defaultValue = 0) const;
/// See IntAttribute()
unsigned UnsignedAttribute( const char* name ) const {
unsigned i=0;
QueryUnsignedAttribute( name, &i );
return i;
}
unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
/// See IntAttribute()
int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
/// See IntAttribute()
bool BoolAttribute(const char* name, bool defaultValue = false) const;
/// See IntAttribute()
bool BoolAttribute( const char* name ) const {
bool b=false;
QueryBoolAttribute( name, &b );
return b;
}
double DoubleAttribute(const char* name, double defaultValue = 0) const;
/// See IntAttribute()
double DoubleAttribute( const char* name ) const {
double d=0;
QueryDoubleAttribute( name, &d );
return d;
}
/// See IntAttribute()
float FloatAttribute( const char* name ) const {
float f=0;
QueryFloatAttribute( name, &f );
return f;
}
float FloatAttribute(const char* name, float defaultValue = 0) const;
/** Given an attribute name, QueryIntAttribute() returns
XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
can't be performed, or XML_NO_ATTRIBUTE if the attribute
doesn't exist. If successful, the result of the conversion
will be written to 'value'. If not successful, nothing will
@ -1242,7 +1282,8 @@ public:
}
return a->QueryIntValue( value );
}
/// See QueryIntAttribute()
/// See QueryIntAttribute()
XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
const XMLAttribute* a = FindAttribute( name );
if ( !a ) {
@ -1250,7 +1291,17 @@ public:
}
return a->QueryUnsignedValue( value );
}
/// See QueryIntAttribute()
/// See QueryIntAttribute()
XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
const XMLAttribute* a = FindAttribute(name);
if (!a) {
return XML_NO_ATTRIBUTE;
}
return a->QueryInt64Value(value);
}
/// See QueryIntAttribute()
XMLError QueryBoolAttribute( const char* name, bool* value ) const {
const XMLAttribute* a = FindAttribute( name );
if ( !a ) {
@ -1277,7 +1328,7 @@ public:
/** Given an attribute name, QueryAttribute() returns
XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
can't be performed, or XML_NO_ATTRIBUTE if the attribute
doesn't exist. It is overloaded for the primitive types,
and is a generally more convenient replacement of
@ -1301,6 +1352,10 @@ public:
return QueryUnsignedAttribute( name, value );
}
int QueryAttribute(const char* name, int64_t* value) const {
return QueryInt64Attribute(name, value);
}
int QueryAttribute( const char* name, bool* value ) const {
return QueryBoolAttribute( name, value );
}
@ -1328,7 +1383,14 @@ public:
XMLAttribute* a = FindOrCreateAttribute( name );
a->SetAttribute( value );
}
/// Sets the named attribute to value.
/// Sets the named attribute to value.
void SetAttribute(const char* name, int64_t value) {
XMLAttribute* a = FindOrCreateAttribute(name);
a->SetAttribute(value);
}
/// Sets the named attribute to value.
void SetAttribute( const char* name, bool value ) {
XMLAttribute* a = FindOrCreateAttribute( name );
a->SetAttribute( value );
@ -1425,7 +1487,9 @@ public:
void SetText( int value );
/// Convenience method for setting text inside an element. See SetText() for important limitations.
void SetText( unsigned value );
/// Convenience method for setting text inside an element. See SetText() for important limitations.
/// Convenience method for setting text inside an element. See SetText() for important limitations.
void SetText(int64_t value);
/// Convenience method for setting text inside an element. See SetText() for important limitations.
void SetText( bool value );
/// Convenience method for setting text inside an element. See SetText() for important limitations.
void SetText( double value );
@ -1461,13 +1525,28 @@ public:
XMLError QueryIntText( int* ival ) const;
/// See QueryIntText()
XMLError QueryUnsignedText( unsigned* uval ) const;
/// See QueryIntText()
/// See QueryIntText()
XMLError QueryInt64Text(int64_t* uval) const;
/// See QueryIntText()
XMLError QueryBoolText( bool* bval ) const;
/// See QueryIntText()
XMLError QueryDoubleText( double* dval ) const;
/// See QueryIntText()
XMLError QueryFloatText( float* fval ) const;
int IntText(int defaultValue = 0) const;
/// See QueryIntText()
unsigned UnsignedText(unsigned defaultValue = 0) const;
/// See QueryIntText()
int64_t Int64Text(int64_t defaultValue = 0) const;
/// See QueryIntText()
bool BoolText(bool defaultValue = false) const;
/// See QueryIntText()
double DoubleText(double defaultValue = 0) const;
/// See QueryIntText()
float FloatText(float defaultValue = 0) const;
// internal:
enum {
OPEN, // <foo>
@ -1481,7 +1560,7 @@ public:
virtual bool ShallowEqual( const XMLNode* compare ) const;
protected:
char* ParseDeep( char* p, StrPair* endTag );
char* ParseDeep( char* p, StrPair* endTag, int* curLineNumPtr );
private:
XMLElement( XMLDocument* doc );
@ -1494,8 +1573,9 @@ private:
}
XMLAttribute* FindOrCreateAttribute( const char* name );
//void LinkAttribute( XMLAttribute* attrib );
char* ParseAttributes( char* p );
char* ParseAttributes( char* p, int* curLineNumPtr );
static void DeleteAttribute( XMLAttribute* attribute );
XMLAttribute* CreateAttribute();
enum { BUF_SIZE = 200 };
int _closingType;
@ -1536,7 +1616,7 @@ public:
/**
Parse an XML file from a character string.
Returns XML_NO_ERROR (0) on success, or
Returns XML_SUCCESS (0) on success, or
an errorID.
You may optionally pass in the 'nBytes', which is
@ -1548,7 +1628,7 @@ public:
/**
Load an XML file from disk.
Returns XML_NO_ERROR (0) on success, or
Returns XML_SUCCESS (0) on success, or
an errorID.
*/
XMLError LoadFile( const char* filename );
@ -1561,14 +1641,14 @@ public:
not text in order for TinyXML-2 to correctly
do newline normalization.
Returns XML_NO_ERROR (0) on success, or
Returns XML_SUCCESS (0) on success, or
an errorID.
*/
XMLError LoadFile( FILE* );
/**
Save the XML file to disk.
Returns XML_NO_ERROR (0) on success, or
Returns XML_SUCCESS (0) on success, or
an errorID.
*/
XMLError SaveFile( const char* filename, bool compact = false );
@ -1577,7 +1657,7 @@ public:
Save the XML file to disk. You are responsible
for providing and closing the FILE*.
Returns XML_NO_ERROR (0) on success, or
Returns XML_SUCCESS (0) on success, or
an errorID.
*/
XMLError SaveFile( FILE* fp, bool compact = false );
@ -1671,7 +1751,11 @@ public:
*/
void DeleteNode( XMLNode* node );
void SetError( XMLError error, const char* str1, const char* str2 );
void SetError( XMLError error, const char* str1, const char* str2, int lineNum );
void ClearError() {
SetError(XML_SUCCESS, 0, 0, 0);
}
/// Return true if there was an error parsing the document.
bool Error() const {
@ -1682,14 +1766,20 @@ public:
return _errorID;
}
const char* ErrorName() const;
static const char* ErrorIDToName(XMLError errorID);
/// Return a possibly helpful diagnostic location or string.
const char* GetErrorStr1() const {
return _errorStr1;
return _errorStr1.GetStr();
}
/// Return a possibly helpful secondary diagnostic location or string.
const char* GetErrorStr2() const {
return _errorStr2;
return _errorStr2.GetStr();
}
/// Return the line where the error occured, or zero if unknown.
int GetErrorLineNum() const
{
return _errorLineNum;
}
/// If there is an error, print it to stdout.
void PrintError() const;
@ -1711,13 +1801,15 @@ private:
XMLDocument( const XMLDocument& ); // not supported
void operator=( const XMLDocument& ); // not supported
bool _writeBOM;
bool _processEntities;
XMLError _errorID;
Whitespace _whitespace;
const char* _errorStr1;
const char* _errorStr2;
char* _charBuffer;
bool _writeBOM;
bool _processEntities;
XMLError _errorID;
Whitespace _whitespace;
mutable StrPair _errorStr1;
mutable StrPair _errorStr2;
int _errorLineNum;
char* _charBuffer;
int _parseCurLineNum;
MemPoolT< sizeof(XMLElement) > _elementPool;
MemPoolT< sizeof(XMLAttribute) > _attributePool;
@ -1845,19 +1937,19 @@ public:
}
/// Safe cast to XMLElement. This can return null.
XMLElement* ToElement() {
return ( ( _node == 0 ) ? 0 : _node->ToElement() );
return ( _node ? _node->ToElement() : 0 );
}
/// Safe cast to XMLText. This can return null.
XMLText* ToText() {
return ( ( _node == 0 ) ? 0 : _node->ToText() );
return ( _node ? _node->ToText() : 0 );
}
/// Safe cast to XMLUnknown. This can return null.
XMLUnknown* ToUnknown() {
return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
return ( _node ? _node->ToUnknown() : 0 );
}
/// Safe cast to XMLDeclaration. This can return null.
XMLDeclaration* ToDeclaration() {
return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
return ( _node ? _node->ToDeclaration() : 0 );
}
private:
@ -1917,16 +2009,16 @@ public:
return _node;
}
const XMLElement* ToElement() const {
return ( ( _node == 0 ) ? 0 : _node->ToElement() );
return ( _node ? _node->ToElement() : 0 );
}
const XMLText* ToText() const {
return ( ( _node == 0 ) ? 0 : _node->ToText() );
return ( _node ? _node->ToText() : 0 );
}
const XMLUnknown* ToUnknown() const {
return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
return ( _node ? _node->ToUnknown() : 0 );
}
const XMLDeclaration* ToDeclaration() const {
return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
return ( _node ? _node->ToDeclaration() : 0 );
}
private:
@ -1998,7 +2090,8 @@ public:
void PushAttribute( const char* name, const char* value );
void PushAttribute( const char* name, int value );
void PushAttribute( const char* name, unsigned value );
void PushAttribute( const char* name, bool value );
void PushAttribute(const char* name, int64_t value);
void PushAttribute( const char* name, bool value );
void PushAttribute( const char* name, double value );
/// If streaming, close the Element.
virtual void CloseElement( bool compactMode=false );
@ -2009,7 +2102,9 @@ public:
void PushText( int value );
/// Add a text node from an unsigned.
void PushText( unsigned value );
/// Add a text node from a bool.
/// Add a text node from an unsigned.
void PushText(int64_t value);
/// Add a text node from a bool.
void PushText( bool value );
/// Add a text node from a float.
void PushText( float value );