143 lines
5.0 KiB
C++

#ifndef CXMLWRITER
#define CXMLWRITER
#include "IArchive.h"
#include "Common/CFourCC.h"
#include <iostream>
#include <tinyxml2.h>
class CXMLWriter : public IArchive
{
tinyxml2::XMLDocument mDoc;
TString mOutFilename;
tinyxml2::XMLElement *mpCurElem;
bool mSaved;
public:
CXMLWriter(const TString& rkFileName, const TString& rkRootName, u16 FileVersion, EGame Game = eUnknownGame)
: IArchive()
, mOutFilename(rkFileName)
, mSaved(false)
{
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
// Create declaration and root node
tinyxml2::XMLDeclaration *pDecl = mDoc.NewDeclaration();
mDoc.LinkEndChild(pDecl);
mpCurElem = mDoc.NewElement(*rkRootName);
mDoc.LinkEndChild(mpCurElem);
// Write version data
mpCurElem->SetAttribute("ArchiveVer", (int) skCurrentArchiveVersion);
mpCurElem->SetAttribute("FileVer", (int) FileVersion);
if (Game != eUnknownGame) mpCurElem->SetAttribute("Game", *GetGameID(Game).ToString());
}
~CXMLWriter()
{
if (!mSaved)
{
bool SaveSuccess = Save();
ASSERT(SaveSuccess);
}
}
inline bool Save()
{
if (mSaved)
{
Log::Error("Attempted to save XML twice!");
return false;
}
tinyxml2::XMLError Error = mDoc.SaveFile(*mOutFilename);
mSaved = true;
if (Error != tinyxml2::XML_SUCCESS)
{
Log::Error("Failed to save XML file: " + mOutFilename);
return false;
}
else
return true;
}
inline bool IsValid() const
{
return mpCurElem != nullptr && !mSaved;
}
// Interface
virtual bool IsReader() const { return false; }
virtual bool IsWriter() const { return true; }
virtual bool IsTextFormat() const { return true; }
virtual bool ParamBegin(const char *pkName)
{
ASSERT(IsValid());
tinyxml2::XMLElement *pElem = mDoc.NewElement(pkName);
mpCurElem->LinkEndChild(pElem);
mpCurElem = pElem;
return true;
}
virtual void ParamEnd()
{
mpCurElem = mpCurElem->Parent()->ToElement();
}
protected:
void WriteParam(const char *pkValue)
{
mpCurElem->SetText(pkValue);
}
public:
virtual void SerializeContainerSize(u32&, const TString&)
{
// Reader obtains container size from number of child elements
}
virtual void SerializeAbstractObjectType(u32& rType)
{
mpCurElem->SetAttribute("Type", (unsigned int) rType);
}
virtual void SerializePrimitive(bool& rValue) { WriteParam(rValue ? "true" : "false"); }
virtual void SerializePrimitive(char& rValue) { WriteParam(*TString(rValue)); }
virtual void SerializePrimitive(s8& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(u8& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(s16& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(u16& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(s32& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(u32& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(s64& rValue) { WriteParam(*TString::FromInt64(rValue, 0, 10)); }
virtual void SerializePrimitive(u64& rValue) { WriteParam(*TString::FromInt64(rValue, 0, 10)); }
virtual void SerializePrimitive(float& rValue) { WriteParam(*TString::FromFloat(rValue)); }
virtual void SerializePrimitive(double& rValue) { WriteParam(*TString::FromFloat((float) rValue)); }
virtual void SerializePrimitive(TString& rValue) { WriteParam(*rValue); }
virtual void SerializePrimitive(TWideString& rValue) { WriteParam(*rValue.ToUTF8()); }
virtual void SerializePrimitive(CFourCC& rValue) { WriteParam(*rValue.ToString()); }
virtual void SerializePrimitive(CAssetID& rValue) { WriteParam(*rValue.ToString( CAssetID::GameIDLength(Game()) )); }
virtual void SerializeHexPrimitive(u8& rValue) { WriteParam(*TString::HexString(rValue, 2)); }
virtual void SerializeHexPrimitive(u16& rValue) { WriteParam(*TString::HexString(rValue, 4)); }
virtual void SerializeHexPrimitive(u32& rValue) { WriteParam(*TString::HexString(rValue, 8)); }
virtual void SerializeHexPrimitive(u64& rValue) { WriteParam(*TString::HexString((u32) rValue, 16)); }
virtual void BulkSerialize(void* pData, u32 Size)
{
char* pCharData = (char*) pData;
TString OutString(Size*2);
for (u32 ByteIdx = 0; ByteIdx < Size; ByteIdx++)
itoa(pCharData[ByteIdx], &OutString[ByteIdx*2], 16);
WriteParam(*OutString);
}
};
#endif // CXMLWRITER