Torque3D/Engine/source/persistence/taml/binary/tamlBinaryParser.cpp
marauder2k7 140e9dbfc6 taml binary parsing
added taml binary parser
2025-10-12 19:43:42 +01:00

165 lines
4.4 KiB
C++

#include "persistence/taml/binary/tamlBinaryParser.h"
#include "console/console.h"
#include "core/util/zip/zipSubStream.h"
#include "platform/profiler.h"
#include "persistence/taml/taml.h"
bool TamlBinaryParser::accept(const char* pFilename, TamlVisitor& visitor)
{
PROFILE_SCOPE(TamlBinaryParser_Accept);
AssertFatal(pFilename != NULL, "TamlBinaryParser::accept - NULL filename.");
char filenameBuffer[1024];
Con::expandScriptFilename(filenameBuffer, sizeof(filenameBuffer), pFilename);
FileStream stream;
if (!stream.open(filenameBuffer, Torque::FS::File::Read))
{
Con::warnf("TamlBinaryParser::accept - Could not open file '%s'.", filenameBuffer);
return false;
}
// Read TAML signature.
StringTableEntry signature = stream.readSTString();
if (signature != StringTable->insert(TAML_SIGNATURE))
{
Con::warnf("TamlBinaryParser::accept - Invalid signature in '%s'.", filenameBuffer);
stream.close();
return false;
}
U32 versionId;
stream.read(&versionId);
bool compressed;
stream.read(&compressed);
if (compressed)
{
ZipSubRStream zipStream;
zipStream.attachStream(&stream);
parseElement(zipStream, visitor, versionId);
zipStream.detachStream();
}
else
{
parseElement(stream, visitor, versionId);
}
stream.close();
return true;
}
//-----------------------------------------------------------------------------
bool TamlBinaryParser::parseElement(Stream& stream, TamlVisitor& visitor, const U32 versionId)
{
PROFILE_SCOPE(TamlBinaryParser_ParseElement);
// Read the type and name.
StringTableEntry typeName = stream.readSTString();
StringTableEntry objectName = stream.readSTString();
// Read references.
U32 refId, refToId;
stream.read(&refId);
stream.read(&refToId);
// Create a property visitor state.
TamlVisitor::PropertyState propertyState;
propertyState.setObjectName(typeName, false);
if (objectName != StringTable->EmptyString())
propertyState.setProperty("Name", objectName);
if (!visitor.visit(*this, propertyState))
return false;
// Parse attributes.
U32 attrCount;
stream.read(&attrCount);
char valueBuffer[4096];
for (U32 i = 0; i < attrCount; ++i)
{
StringTableEntry attrName = stream.readSTString();
stream.readLongString(sizeof(valueBuffer), valueBuffer);
propertyState.setProperty(attrName, valueBuffer);
visitor.visit(*this, propertyState);
}
// Parse children.
U32 childCount;
stream.read(&childCount);
for (U32 c = 0; c < childCount; ++c)
{
if (!parseElement(stream, visitor, versionId))
return false;
}
// Parse custom nodes.
U32 customCount;
stream.read(&customCount);
for (U32 cn = 0; cn < customCount; ++cn)
{
StringTableEntry customNodeName = stream.readSTString();
propertyState.setProperty("CustomNode", customNodeName);
visitor.visit(*this, propertyState);
parseCustomNode(stream, visitor, versionId);
}
return true;
}
//-----------------------------------------------------------------------------
bool TamlBinaryParser::parseCustomNode(Stream& stream, TamlVisitor& visitor, const U32 versionId)
{
PROFILE_SCOPE(TamlBinaryParser_ParseCustomNode);
bool isProxyObject;
stream.read(&isProxyObject);
if (isProxyObject)
{
// Parse nested proxy element.
return parseElement(stream, visitor, versionId);
}
// Read custom node name and text.
StringTableEntry nodeName = stream.readSTString();
char textBuffer[1024];
stream.readLongString(sizeof(textBuffer), textBuffer);
// Create visitor state for the node.
TamlVisitor::PropertyState nodeState;
nodeState.setObjectName(nodeName, false);
nodeState.setProperty("Text", textBuffer);
visitor.visit(*this, nodeState);
// Parse child nodes.
U32 childCount;
stream.read(&childCount);
for (U32 i = 0; i < childCount; ++i)
{
if (!parseCustomNode(stream, visitor, versionId))
return false;
}
// Parse fields.
U32 fieldCount;
stream.read(&fieldCount);
char valueBuffer[1024];
for (U32 f = 0; f < fieldCount; ++f)
{
StringTableEntry fieldName = stream.readSTString();
stream.readLongString(sizeof(valueBuffer), valueBuffer);
nodeState.setProperty(fieldName, valueBuffer);
visitor.visit(*this, nodeState);
}
return true;
}