mirror of
https://github.com/1dot13/source.git
synced 2026-09-02 14:36:06 +02:00
************************************************************
* Merged Source Code from Development Trunk: Revision 4063 * ************************************************************ - Source Code is merged from: https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP - This will be the Source for the Beta 2011 Test git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4064 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
#ifndef XML_AUTO_PARSE_H
|
||||
#define XML_AUTO_PARSE_H
|
||||
|
||||
#include <vfs/Core/vfs_debug.h>
|
||||
#include <vfs/Core/Interface/vfs_file_interface.h>
|
||||
#include "XML_Parser.h"
|
||||
#include <stack>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#if !defined(TRUE)
|
||||
# define TRUE 1
|
||||
#endif
|
||||
|
||||
namespace xml_auto
|
||||
{
|
||||
class ITransition
|
||||
{
|
||||
public:
|
||||
void Register() { _ref_count++; }
|
||||
void UnRegister() { if(_ref_count > 0) _ref_count--; }
|
||||
virtual void Delete()
|
||||
{
|
||||
UnRegister();
|
||||
if(_ref_count == 0) delete this;
|
||||
}
|
||||
virtual void enter(const char* tag_name, IXMLParser::Attributes const& atts) {};
|
||||
virtual void leave(const char* tag_name, std::string const& data) {};
|
||||
virtual bool handleText() {return false;};
|
||||
protected:
|
||||
ITransition() : _ref_count(0) {};
|
||||
~ITransition() {};
|
||||
private:
|
||||
int _ref_count;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class TTransition : public ITransition
|
||||
{
|
||||
public:
|
||||
typedef typename T::States state_t;
|
||||
const state_t StartPoint, EndPoint;
|
||||
T* P_DATA; // parser data
|
||||
protected:
|
||||
TTransition(const state_t start, const state_t end, T* p_data = NULL)
|
||||
: StartPoint(start), EndPoint(end), P_DATA(p_data)
|
||||
{
|
||||
Register();
|
||||
};
|
||||
virtual ~TTransition()
|
||||
{};
|
||||
};
|
||||
|
||||
template<typename T, typename States>
|
||||
class TBaseStructure
|
||||
{
|
||||
public:
|
||||
typedef TTransition<T> transition_t;
|
||||
typedef States state_t;
|
||||
private:
|
||||
// map : transition trigger (string) -> pointing at next state
|
||||
typedef std::map<std::string, transition_t*> tr_state_t;
|
||||
|
||||
// map : state -> outgoing transitions (of that state)
|
||||
typedef std::map<state_t,tr_state_t> tr_map_t;
|
||||
public:
|
||||
transition_t* getTransition(state_t current_state, std::string const& str)
|
||||
{
|
||||
typename tr_map_t::iterator it = _state_tr_map.find(current_state);
|
||||
if(it != _state_tr_map.end())
|
||||
{
|
||||
typename tr_state_t::iterator trit = it->second.find(str);
|
||||
if( trit != it->second.end() )
|
||||
{
|
||||
return trit->second;
|
||||
}
|
||||
else if( (trit=it->second.find("")) != it->second.end() )
|
||||
{
|
||||
return trit->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
~TBaseStructure()
|
||||
{
|
||||
typename tr_map_t::iterator it = _state_tr_map.begin();
|
||||
for(; it != _state_tr_map.end(); ++it)
|
||||
{
|
||||
typename tr_state_t::iterator trit = it->second.begin();
|
||||
for(;trit != it->second.end(); trit++)
|
||||
{
|
||||
trit->second->Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
protected:
|
||||
void newTransition(std::string const& tag, transition_t* tr)
|
||||
{
|
||||
_state_tr_map[tr->StartPoint][tag] = tr;
|
||||
_state_tr_map[tr->EndPoint][tag] = tr;
|
||||
// we use one transition twice -> increment ref counter
|
||||
tr->Register();
|
||||
}
|
||||
|
||||
tr_map_t _state_tr_map;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class TGenericXMLParser : public IXMLParser
|
||||
{
|
||||
public:
|
||||
typedef TBaseStructure<T, typename T::States> struct_t;
|
||||
TGenericXMLParser(struct_t* base, IXMLParser* caller = NULL)
|
||||
: IXMLParser("",NULL,caller), m_base(base), m_state(T::STATE_NONE)
|
||||
{
|
||||
parser = XML_ParserCreate(NULL);
|
||||
setParser(&parser);
|
||||
};
|
||||
~TGenericXMLParser()
|
||||
{
|
||||
if(parser)
|
||||
{
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
virtual void onStartElement(const XML_Char* name, const XML_Char** atts)
|
||||
{
|
||||
typename struct_t::transition_t* tr = m_base->getTransition(m_state.state(), name);
|
||||
if(tr && m_state.stateTransition(tr->StartPoint, LazyTrue(), tr->EndPoint))
|
||||
{
|
||||
m_tr_stack.push(tr);
|
||||
tr->enter(name, IXMLParser::Attributes(atts));
|
||||
}
|
||||
sCharData = "";
|
||||
}
|
||||
virtual void onEndElement(const XML_Char* name)
|
||||
{
|
||||
typename struct_t::transition_t* tr = m_base->getTransition(m_state.state(), name);
|
||||
if(tr && m_state.stateTransition(tr->EndPoint, LazyTrue(), tr->StartPoint))
|
||||
{
|
||||
SGP_THROW_IFFALSE(tr == m_tr_stack.top(),
|
||||
_BS(L"Transition associated to tag [") << name << L"] doesn't correspond to saved transition" << _BS::wget);
|
||||
tr->leave(name, sCharData);
|
||||
m_tr_stack.pop();
|
||||
}
|
||||
};
|
||||
virtual void onTextElement(const XML_Char *str, int len)
|
||||
{
|
||||
if(!m_tr_stack.empty())
|
||||
{
|
||||
typename struct_t::transition_t* tr = m_tr_stack.top();
|
||||
if(tr && tr->handleText())
|
||||
{
|
||||
sCharData.append(str,len);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void parseBuffer(vfs::Byte* buffer, vfs::size_t length)
|
||||
{
|
||||
this->grabParser();
|
||||
XML_Parser& _parser = this->getParser();
|
||||
if(!XML_Parse(_parser, buffer, length, TRUE))
|
||||
{
|
||||
std::wstringstream wss;
|
||||
wss << L"XML Parser Error : "
|
||||
<< vfs::String::as_utf16(XML_ErrorString(XML_GetErrorCode(_parser)))
|
||||
<< L" in line "
|
||||
<< XML_GetCurrentLineNumber(_parser);
|
||||
SGP_THROW(wss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void parseFile(vfs::tReadableFile* pFile)
|
||||
{
|
||||
if(!pFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
vfs::COpenReadFile rfile(pFile);
|
||||
|
||||
vfs::size_t size = rfile->getSize();
|
||||
std::vector<vfs::Byte> buffer(size+1);
|
||||
|
||||
SGP_TRYCATCH_RETHROW( rfile->read(&buffer[0],size), L"" );
|
||||
buffer[size] = 0;
|
||||
|
||||
SGP_TRYCATCH_RETHROW( this->parseBuffer(&buffer[0], size),
|
||||
_BS(L"error in file : ") << pFile->getPath() << _BS::wget);
|
||||
}
|
||||
|
||||
void parseFile(vfs::Path const& sFile)
|
||||
{
|
||||
vfs::tReadableFile* file = getVFS()->getReadFile(sFile);
|
||||
SGP_THROW_IFFALSE(file, _BS(L"Could not find file : ") << sFile << _BS::wget);
|
||||
|
||||
SGP_TRYCATCH_RETHROW( this->parseFile(file),
|
||||
_BS(L"error in file : ") << sFile << _BS::wget);
|
||||
}
|
||||
|
||||
private:
|
||||
XML_Parser parser;
|
||||
|
||||
typedef IXMLParser::ParserState<typename T::States> ParserState_t;
|
||||
struct_t* m_base;
|
||||
|
||||
typedef std::stack<typename struct_t::transition_t*> tr_stack_t;
|
||||
tr_stack_t m_tr_stack;
|
||||
ParserState_t m_state;
|
||||
};
|
||||
}
|
||||
|
||||
#define PARSER_CLASS_MACRO(class_name, states) \
|
||||
class class_name : public states, public xml_auto::TBaseStructure<class_name, states::States>
|
||||
|
||||
#define PURE_TRANSITION(class_name, main_type) \
|
||||
class class_name : public xml_auto::TTransition<main_type>{ \
|
||||
public: \
|
||||
typedef main_type::States state_t; \
|
||||
typedef xml_auto::TTransition<main_type> super_t; \
|
||||
class_name(const state_t start, const state_t end) : super_t(start, end) \
|
||||
{} \
|
||||
virtual ~class_name() \
|
||||
{} \
|
||||
};
|
||||
|
||||
#define DEFINE_TRANSITION(class_name, base_type, handle_text) \
|
||||
class class_name : public xml_auto::TTransition<base_type>{ \
|
||||
public: \
|
||||
typedef xml_auto::TTransition<base_type> super_t; \
|
||||
typedef base_type::States state_t; \
|
||||
class_name(const state_t start, const state_t end, base_type* base_obj) : super_t(start,end,base_obj) {}; \
|
||||
virtual ~class_name() {}; \
|
||||
virtual bool handleText() {return handle_text;}; \
|
||||
|
||||
#define DEFINE_TRANSITION_WDATA(class_name, base_type, handle_text, tr_data_type) \
|
||||
class class_name : public xml_auto::TTransition<base_type>{ \
|
||||
tr_data_type T_DATA; \
|
||||
public: \
|
||||
typedef xml_auto::TTransition<base_type> super_t; \
|
||||
typedef base_type::States state_t; \
|
||||
class_name(const state_t start, const state_t end, base_type* base_obj) : super_t(start,end,base_obj) {}; \
|
||||
virtual ~class_name() {}; \
|
||||
virtual bool handleText() {return handle_text;}; \
|
||||
|
||||
#define FINISH_TRANSITION };
|
||||
|
||||
#define TRANSITION_ENTER virtual void enter(const char* tag_name, IXMLParser::Attributes const& atts)
|
||||
#define TRANSITION_LEAVE virtual void leave(const char* tag_name, std::string const& char_data)
|
||||
|
||||
#define TR_HANDLE(from_state, trigger, to_state, handler_class_type) newTransition((trigger), new handler_class_type((from_state),(to_state),this));
|
||||
#define TR_PASS(from_state, trigger, to_state) newTransition((trigger), new NOOP((from_state),(to_state)));
|
||||
|
||||
#endif // XML_AUTO_PARSE_H
|
||||
Reference in New Issue
Block a user