Files
FC1/CrySystem/XML/_XMLDOMParserImpl.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

238 lines
5.5 KiB
C++

// _XMLDOMParserImpl.cpp: implementation of the _XMLDOMParserImpl class.
//
//////////////////////////////////////////////////////////////////////
//#ifndef _XBOX
#include "stdafx.h"
//#endif
#include "_XMLDOMParserImpl.h"
#if !defined(LINUX)
#include <assert.h>
#endif
#define XMLPARSEAPI(type) type
#include "expat\expat.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
_XMLDOMParserImpl::_XMLDOMParserImpl(XDOM::IXMLDOMDocument *pDoc)
{
m_pDoc=pDoc;
m_nFilePos=0;
}
_XMLDOMParserImpl::~_XMLDOMParserImpl()
{
}
void _XMLDOMParserImpl::StartDocument(bool unicode)
{
m_bUnicode=unicode;
}
void _XMLDOMParserImpl::StartElement( const char *name)
{
XDOM::IXMLDOMNode *pParent=NULL;
XDOM::IXMLDOMNode *pNode=NULL;
if (!nodeStack.empty()) {
pParent = nodeStack.back();
pNode=m_pDoc->createNode(XDOM::NODE_ELEMENT,name);
} else {
m_pDoc->setName(name);
pNode=m_pDoc;
}
nodeStack.push_back(pNode);
if (pParent) {
pParent->appendChild( pNode );
}
}
void _XMLDOMParserImpl::EndElement()
{
assert( !nodeStack.empty() );
if (!nodeStack.empty()) {
nodeStack.pop_back();
}
}
void _XMLDOMParserImpl::Data( const char *data )
{
assert( !nodeStack.empty() );
if (!nodeStack.empty())
{
XDOM::IXMLDOMNode *pNode = nodeStack.back();
const char *sPrevText = pNode->getText();
if (strlen(sPrevText) == 0)
pNode->setText(data);
else
{
std::string addstr = sPrevText;
addstr += data;
pNode->setText(addstr.c_str());
}
}
}
void _XMLDOMParserImpl::Attribute( const char *name,const char *value)
{
XDOM::IXMLDOMNode *pNode=NULL;
if (!nodeStack.empty())
{
pNode=nodeStack.back();
}
else
{
pNode=m_pDoc;
}
XDOM::IXMLDOMNode *pAttr=NULL;
pAttr=m_pDoc->createNode(XDOM::NODE_ATTRIBUTE,name);
pAttr->setText(value);
pNode->appendChild(pAttr);
}
void _XMLDOMParserImpl::EndDocument(const char *error)
{
if(error){
m_bErrorState=true;
m_sErrorString=error;
}
m_sErrorString="";
m_bErrorState=false;
}
unsigned int _XMLDOMParserImpl::GetByte()
{
if(m_nFilePos>=(int)(m_pBuffer->size()))return -1;
return ((unsigned int)(*m_pBuffer)[m_nFilePos++]);
}
//////////////////////////////////////////////////////////////////////////
// Expat Callbacks.
//////////////////////////////////////////////////////////////////////////
static void EXPAT_XML_StartElement(void *userData, const char *name, const char **atts)
{
((_XMLDOMParserImpl*)userData)->OnStartElement( name,atts );
}
static void EXPAT_XML_EndElement(void *userData, const char *name )
{
((_XMLDOMParserImpl*)userData)->OnEndElement( name );
}
static void EXPAT_XML_CharacterData( void *userData, const char *s, int len )
{
((_XMLDOMParserImpl*)userData)->OnCharacterData( s,len );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Processing of Expat callbacks.
//////////////////////////////////////////////////////////////////////////
void _XMLDOMParserImpl::OnStartElement( const char *name, const char **atts )
{
StartElement( name );
int i = 0;
while (atts[i] != 0)
{
Attribute( atts[i],atts[i+1] );
i += 2;
}
}
//////////////////////////////////////////////////////////////////////////
void _XMLDOMParserImpl::OnEndElement( const char *name )
{
EndElement();
}
//////////////////////////////////////////////////////////////////////////
// Local string trimming functions.
//////////////////////////////////////////////////////////////////////////
namespace
{
void string_ltrim( String &str, const char* whitespace )
{
size_t idx = str.find_first_not_of(whitespace);
if (idx == 0)
return;
else if( idx != String::npos)
str = str.substr(idx);
else
str = "";
}
void string_rtrim( String &str, const char* whitespace )
{
size_t idx = str.find_last_not_of(whitespace);
if( idx != String::npos )
str = str.substr(0,idx+1);
}
void string_trim( String &str, const char* whitespace )
{
string_ltrim( str,whitespace );
string_rtrim( str,whitespace );
}
}
//////////////////////////////////////////////////////////////////////////
void _XMLDOMParserImpl::OnCharacterData( const char *s, int len )
{
String tempstr( s,len );
// Trim whitespaces from both sides.
string_trim( tempstr,"\t\n\r " );
Data( tempstr.c_str() );
}
//////////////////////////////////////////////////////////////////////////
bool _XMLDOMParserImpl::parse( std::vector<unsigned char> &buffer,string &errorString )
{
/*
m_nFilePos=0;
m_pBuffer=&buffer;
m_bUnicode=false;
m_bErrorState=false;
NanoXML nx;
nx.Parse(this);
m_pBuffer=NULL;
m_sErrorString=errorString;
return !m_bErrorState;
*/
m_bUnicode=false;
m_bErrorState=false;
XML_Memory_Handling_Suite memHandler;
memHandler.malloc_fcn = CryModuleMalloc;
memHandler.realloc_fcn = CryModuleRealloc;
memHandler.free_fcn = CryModuleFree;
XML_Parser parser = XML_ParserCreate_MM(NULL,&memHandler,NULL);
XML_SetUserData( parser, this );
XML_SetElementHandler( parser, EXPAT_XML_StartElement,EXPAT_XML_EndElement );
XML_SetCharacterDataHandler( parser,EXPAT_XML_CharacterData );
const char *sBuffer = (char*)&buffer[0];
if (!XML_Parse( parser,sBuffer,(int)buffer.size(),1 ))
{
char *str = new char [32768];
sprintf( str,"XML Error: %s at line %d",XML_ErrorString(XML_GetErrorCode(parser)),XML_GetCurrentLineNumber(parser) );
errorString = str;
delete [] str;
}
XML_ParserFree( parser );
return !m_bErrorState;
}