mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
LOBOT code (by Asdow, original code by Bio).
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8755 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
#include "AbstractXMLLoader.h"
|
||||
|
||||
namespace LogicalBodyTypes {
|
||||
|
||||
AbstractXMLLoader::AbstractXMLLoader(XML_StartElementHandler startHandler, XML_EndElementHandler endHandler, XML_CharacterDataHandler charHandler, ParseDataFactoryFunc parseDataFactF) {
|
||||
startElementHandler = startHandler;
|
||||
endElementHandler = endHandler;
|
||||
characterDataHandler = charHandler;
|
||||
parseDataFactFuncPntr = parseDataFactF;
|
||||
}
|
||||
|
||||
AbstractXMLLoader::~AbstractXMLLoader(void) {
|
||||
}
|
||||
|
||||
AbstractXMLLoader::ParseData::ParseData(XML_Parser* parser) {
|
||||
pParser = parser;
|
||||
state = E_NONE;
|
||||
level = 0;
|
||||
szCharData[0] = '\0';
|
||||
szErrorTxt[0] = '\0';
|
||||
}
|
||||
|
||||
AbstractXMLLoader::ParseData* AbstractXMLLoader::MakeParseData(XML_Parser* parser) {
|
||||
return new ParseData(parser);
|
||||
}
|
||||
|
||||
bool AbstractXMLLoader::LoadFromFile(const char* directoryName, const char* fileName) {
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8* lpcBuffer;
|
||||
char fileNameFull[MAX_PATH + 1];
|
||||
if (strlen(fileName) + strlen(directoryName) >= MAX_PATH) {
|
||||
LiveMessage("Can't load file. Concatinated filename too long for buffer!");
|
||||
return false;
|
||||
}
|
||||
SetDirectoryName(directoryName);
|
||||
SetFileName(fileName);
|
||||
strcpy(fileNameFull, directoryName);
|
||||
strcat(fileNameFull, fileName);
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
AbstractXMLLoader::ParseData* data = parseDataFactFuncPntr(&parser);
|
||||
|
||||
std::string msg = "Loading ";
|
||||
msg += fileName;
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, msg.c_str());
|
||||
hFile = FileOpen(fileNameFull, FILE_ACCESS_READ, FALSE);
|
||||
if (!hFile) {
|
||||
delete data;
|
||||
return false;
|
||||
}
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8*)MemAlloc(uiFSize + 1);
|
||||
if (!FileRead(hFile, lpcBuffer, uiFSize, &uiBytesRead)) {
|
||||
MemFree(lpcBuffer);
|
||||
delete data;
|
||||
return false;
|
||||
}
|
||||
lpcBuffer[uiFSize] = 0;
|
||||
FileClose(hFile);
|
||||
|
||||
ExternalEntityArgs eeArgs;
|
||||
eeArgs.directoryName = directoryName;
|
||||
eeArgs.fileName = fileName;
|
||||
eeArgs.pParser = &parser;
|
||||
|
||||
XML_SetElementHandler(parser, startElementHandler, endElementHandler);
|
||||
XML_SetCharacterDataHandler(parser, characterDataHandler);
|
||||
XML_SetUserData(parser, data);
|
||||
XML_SetExternalEntityRefHandler(parser, ExternalEntityHandler);
|
||||
XML_SetExternalEntityRefHandlerArg(parser, (void*)&eeArgs);
|
||||
|
||||
try {
|
||||
if (!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) {
|
||||
CHAR8 errorBuf[512];
|
||||
sprintf(errorBuf, "XML Parser Error in %s[%d]: %s", fileNameFull, XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser)));
|
||||
LiveMessage(errorBuf);
|
||||
MemFree(lpcBuffer);
|
||||
delete data;
|
||||
return false;
|
||||
}
|
||||
} catch (XMLParseException e) {
|
||||
CHAR8 errorBuf[512];
|
||||
sprintf(errorBuf, "XML Parser Exception in %s[%d]: %s", fileNameFull, e._LINE, e.what());
|
||||
LiveMessage(errorBuf);
|
||||
MemFree(lpcBuffer);
|
||||
XML_ParserFree(parser);
|
||||
delete data;
|
||||
return false;
|
||||
}
|
||||
MemFree(lpcBuffer);
|
||||
XML_ParserFree(parser);
|
||||
delete data;
|
||||
return true;
|
||||
}
|
||||
|
||||
int XMLCALL AbstractXMLLoader::ExternalEntityHandler(XML_Parser args, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId) {
|
||||
ExternalEntityArgs* eArgs = (ExternalEntityArgs*)args;
|
||||
char fileNameFull[MAX_PATH + 1];
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8* lpcBuffer;
|
||||
HWFILE hFile;
|
||||
if (strlen(eArgs->directoryName) + strlen(systemId) >= MAX_PATH) {
|
||||
LiveMessage("Can't load file specified in external entity. Concatinated filename too long for buffer!");
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
strcpy(fileNameFull, eArgs->directoryName);
|
||||
strcat(fileNameFull, systemId);
|
||||
|
||||
hFile = FileOpen(fileNameFull, FILE_ACCESS_READ, FALSE);
|
||||
if (!hFile) {
|
||||
LiveMessage("File specified in external entity can't be opened!");
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8*)MemAlloc(uiFSize + 1);
|
||||
if (!FileRead(hFile, lpcBuffer, uiFSize, &uiBytesRead)) {
|
||||
LiveMessage("File specified in external entity couldn't be read!");
|
||||
MemFree(lpcBuffer);
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
lpcBuffer[uiFSize] = 0;
|
||||
FileClose(hFile);
|
||||
|
||||
XML_Parser extParser = XML_ExternalEntityParserCreate(*eArgs->pParser, context, NULL);
|
||||
ParseData* data = (ParseData*)XML_GetUserData(*eArgs->pParser);
|
||||
data->pParser = &extParser;
|
||||
try {
|
||||
if (!XML_Parse(extParser, lpcBuffer, uiFSize, TRUE)) {
|
||||
CHAR8 errorBuf[512];
|
||||
sprintf(errorBuf, "XML Parser Error in external entity %s[%d]: %s", systemId, XML_GetCurrentLineNumber(extParser), XML_ErrorString(XML_GetErrorCode(extParser)));
|
||||
LiveMessage(errorBuf);
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
} catch (XMLParseException e) {
|
||||
CHAR8 errorBuf[512];
|
||||
sprintf(errorBuf, "XML Parser Exception in external entity %s[%d]: %s", systemId, e._LINE, e.what());
|
||||
LiveMessage(errorBuf);
|
||||
XML_ParserFree(extParser);
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
data->pParser = eArgs->pParser;
|
||||
XML_ParserFree(extParser);
|
||||
return XML_STATUS_OK;
|
||||
};
|
||||
|
||||
|
||||
const char* AbstractXMLLoader::GetFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
const char* AbstractXMLLoader::GetDirectoryName() {
|
||||
return directoryName;
|
||||
}
|
||||
|
||||
void AbstractXMLLoader::SetFileName(const char* fileName) {
|
||||
strcpy(this->fileName, fileName);
|
||||
}
|
||||
|
||||
void AbstractXMLLoader::SetDirectoryName(const char* directoryName) {
|
||||
strcpy(this->directoryName, directoryName);
|
||||
}
|
||||
|
||||
const XML_Char* AbstractXMLLoader::GetAttribute(const XML_Char* name, const XML_Char** atts) {
|
||||
for (const XML_Char** pIter = atts; *pIter != NULL; pIter++) {
|
||||
const XML_Char* key = *pIter++;
|
||||
if (strcmp(key, name) == 0) return *pIter;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool AbstractXMLLoader::ConvertStringToINT8(const XML_Char* num, INT8* int8) {
|
||||
long l = strtol(num, NULL, 10);
|
||||
if (l > 127 || l < -128) return false;
|
||||
if (l == 0 && strcmp(num, "0") != 0) return false;
|
||||
*int8 = (INT8)l;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractXMLLoader::ConvertStringToUINT8(const XML_Char* num, UINT8* uInt8) {
|
||||
unsigned long ul = strtoul(num, NULL, 10);
|
||||
if (ul > 255) return false;
|
||||
if (ul == 0 && strcmp(num, "0") != 0) return false;
|
||||
*uInt8 = (UINT8)ul;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractXMLLoader::ConvertStringToINT32(const XML_Char* num, INT32* int32) {
|
||||
long l = strtol(num, NULL, 10);
|
||||
// TODO: add range checks also for long types (and use the defined macros)
|
||||
// TODO: string should be trimmed (other convert functions also)
|
||||
if (l == 0 && strcmp(num, "0") != 0) return false;
|
||||
*int32 = (INT32)l;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractXMLLoader::ConvertStringToUINT32(const XML_Char* num, UINT32* uInt32) {
|
||||
unsigned long ul = strtoul(num, NULL, 10);
|
||||
if (ul == 0 && strcmp(num, "0") != 0) return false;
|
||||
*uInt32 = ul;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractXMLLoader::ConvertStringToBOOLEAN(const XML_Char* num, BOOLEAN* fBoolean) {
|
||||
unsigned long ul = strtoul(num, NULL, 10);
|
||||
if (ul == 0 && strcmp(num, "0") != 0) return false;
|
||||
*fBoolean = ul != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user