/*
GameEngine and Editor
by John Ryland
Copyright (c) 2023
*/
////////////////////////////////////////////////////////////////////////////////////
// XML Parser
#include "XmlParser.h"
#include "XmlTokenizer.h"
struct XmlParseContext
{
XmlTag* rootTag;
XmlTag* currentTag = nullptr;
std::string currentAttribName;
};
static
void XmlSchemaConsumer(const XmlToken& token, XmlParseContext* ctx)
{
if (!ctx->currentTag)
ctx->currentTag = ctx->rootTag;
std::string str(token.buffer, token.buffer + token.length);
XmlTag newTag;
switch (token.type)
{
case XT_Text:
//printf(" xml text: \"%s\"\n", str.c_str());
ctx->currentTag->text += str;
break;
case XT_ElementBegin:
//printf(" xml begin: \"%s\"\n", str.c_str());
newTag.parent = ctx->currentTag;
newTag.tag = str;
ctx->currentTag->children.push_back(newTag);
ctx->currentTag = &ctx->currentTag->children.back();
break;
case XT_ElementEnd:
//printf(" xml end: \"%s\"\n", str.c_str());
ctx->currentTag = ctx->currentTag->parent;
break;
case XT_AttributeName:
//printf(" xml attrib-name: \"%s\"\n", str.c_str());
ctx->currentAttribName = str;
break;
case XT_AttributeValue:
//printf(" xml attrib-value: \"%s\"\n", str.c_str());
ctx->currentTag->attribValues.insert({ctx->currentAttribName, str });
break;
case XT_Comment:
//printf(" xml comment: \"%s\"\n", str.c_str());
break;
case XT_Unknown:
//printf(" xml unknown: \"%s\"\n", str.c_str());
break;
default:
//printf(" xml default: \"%s\"\n", str.c_str());
break;
}
}
static
void XmlConsumer(const XmlToken& token, void* user)
{
XmlSchemaConsumer(token, (XmlParseContext*)user);
}
static
void CheckReadResult(size_t result, size_t expected)
{
if (result != expected)
{
printf("read result: %lu, expected: %lu\n", result, expected);
exit(0);
}
}
bool ParseXmlFile(const char* xmlFileName, XmlTag* root)
{
FILE* xmlFile = fopen(xmlFileName, "r");
if (xmlFile)
{
fseek(xmlFile, 0, SEEK_END);
size_t siz = ftell(xmlFile);
//printf("file size = %lu\n", siz);
fseek(xmlFile, 0, SEEK_SET);
char* xmlData = (char*)malloc(siz);
CheckReadResult(fread(xmlData, siz, 1, xmlFile), 1);
XmlParseContext ctx;
ctx.rootTag = root;
XmlTokenize(xmlData, siz, &XmlConsumer, &ctx);
free(xmlData);
fclose(xmlFile);
return true;
}
return false;
}