Added support for bitfield properties

This commit is contained in:
parax0
2015-10-25 17:43:11 -06:00
parent 8470923e45
commit b187da3925
11 changed files with 270 additions and 10 deletions

View File

@@ -58,6 +58,21 @@ CPropertyStruct* CScriptLoader::LoadStructMP1(CInputStream& SCLY, CStructTemplat
pProp = new CLongProperty(v);
break;
}
case eBitfieldProperty: {
long v = SCLY.ReadLong();
pProp = new CBitfieldProperty(v);
// Validate
u32 mask = 0;
CBitfieldTemplate *pBitfieldTemp = static_cast<CBitfieldTemplate*>(pPropTmp);
for (u32 iMask = 0; iMask < pBitfieldTemp->NumFlags(); iMask++)
mask |= pBitfieldTemp->FlagMask(iMask);
u32 check = v & ~mask;
if (check != 0) Log::FileWarning(SCLY.GetSourceString(), SCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + StringUtil::ToHexString(check, true, true, 8));
break;
}
case eEnumProperty: {
CEnumTemplate *pEnumTemp = static_cast<CEnumTemplate*>(pPropTmp);
u32 ID = SCLY.ReadLong();
@@ -273,6 +288,22 @@ void CScriptLoader::LoadStructMP2(CInputStream& SCLY, CPropertyStruct *pStruct,
break;
}
case eBitfieldProperty: {
CBitfieldProperty *pBitfieldCast = static_cast<CBitfieldProperty*>(pProp);
pBitfieldCast->Set(SCLY.ReadLong());
// Validate
u32 mask = 0;
CBitfieldTemplate *pBitfieldTemp = static_cast<CBitfieldTemplate*>(pPropTemp);
for (u32 iMask = 0; iMask < pBitfieldTemp->NumFlags(); iMask++)
mask |= pBitfieldTemp->FlagMask(iMask);
u32 check = pBitfieldCast->Get() & ~mask;
if (check != 0) Log::FileWarning(SCLY.GetSourceString(), SCLY.Tell() - 4, "Bitfield property \"" + pBitfieldTemp->Name() + "\" in struct \"" + pTemp->Name() + "\" has flags set that aren't in the template: " + StringUtil::ToHexString(check, true, true, 8));
break;
}
case eEnumProperty: {
CEnumProperty *pEnumCast = static_cast<CEnumProperty*>(pProp);
CEnumTemplate *pEnumTemp = static_cast<CEnumTemplate*>(pPropTemp);

View File

@@ -2,6 +2,31 @@
#include "CWorldLoader.h"
#include <Core/Log.h>
void CTemplateLoader::LoadBitFlags(tinyxml2::XMLElement *pElem, CBitfieldTemplate *pTemp, const std::string& templateName)
{
tinyxml2::XMLElement *pChild = pElem->FirstChildElement("bitflag");
while (pChild)
{
const char *kpMask = pChild->Attribute("mask");
const char *kpName = pChild->Attribute("name");
if (kpMask && kpName)
pTemp->mBitFlags.push_back(CBitfieldTemplate::SBitFlag(kpName, StringUtil::ToInt32(kpMask)));
else
{
std::string LogErrorBase = "Couldn't parse bit flag in " + templateName + "; ";
if (!kpMask && kpName) Log::Error(LogErrorBase + "no mask (" + kpName + ")");
else if (kpMask && !kpName) Log::Error(LogErrorBase + "no name (mask " + kpMask + ")");
else Log::Error(LogErrorBase + "no valid ID or name");
}
pChild = pChild->NextSiblingElement("bitflag");
}
}
void CTemplateLoader::LoadEnumerators(tinyxml2::XMLElement *pElem, CEnumTemplate *pTemp, const std::string& templateName)
{
tinyxml2::XMLElement *pChild = pElem->FirstChildElement("enumerator");
@@ -18,8 +43,8 @@ void CTemplateLoader::LoadEnumerators(tinyxml2::XMLElement *pElem, CEnumTemplate
{
std::string LogErrorBase = "Couldn't parse enumerator in " + templateName + "; ";
if (!kpID && kpName) Log::Error(LogErrorBase + "no valid ID (" + kpName + ")");
if (kpID && !kpName) Log::Error(LogErrorBase + "no valid name (ID " + kpID + ")");
if (!kpID && kpName) Log::Error(LogErrorBase + "no valid ID (" + kpName + ")");
else if (kpID && !kpName) Log::Error(LogErrorBase + "no valid name (ID " + kpID + ")");
else Log::Error(LogErrorBase + "no valid ID or name");
}
@@ -193,15 +218,54 @@ CPropertyTemplate* CTemplateLoader::LoadPropertyTemplate(tinyxml2::XMLElement *p
LoadEnumerators(pRoot, pEnum, kpTemplateStr );
}
// Name
if (!name.empty())
pEnum->mPropName = name;
return pEnum;
}
// Name
if (!name.empty())
pEnum->mPropName = name;
return pEnum;
}
// Load Bitfield
else if (strcmp(pElem->Name(), "bitfield") == 0)
{
CBitfieldTemplate *pBitfield = new CBitfieldTemplate(ID);
// Embedded
if (!pElem->NoChildren())
LoadBitFlags(pElem, pBitfield, templateName);
// Template
else if (kpTemplateStr)
{
std::string tempPath = mMasterDir + kpTemplateStr;
tinyxml2::XMLDocument bitfieldXML;
bitfieldXML.LoadFile(tempPath.c_str());
if (bitfieldXML.Error())
Log::Error("Couldn't open bitfield XML: " + mMasterDir + kpTemplateStr);
else
{
tinyxml2::XMLElement *pRoot = bitfieldXML.FirstChildElement("bitfield");
pBitfield->mSourceFile = kpTemplateStr;
if (pRoot->Attribute("name"))
pBitfield->mPropName = pRoot->Attribute("name");
LoadBitFlags(pRoot, pBitfield, kpTemplateStr);
}
}
// Name
if (!name.empty())
pBitfield->mPropName = name;
return pBitfield;
}
return nullptr;
}

View File

@@ -15,6 +15,7 @@ class CTemplateLoader
CTemplateLoader(const std::string& templatesDir) : mTemplatesDir(templatesDir) {}
// Load Property
void LoadBitFlags(tinyxml2::XMLElement *pElem, CBitfieldTemplate *pTemp, const std::string& templateName);
void LoadEnumerators(tinyxml2::XMLElement *pElem, CEnumTemplate *pTemp, const std::string& templateName);
void LoadStructProperties(tinyxml2::XMLElement *pElem, CStructTemplate *pTemp, const std::string& templateName);
CPropertyTemplate* LoadPropertyTemplate(tinyxml2::XMLElement *pElem, const std::string& templateName);