|
|
@@ -0,0 +1,164 @@
|
|
|
+#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;
|
|
|
+}
|