mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8882 3b4a5df2-a311-0410-b5c6-a8a6f20db521
216 lines
6.8 KiB
C++
216 lines
6.8 KiB
C++
#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);
|
|
MemFree(lpcBuffer);
|
|
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);
|
|
MemFree(lpcBuffer);
|
|
return XML_STATUS_ERROR;
|
|
}
|
|
data->pParser = eArgs->pParser;
|
|
XML_ParserFree(extParser);
|
|
MemFree(lpcBuffer);
|
|
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;
|
|
}
|
|
|
|
}
|