Переглянути джерело

taml binary parsing

added taml binary parser
marauder2k7 2 тижнів тому
батько
коміт
140e9dbfc6

+ 164 - 0
Engine/source/persistence/taml/binary/tamlBinaryParser.cpp

@@ -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;
+}

+ 37 - 0
Engine/source/persistence/taml/binary/tamlBinaryParser.h

@@ -0,0 +1,37 @@
+#pragma once
+#ifndef _TAML_BINARYPARSER_H_
+
+#ifndef _TAML_PARSER_H_
+#include "persistence/taml/tamlParser.h"
+#endif
+
+#ifndef _TAML_VISITOR_H_
+#include "persistence/taml/tamlVisitor.h"
+#endif
+
+#ifndef _STREAM_H_
+#include "core/stream/stream.h"
+#endif
+
+#ifndef _FILESTREAM_H_
+#include "core/stream/fileStream.h"
+#endif
+
+class TamlBinaryParser : public TamlParser
+{
+public:
+   TamlBinaryParser() {}
+   virtual ~TamlBinaryParser() {}
+
+   /// Whether the parser can change a property or not.
+   bool canChangeProperty(void) override { return false; }
+
+   /// Accept visitor.
+   bool accept(const char* pFilename, TamlVisitor& visitor) override;
+
+private:
+   bool parseElement(Stream& stream, TamlVisitor& visitor, const U32 versionId);
+   bool parseCustomNode(Stream& stream, TamlVisitor& visitor, const U32 versionId);
+};
+
+#endif // !_TAML_BINARYPARSER_H_

+ 17 - 0
Engine/source/persistence/taml/taml.cpp

@@ -42,6 +42,10 @@
 #include "persistence/taml/binary/tamlBinaryReader.h"
 #include "persistence/taml/binary/tamlBinaryReader.h"
 #endif
 #endif
 
 
+#ifndef _TAML_BINARYPARSER_H_
+#include "persistence/taml/binary/tamlBinaryParser.h"
+#endif
+
 #ifndef _TAML_JSONWRITER_H_
 #ifndef _TAML_JSONWRITER_H_
 #include "persistence/taml/json/tamlJSONWriter.h"
 #include "persistence/taml/json/tamlJSONWriter.h"
 #endif
 #endif
@@ -455,6 +459,19 @@ bool Taml::parse(const char* pFilename, TamlVisitor& visitor)
    }
    }
 
 
    case BinaryFormat:
    case BinaryFormat:
+   {
+      // Parse with the visitor.
+      TamlBinaryParser parser;
+      // Are property changes needed but not supported?
+      if (visitor.wantsPropertyChanges() && !parser.canChangeProperty())
+      {
+         // Yes, so warn.
+         Con::warnf("Taml::parse() - Cannot parse '%s' file-type for filename '%s' as a specified visitor requires property changes which are not supported by the parser.", getFormatModeDescription(formatMode), pFilename);
+         return false;
+      }
+
+      return parser.accept(pFilename, visitor);
+   }
    default:
    default:
       break;
       break;
    }
    }