diff --git a/tinyxml2.cpp b/tinyxml2.cpp index 140df86..3ec4f6d 100755 --- a/tinyxml2.cpp +++ b/tinyxml2.cpp @@ -1039,7 +1039,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) } } if ( !wellLocated ) { - _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "value: %s", decl->Value()); + _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); DeleteNode( node ); break; } @@ -1074,7 +1074,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) } } if ( mismatch ) { - _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "name=%s", ele->Name()); + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); DeleteNode( node ); break; } @@ -1811,7 +1811,7 @@ char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) while( p ) { p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); if ( !(*p) ) { - _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "element name=%s", Name() ); + _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); return 0; } @@ -1826,7 +1826,7 @@ char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); if ( !p || Attribute( attrib->Name() ) ) { DeleteAttribute( attrib ); - _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "element name=%s", Name() ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); return 0; } // There is a minor bug here: if the attribute in the source xml @@ -2153,7 +2153,7 @@ XMLError XMLDocument::LoadFile( const char* filename ) Clear(); FILE* fp = callfopen( filename, "rb" ); if ( !fp ) { - SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ); + SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ? filename : ""); return _errorID; } LoadFile( fp ); @@ -2234,7 +2234,7 @@ XMLError XMLDocument::SaveFile( const char* filename, bool compact ) { FILE* fp = callfopen( filename, "w" ); if ( !fp ) { - SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ); + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ? filename : ""); return _errorID; } SaveFile(fp, compact); @@ -2307,7 +2307,7 @@ void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... if (format) { size_t BUFFER_SIZE = 1000; char* buffer = new char[BUFFER_SIZE]; - TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d line=%d ", ErrorIDToName(error), int(error), lineNum); + TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d: ", ErrorIDToName(error), int(error), int(error), lineNum); size_t len = strlen(buffer); va_list va; @@ -2329,34 +2329,22 @@ void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... return errorName; } -const char* XMLDocument::GetErrorStr() const +const char* XMLDocument::ErrorStr() const { return _errorStr.Empty() ? "" : _errorStr.GetStr(); } + +void XMLDocument::PrintError() const +{ + printf("%s\n", ErrorStr()); +} + const char* XMLDocument::ErrorName() const { return ErrorIDToName(_errorID); } -void XMLDocument::PrintError() const -{ - if ( Error() ) { - static const int LEN = 20; - char buf1[LEN] = { 0 }; - char buf2[LEN] = { 0 }; - - if ( !_errorStr.Empty() ) { - TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr.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 line=%d\n", - static_cast( _errorID ), ErrorName(), buf1, buf2, _errorLineNum ); - } -} - void XMLDocument::Parse() { TIXMLASSERT( NoChildren() ); // Clear() must have been called previously diff --git a/tinyxml2.h b/tinyxml2.h index ecab407..c9850f6 100755 --- a/tinyxml2.h +++ b/tinyxml2.h @@ -1634,6 +1634,13 @@ enum Whitespace { class TINYXML2_LIB XMLDocument : public XMLNode { friend class XMLElement; + // Gives access to SetError, but over-access for everything else. + // Wishing C++ had "internal" scope. + friend class XMLNode; + friend class XMLText; + friend class XMLComment; + friend class XMLDeclaration; + friend class XMLUnknown; public: /// constructor XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); @@ -1785,8 +1792,6 @@ public: */ void DeleteNode( XMLNode* node ); - void SetError( XMLError error, int lineNum, const char* format, ... ); - void ClearError() { SetError(XML_SUCCESS, 0, 0); } @@ -1802,16 +1807,19 @@ public: const char* ErrorName() const; static const char* ErrorIDToName(XMLError errorID); - /// Return a possibly helpful diagnostic location or string. - const char* GetErrorStr() const; + /** Returns a "long form" error description. A hopefully helpful + diagnostic with location, line number, and/or additional info. + */ + const char* ErrorStr() const; + + /// A (trivial) utility function that prints the ErrorStr() to stdout. + void PrintError() const; /// Return the line where the error occured, or zero if unknown. - int GetErrorLineNum() const + int ErrorLineNum() const { return _errorLineNum; } - /// If there is an error, print it to stdout. - void PrintError() const; /// Clear the document, resetting it to the initial state. void Clear(); @@ -1867,6 +1875,8 @@ private: void Parse(); + void SetError( XMLError error, int lineNum, const char* format, ... ); + template NodeType* CreateUnlinkedNode( MemPoolT& pool ); }; diff --git a/xmltest.cpp b/xmltest.cpp index 01b5011..a297722 100644 --- a/xmltest.cpp +++ b/xmltest.cpp @@ -499,13 +499,9 @@ int main( int argc, const char ** argv ) int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", replacementIntValue ); XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 ); XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result ); - doc->PrintError(); XMLTest( "Programmatic DOM", defaultIntValue, value1 ); XMLTest( "Programmatic DOM", replacementIntValue, value2 ); - - exit(0); - doc->Print(); { @@ -1958,11 +1954,9 @@ int main( int argc, const char ** argv ) XMLDocument doc; for( int i = 0; i < XML_ERROR_COUNT; i++ ) { const XMLError error = static_cast(i); - doc.SetError( error, 0, 0, 0 ); - XMLTest( "ErrorID() after SetError()", error, doc.ErrorID() ); - const char* name = doc.ErrorName(); - XMLTest( "ErrorName() after SetError()", true, name != 0 ); - XMLTest( "ErrorName() after SetError()", true, strlen(name) > 0 ); + const char* name = XMLDocument::ErrorIDToName(error); + XMLTest( "ErrorName() after ClearError()", true, name != 0 ); + XMLTest( "ErrorName() after ClearError()", true, strlen(name) > 0 ); } } @@ -2060,7 +2054,7 @@ int main( int argc, const char ** argv ) XMLTest(testString, parseError, doc.ErrorID()); XMLTest(testString, true, doc.Error()); XMLTest(testString, expected_error, parseError); - XMLTest(testString, expectedLine, doc.GetErrorLineNum()); + XMLTest(testString, expectedLine, doc.ErrorLineNum()); }; void TestStringLines(const char *testString, const char *docStr, const char *expectedLines) @@ -2178,6 +2172,18 @@ int main( int argc, const char ** argv ) "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10"); } + { + const char* xml = "Text"; + XMLDocument doc; + doc.Parse(xml); + XMLTest("Test mismatched elements.", true, doc.Error()); + XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID()); + // For now just make sure calls work & doesn't crash. + // May solidify the error output in the future. + printf("%s\n", doc.ErrorStr()); + doc.PrintError(); + } + // ----------- Performance tracking -------------- { #if defined( _MSC_VER )