mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-27 16:19:34 +00:00
Update usage of TinyXML to use TinyXML2
This commit is contained in:
parent
cd170910b2
commit
9a795e89f3
23 changed files with 865 additions and 1447 deletions
|
|
@ -21,13 +21,16 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "fsTinyXml.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "console/console.h"
|
||||
|
||||
bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding )
|
||||
bool VfsXMLDocument::LoadFile(const char* pFilename)
|
||||
{
|
||||
// Expand the file-path.
|
||||
char filenameBuffer[1024];
|
||||
Con::expandScriptFilename( filenameBuffer, sizeof(filenameBuffer), pFilename );
|
||||
Con::expandScriptFilename(filenameBuffer, sizeof(filenameBuffer), pFilename);
|
||||
|
||||
FileStream stream;
|
||||
|
||||
|
|
@ -38,15 +41,15 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding )
|
|||
#endif
|
||||
|
||||
// File open for read?
|
||||
if ( !stream.open( filenameBuffer, Torque::FS::File::Read ) )
|
||||
if (!stream.open(filenameBuffer, Torque::FS::File::Read))
|
||||
{
|
||||
// No, so warn.
|
||||
Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for parse.", filenameBuffer );
|
||||
Con::warnf("TamlXmlParser::parse() - Could not open filename '%s' for parse.", filenameBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load document from stream.
|
||||
if ( !LoadFile( stream ) )
|
||||
if (!LoadFile(stream))
|
||||
{
|
||||
// Warn!
|
||||
Con::warnf("TamlXmlParser: Could not load Taml XML file from stream.");
|
||||
|
|
@ -58,7 +61,7 @@ bool fsTiXmlDocument::LoadFile( const char * pFilename, TiXmlEncoding encoding )
|
|||
return true;
|
||||
}
|
||||
|
||||
bool fsTiXmlDocument::SaveFile( const char * pFilename ) const
|
||||
bool VfsXMLDocument::SaveFile(const char* pFilename)
|
||||
{
|
||||
// Expand the file-name into the file-path buffer.
|
||||
char filenameBuffer[1024];
|
||||
|
|
@ -67,10 +70,10 @@ bool fsTiXmlDocument::SaveFile( const char * pFilename ) const
|
|||
FileStream stream;
|
||||
|
||||
// File opened?
|
||||
if ( !stream.open( filenameBuffer, Torque::FS::File::Write ) )
|
||||
if (!stream.open(filenameBuffer, Torque::FS::File::Write))
|
||||
{
|
||||
// No, so warn.
|
||||
Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", filenameBuffer );
|
||||
Con::warnf("Taml::writeFile() - Could not open filename '%s' for write.", filenameBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -80,10 +83,80 @@ bool fsTiXmlDocument::SaveFile( const char * pFilename ) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool fsTiXmlDocument::LoadFile( FileStream &stream, TiXmlEncoding encoding )
|
||||
void VfsXMLDocument::ClearError()
|
||||
{
|
||||
_errorID = tinyxml2::XML_SUCCESS;
|
||||
_errorLineNum = 0;
|
||||
_errorStr.Reset();
|
||||
|
||||
tinyxml2::XMLDocument::ClearError();
|
||||
}
|
||||
|
||||
void VfsXMLDocument::SetError(tinyxml2::XMLError error, int lineNum, const char* format, ...)
|
||||
{
|
||||
TIXMLASSERT(error >= 0 && error < tinyxml2::XML_ERROR_COUNT);
|
||||
_errorID = error;
|
||||
_errorLineNum = lineNum;
|
||||
_errorStr.Reset();
|
||||
|
||||
const size_t BUFFER_SIZE = 1000;
|
||||
char* buffer = new char[BUFFER_SIZE];
|
||||
|
||||
TIXMLASSERT(sizeof(error) <= sizeof(int));
|
||||
dSprintf(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);
|
||||
|
||||
if (format) {
|
||||
size_t len = strlen(buffer);
|
||||
dSprintf(buffer + len, BUFFER_SIZE - len, ": ");
|
||||
len = strlen(buffer);
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
dSprintf(buffer + len, BUFFER_SIZE - len, format, va);
|
||||
va_end(va);
|
||||
}
|
||||
_errorStr.SetStr(buffer);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
VfsXMLPrinter::VfsXMLPrinter(FileStream& stream, bool compact, int depth)
|
||||
: XMLPrinter(NULL, compact, depth),
|
||||
m_Stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
VfsXMLPrinter::~VfsXMLPrinter()
|
||||
{
|
||||
m_Stream.flush();
|
||||
m_Stream.close();
|
||||
}
|
||||
|
||||
void VfsXMLPrinter::Print(const char* format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
m_Stream.writeFormattedBuffer(format, va);
|
||||
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void VfsXMLPrinter::Write(const char* data, size_t size)
|
||||
{
|
||||
m_Stream.write(size, data);
|
||||
}
|
||||
|
||||
void VfsXMLPrinter::Putc(char ch)
|
||||
{
|
||||
m_Stream.write(static_cast<U8>(ch));
|
||||
}
|
||||
|
||||
bool VfsXMLDocument::LoadFile(FileStream& stream)
|
||||
{
|
||||
// Delete the existing data:
|
||||
Clear();
|
||||
// Clear shadowed error
|
||||
ClearError();
|
||||
//TODO: Can't clear location, investigate if this gives issues.
|
||||
//doc.location.Clear();
|
||||
|
||||
|
|
@ -91,9 +164,9 @@ bool fsTiXmlDocument::LoadFile( FileStream &stream, TiXmlEncoding encoding )
|
|||
long length = stream.getStreamSize();
|
||||
|
||||
// Strange case, but good to handle up front.
|
||||
if ( length <= 0 )
|
||||
if (length <= 0)
|
||||
{
|
||||
SetError( TiXmlDocument::TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
SetError(tinyxml2::XML_ERROR_EMPTY_DOCUMENT, 0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -118,12 +191,13 @@ bool fsTiXmlDocument::LoadFile( FileStream &stream, TiXmlEncoding encoding )
|
|||
}
|
||||
*/
|
||||
|
||||
char* buf = new char[ length+1 ];
|
||||
char* buf = new char[length + 1];
|
||||
buf[0] = 0;
|
||||
|
||||
if ( !stream.read( length, buf ) ) {
|
||||
if (!stream.read(length, buf))
|
||||
{
|
||||
delete [] buf;
|
||||
SetError( TiXmlDocument::TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
SetError(tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -138,610 +212,48 @@ bool fsTiXmlDocument::LoadFile( FileStream &stream, TiXmlEncoding encoding )
|
|||
// * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
|
||||
// * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
|
||||
|
||||
const char* p = buf; // the read head
|
||||
char* q = buf; // the write head
|
||||
const char* p = buf; // the read head
|
||||
char* q = buf; // the write head
|
||||
const char CR = 0x0d;
|
||||
const char LF = 0x0a;
|
||||
|
||||
buf[length] = 0;
|
||||
while( *p ) {
|
||||
assert( p < (buf+length) );
|
||||
assert( q <= (buf+length) );
|
||||
assert( q <= p );
|
||||
while (*p)
|
||||
{
|
||||
assert(p < (buf+length));
|
||||
assert(q <= (buf+length));
|
||||
assert(q <= p);
|
||||
|
||||
if ( *p == CR ) {
|
||||
if (*p == CR)
|
||||
{
|
||||
*q++ = LF;
|
||||
p++;
|
||||
if ( *p == LF ) { // check for CR+LF (and skip LF)
|
||||
if (*p == LF)
|
||||
{
|
||||
// check for CR+LF (and skip LF)
|
||||
p++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
*q++ = *p++;
|
||||
}
|
||||
}
|
||||
assert( q <= (buf+length) );
|
||||
assert(q <= (buf+length));
|
||||
*q = 0;
|
||||
|
||||
Parse( buf, 0, encoding );
|
||||
Parse(buf, length);
|
||||
|
||||
delete [] buf;
|
||||
return !Error();
|
||||
}
|
||||
|
||||
bool fsTiXmlDocument::SaveFile( FileStream &stream ) const
|
||||
bool VfsXMLDocument::SaveFile(FileStream& stream)
|
||||
{
|
||||
if ( useMicrosoftBOM )
|
||||
{
|
||||
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
|
||||
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
|
||||
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
|
||||
|
||||
stream.write( TIXML_UTF_LEAD_0 );
|
||||
stream.write( TIXML_UTF_LEAD_1 );
|
||||
stream.write( TIXML_UTF_LEAD_2 );
|
||||
}
|
||||
Print( stream, 0 );
|
||||
return true;
|
||||
// Clear any error from the last save, otherwise it will get reported
|
||||
// for *this* call.
|
||||
ClearError();
|
||||
VfsXMLPrinter printer(stream, false, 0);
|
||||
Print(&printer);
|
||||
return !Error();
|
||||
}
|
||||
|
||||
void fsTiXmlDocument::Print( FileStream& stream, int depth ) const
|
||||
{
|
||||
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
|
||||
{
|
||||
//AttemptPrintTiNode(const_cast<TiXmlNode*>(node), stream, depth);
|
||||
dynamic_cast<const fsTiXmlNode*>(node)->Print( stream, depth );
|
||||
stream.writeText( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
void fsTiXmlAttribute::Print( FileStream& stream, int depth, TIXML_STRING* str ) const
|
||||
{
|
||||
TIXML_STRING n, v;
|
||||
|
||||
TiXmlString val = TiXmlString(Value());
|
||||
|
||||
EncodeString( NameTStr(), &n );
|
||||
EncodeString( val, &v );
|
||||
|
||||
for ( int i=0; i< depth; i++ ) {
|
||||
stream.writeText( " " );
|
||||
}
|
||||
|
||||
if (val.find ('\"') == TIXML_STRING::npos) {
|
||||
const char* pValue = v.c_str();
|
||||
char buffer[4096];
|
||||
const S32 length = dSprintf(buffer, sizeof(buffer), "%s=\"%s\"", n.c_str(), pValue);
|
||||
stream.write(length, buffer);
|
||||
if ( str ) {
|
||||
(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
|
||||
}
|
||||
}
|
||||
else {
|
||||
char buffer[4096];
|
||||
const S32 length = dSprintf(buffer, sizeof(buffer), "%s='%s'", n.c_str(), v.c_str());
|
||||
stream.write(length, buffer);
|
||||
if ( str ) {
|
||||
(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fsTiXmlDeclaration::Print(FileStream& stream, int depth, TiXmlString* str) const
|
||||
{
|
||||
stream.writeStringBuffer( "<?xml " );
|
||||
if ( str ) (*str) += "<?xml ";
|
||||
|
||||
if ( !version.empty() ) {
|
||||
stream.writeFormattedBuffer( "version=\"%s\" ", version.c_str ());
|
||||
if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
|
||||
}
|
||||
if ( !encoding.empty() ) {
|
||||
stream.writeFormattedBuffer( "encoding=\"%s\" ", encoding.c_str ());
|
||||
if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
|
||||
}
|
||||
if ( !standalone.empty() ) {
|
||||
stream.writeFormattedBuffer( "standalone=\"%s\" ", standalone.c_str ());
|
||||
if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
|
||||
}
|
||||
stream.writeStringBuffer( "?>" );
|
||||
if ( str ) (*str) += "?>";
|
||||
}
|
||||
|
||||
void fsTiXmlElement::Print(FileStream& stream, int depth) const
|
||||
{
|
||||
int i;
|
||||
for ( i=0; i<depth; i++ ) {
|
||||
stream.writeStringBuffer( " " );
|
||||
}
|
||||
|
||||
stream.writeFormattedBuffer( "<%s", value.c_str() );
|
||||
|
||||
const TiXmlAttribute* attrib;
|
||||
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
|
||||
{
|
||||
stream.writeStringBuffer( "\n" );
|
||||
dynamic_cast<const fsTiXmlAttribute*>(attrib)->Print( stream, depth+1 );
|
||||
}
|
||||
|
||||
// There are 3 different formatting approaches:
|
||||
// 1) An element without children is printed as a <foo /> node
|
||||
// 2) An element with only a text child is printed as <foo> text </foo>
|
||||
// 3) An element with children is printed on multiple lines.
|
||||
TiXmlNode* node;
|
||||
if ( !firstChild )
|
||||
{
|
||||
stream.writeStringBuffer( " />" );
|
||||
}
|
||||
else if ( firstChild == lastChild && firstChild->ToText() )
|
||||
{
|
||||
stream.writeStringBuffer( ">" );
|
||||
dynamic_cast<const fsTiXmlNode*>(firstChild)->Print( stream, depth + 1 );
|
||||
stream.writeFormattedBuffer( "</%s>", value.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.writeStringBuffer( ">" );
|
||||
|
||||
for ( node = firstChild; node; node=node->NextSibling() )
|
||||
{
|
||||
if ( !node->ToText() )
|
||||
{
|
||||
stream.writeStringBuffer( "\n" );
|
||||
}
|
||||
dynamic_cast<const fsTiXmlNode*>(node)->Print( stream, depth+1 );
|
||||
}
|
||||
stream.writeStringBuffer( "\n" );
|
||||
for( i=0; i<depth; ++i ) {
|
||||
stream.writeStringBuffer( " " );
|
||||
}
|
||||
stream.writeFormattedBuffer( "</%s>", value.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
void fsTiXmlComment::Print(FileStream& stream, int depth) const
|
||||
{
|
||||
for ( int i=0; i<depth; i++ )
|
||||
{
|
||||
stream.writeStringBuffer( " " );
|
||||
}
|
||||
stream.writeFormattedBuffer( "<!--%s-->", value.c_str() );
|
||||
}
|
||||
|
||||
void fsTiXmlText::Print(FileStream& stream, int depth) const
|
||||
{
|
||||
if ( cdata )
|
||||
{
|
||||
int i;
|
||||
stream.writeStringBuffer( "\n" );
|
||||
for ( i=0; i<depth; i++ ) {
|
||||
stream.writeStringBuffer( " " );
|
||||
}
|
||||
stream.writeFormattedBuffer( "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
|
||||
}
|
||||
else
|
||||
{
|
||||
TIXML_STRING buffer;
|
||||
EncodeString( value, &buffer );
|
||||
stream.writeFormattedBuffer( "%s", buffer.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
void fsTiXmlUnknown::Print(FileStream& stream, int depth) const
|
||||
{
|
||||
for ( int i=0; i<depth; i++ )
|
||||
stream.writeStringBuffer( " " );
|
||||
|
||||
stream.writeFormattedBuffer( "<%s>", value.c_str() );
|
||||
}
|
||||
|
||||
static TiXmlNode* TiNodeIdentify( TiXmlNode* parent, const char* p, TiXmlEncoding encoding )
|
||||
{
|
||||
TiXmlNode* returnNode = 0;
|
||||
|
||||
p = TiXmlNode::SkipWhiteSpace( p, encoding );
|
||||
if( !p || !*p || *p != '<' )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = TiXmlNode::SkipWhiteSpace( p, encoding );
|
||||
|
||||
if ( !p || !*p )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// What is this thing?
|
||||
// - Elements start with a letter or underscore, but xml is reserved.
|
||||
// - Comments: <!--
|
||||
// - Decleration: <?xml
|
||||
// - Everthing else is unknown to tinyxml.
|
||||
//
|
||||
|
||||
const char* xmlHeader = { "<?xml" };
|
||||
const char* commentHeader = { "<!--" };
|
||||
const char* dtdHeader = { "<!" };
|
||||
const char* cdataHeader = { "<![CDATA[" };
|
||||
|
||||
if ( TiXmlNode::StringEqual( p, xmlHeader, true, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Declaration\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlDeclaration();
|
||||
}
|
||||
else if ( TiXmlNode::StringEqual( p, commentHeader, false, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Comment\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlComment();
|
||||
}
|
||||
else if ( TiXmlNode::StringEqual( p, cdataHeader, false, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing CDATA\n" );
|
||||
#endif
|
||||
TiXmlText* text = new fsTiXmlText( "" );
|
||||
text->SetCDATA( true );
|
||||
returnNode = text;
|
||||
}
|
||||
else if ( TiXmlNode::StringEqual( p, dtdHeader, false, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Unknown(1)\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlUnknown();
|
||||
}
|
||||
else if ( TiXmlNode::IsAlpha( *(p+1), encoding )
|
||||
|| *(p+1) == '_' )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Element\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlElement( "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Unknown(2)\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlUnknown();
|
||||
}
|
||||
|
||||
if ( returnNode )
|
||||
{
|
||||
// Set the parent, so it can report errors
|
||||
returnNode->parent = parent;
|
||||
}
|
||||
return returnNode;
|
||||
}
|
||||
|
||||
TiXmlNode* fsTiXmlDocument::Identify( const char* p, TiXmlEncoding encoding )
|
||||
{
|
||||
return TiNodeIdentify(this, p, encoding);
|
||||
}
|
||||
|
||||
TiXmlNode* fsTiXmlElement::Identify( const char* p, TiXmlEncoding encoding )
|
||||
{
|
||||
return TiNodeIdentify(this, p, encoding);
|
||||
}
|
||||
|
||||
const char* fsTiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
|
||||
{
|
||||
p = SkipWhiteSpace( p, encoding );
|
||||
TiXmlDocument* document = GetDocument();
|
||||
|
||||
if ( !p || !*p )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( data )
|
||||
{
|
||||
data->Stamp( p, encoding );
|
||||
location = data->Cursor();
|
||||
}
|
||||
|
||||
if ( *p != '<' )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = SkipWhiteSpace( p+1, encoding );
|
||||
|
||||
// Read the name.
|
||||
const char* pErr = p;
|
||||
|
||||
p = ReadName( p, &value, encoding );
|
||||
if ( !p || !*p )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
TIXML_STRING endTag ("</");
|
||||
endTag += value;
|
||||
|
||||
// Check for and read attributes. Also look for an empty
|
||||
// tag or an end tag.
|
||||
while ( p && *p )
|
||||
{
|
||||
pErr = p;
|
||||
p = SkipWhiteSpace( p, encoding );
|
||||
if ( !p || !*p )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
if ( *p == '/' )
|
||||
{
|
||||
++p;
|
||||
// Empty tag.
|
||||
if ( *p != '>' )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
return (p+1);
|
||||
}
|
||||
else if ( *p == '>' )
|
||||
{
|
||||
// Done with attributes (if there were any.)
|
||||
// Read the value -- which can include other
|
||||
// elements -- read the end tag, and return.
|
||||
++p;
|
||||
p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
|
||||
if ( !p || !*p ) {
|
||||
// We were looking for the end tag, but found nothing.
|
||||
// Fix for [ 1663758 ] Failure to report error on bad XML
|
||||
if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We should find the end tag now
|
||||
// note that:
|
||||
// </foo > and
|
||||
// </foo>
|
||||
// are both valid end tags.
|
||||
if ( StringEqual( p, endTag.c_str(), false, encoding ) )
|
||||
{
|
||||
p += endTag.length();
|
||||
p = SkipWhiteSpace( p, encoding );
|
||||
if ( p && *p && *p == '>' ) {
|
||||
++p;
|
||||
return p;
|
||||
}
|
||||
if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to read an attribute:
|
||||
TiXmlAttribute* attrib = new fsTiXmlAttribute();
|
||||
if ( !attrib )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
attrib->SetDocument( document );
|
||||
pErr = p;
|
||||
p = attrib->Parse( p, data, encoding );
|
||||
|
||||
if ( !p || !*p )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
|
||||
delete attrib;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle the strange case of double attributes:
|
||||
#ifdef TIXML_USE_STL
|
||||
TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
|
||||
#else
|
||||
TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
|
||||
#endif
|
||||
if ( node )
|
||||
{
|
||||
if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
|
||||
delete attrib;
|
||||
return 0;
|
||||
}
|
||||
|
||||
attributeSet.Add( attrib );
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
TiXmlNode* fsTiXmlNode::Identify(char const* p, TiXmlEncoding encoding)
|
||||
{
|
||||
TiXmlNode* returnNode = 0;
|
||||
|
||||
p = TiXmlBase::SkipWhiteSpace( p, encoding );
|
||||
if( !p || !*p || *p != '<' )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = TiXmlBase::SkipWhiteSpace( p, encoding );
|
||||
|
||||
if ( !p || !*p )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// What is this thing?
|
||||
// - Elements start with a letter or underscore, but xml is reserved.
|
||||
// - Comments: <!--
|
||||
// - Decleration: <?xml
|
||||
// - Everthing else is unknown to tinyxml.
|
||||
//
|
||||
|
||||
const char* xmlHeader = { "<?xml" };
|
||||
const char* commentHeader = { "<!--" };
|
||||
const char* dtdHeader = { "<!" };
|
||||
const char* cdataHeader = { "<![CDATA[" };
|
||||
|
||||
if ( TiXmlBase::StringEqual( p, xmlHeader, true, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Declaration\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlDeclaration();
|
||||
}
|
||||
else if ( TiXmlBase::StringEqual( p, commentHeader, false, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Comment\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlComment();
|
||||
}
|
||||
else if ( TiXmlBase::StringEqual( p, cdataHeader, false, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing CDATA\n" );
|
||||
#endif
|
||||
fsTiXmlText* text = new fsTiXmlText( "" );
|
||||
text->SetCDATA( true );
|
||||
returnNode = text;
|
||||
}
|
||||
else if ( TiXmlBase::StringEqual( p, dtdHeader, false, encoding ) )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Unknown(1)\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlUnknown();
|
||||
}
|
||||
else if ( TiXmlBase::IsAlpha( *(p+1), encoding )
|
||||
|| *(p+1) == '_' )
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Element\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlElement( "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_PARSER
|
||||
TIXML_LOG( "XML parsing Unknown(2)\n" );
|
||||
#endif
|
||||
returnNode = new fsTiXmlUnknown();
|
||||
}
|
||||
|
||||
if ( returnNode )
|
||||
{
|
||||
// Set the parent, so it can report errors
|
||||
returnNode->parent = this;
|
||||
}
|
||||
return returnNode;
|
||||
}
|
||||
|
||||
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
|
||||
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
|
||||
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
|
||||
|
||||
char const* fsTiXmlDocument::Parse(char const* p, TiXmlParsingData* prevData, TiXmlEncoding encoding)
|
||||
{
|
||||
ClearError();
|
||||
|
||||
// Parse away, at the document level. Since a document
|
||||
// contains nothing but other tags, most of what happens
|
||||
// here is skipping white space.
|
||||
if ( !p || !*p )
|
||||
{
|
||||
SetError( TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note that, for a document, this needs to come
|
||||
// before the while space skip, so that parsing
|
||||
// starts from the pointer we are given.
|
||||
location.Clear();
|
||||
if ( prevData )
|
||||
{
|
||||
location.row = prevData->Cursor().row;
|
||||
location.col = prevData->Cursor().col;
|
||||
}
|
||||
else
|
||||
{
|
||||
location.row = 0;
|
||||
location.col = 0;
|
||||
}
|
||||
TiXmlParsingData data( p, TabSize(), location.row, location.col );
|
||||
location = data.Cursor();
|
||||
|
||||
if ( encoding == TIXML_ENCODING_UNKNOWN )
|
||||
{
|
||||
// Check for the Microsoft UTF-8 lead bytes.
|
||||
const unsigned char* pU = (const unsigned char*)p;
|
||||
if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
|
||||
&& *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
|
||||
&& *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
|
||||
{
|
||||
encoding = TIXML_ENCODING_UTF8;
|
||||
useMicrosoftBOM = true;
|
||||
}
|
||||
}
|
||||
|
||||
p = TiXmlBase::SkipWhiteSpace( p, encoding );
|
||||
if ( !p )
|
||||
{
|
||||
SetError( TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ( p && *p )
|
||||
{
|
||||
TiXmlNode* node = fsTiXmlNode::Identify( p, encoding );
|
||||
if ( node )
|
||||
{
|
||||
p = node->Parse( p, &data, encoding );
|
||||
LinkEndChild( node );
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Did we get encoding info?
|
||||
if ( encoding == TIXML_ENCODING_UNKNOWN
|
||||
&& node->ToDeclaration() )
|
||||
{
|
||||
TiXmlDeclaration* dec = node->ToDeclaration();
|
||||
const char* enc = dec->Encoding();
|
||||
assert( enc );
|
||||
|
||||
if ( *enc == 0 )
|
||||
encoding = TIXML_ENCODING_UTF8;
|
||||
else if ( TiXmlBase::StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
|
||||
encoding = TIXML_ENCODING_UTF8;
|
||||
else if ( TiXmlBase::StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
|
||||
encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
|
||||
else
|
||||
encoding = TIXML_ENCODING_LEGACY;
|
||||
}
|
||||
|
||||
p = TiXmlBase::SkipWhiteSpace( p, encoding );
|
||||
}
|
||||
|
||||
// Was this empty?
|
||||
if ( !firstChild ) {
|
||||
SetError( TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// All is well.
|
||||
return p;
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue