tamlBinaryParser.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "persistence/taml/binary/tamlBinaryParser.h"
  2. #include "console/console.h"
  3. #include "core/util/zip/zipSubStream.h"
  4. #include "platform/profiler.h"
  5. #include "persistence/taml/taml.h"
  6. bool TamlBinaryParser::accept(const char* pFilename, TamlVisitor& visitor)
  7. {
  8. isRoot = true;
  9. PROFILE_SCOPE(TamlBinaryParser_Accept);
  10. AssertFatal(pFilename != NULL, "TamlBinaryParser::accept - NULL filename.");
  11. char filenameBuffer[1024];
  12. Con::expandScriptFilename(filenameBuffer, sizeof(filenameBuffer), pFilename);
  13. FileStream stream;
  14. if (!stream.open(filenameBuffer, Torque::FS::File::Read))
  15. {
  16. Con::warnf("TamlBinaryParser::accept - Could not open file '%s'.", filenameBuffer);
  17. return false;
  18. }
  19. // Read TAML signature.
  20. StringTableEntry signature = stream.readSTString();
  21. if (signature != StringTable->insert(TAML_SIGNATURE))
  22. {
  23. Con::warnf("TamlBinaryParser::accept - Invalid signature in '%s'.", filenameBuffer);
  24. stream.close();
  25. return false;
  26. }
  27. setParsingFilename(pFilename);
  28. U32 versionId;
  29. stream.read(&versionId);
  30. bool compressed;
  31. stream.read(&compressed);
  32. if (compressed)
  33. {
  34. ZipSubRStream zipStream;
  35. zipStream.attachStream(&stream);
  36. parseElement(zipStream, visitor, versionId);
  37. zipStream.detachStream();
  38. }
  39. else
  40. {
  41. parseElement(stream, visitor, versionId);
  42. }
  43. stream.close();
  44. setParsingFilename(StringTable->EmptyString());
  45. return true;
  46. }
  47. //-----------------------------------------------------------------------------
  48. bool TamlBinaryParser::parseElement(Stream& stream, TamlVisitor& visitor, const U32 versionId)
  49. {
  50. PROFILE_SCOPE(TamlBinaryParser_ParseElement);
  51. // --- Read element header ---
  52. StringTableEntry pElementName = stream.readSTString();
  53. StringTableEntry pObjectName = stream.readSTString();
  54. // Read references.
  55. U32 refId, refToId;
  56. stream.read(&refId);
  57. stream.read(&refToId);
  58. // If this is a reference to another object, skip it.
  59. if (refToId != 0)
  60. return true;
  61. // Create a property visitor state.
  62. TamlVisitor::PropertyState propertyState;
  63. propertyState.setObjectName(pElementName, isRoot);
  64. if (pObjectName != StringTable->EmptyString())
  65. propertyState.setProperty("Name", pObjectName);
  66. if(isRoot)
  67. isRoot = false;
  68. // --- Attributes ---
  69. parseAttributes(stream, visitor, versionId, propertyState);
  70. // --- Children ---
  71. parseChildren(stream, visitor, versionId);
  72. // --- Custom elements ---
  73. parseCustomElements(stream, visitor, versionId);
  74. return true;
  75. }
  76. void TamlBinaryParser::parseAttributes(Stream& stream, TamlVisitor& visitor, const U32 versionId, TamlVisitor::PropertyState& state)
  77. {
  78. PROFILE_SCOPE(TamlBinaryParser_ParseAttributes);
  79. U32 attributeCount;
  80. stream.read(&attributeCount);
  81. if (attributeCount == 0)
  82. return;
  83. char valueBuffer[4096];
  84. for (U32 i = 0; i < attributeCount; ++i)
  85. {
  86. StringTableEntry attrName = stream.readSTString();
  87. stream.readLongString(4096, valueBuffer);
  88. state.setProperty(attrName, valueBuffer);
  89. const bool visitStatus = visitor.visit(*this, state);
  90. if (!visitStatus)
  91. return;
  92. }
  93. }
  94. //-----------------------------------------------------------------------------
  95. void TamlBinaryParser::parseChildren(Stream& stream, TamlVisitor& visitor, const U32 versionId)
  96. {
  97. PROFILE_SCOPE(TamlBinaryParser_ParseChildren);
  98. U32 childCount = 0;
  99. stream.read(&childCount);
  100. if (childCount == 0)
  101. return;
  102. for (U32 i = 0; i < childCount; ++i)
  103. {
  104. parseElement(stream, visitor, versionId);
  105. }
  106. }
  107. //-----------------------------------------------------------------------------
  108. void TamlBinaryParser::parseCustomElements(Stream& stream, TamlVisitor& visitor, const U32 versionId)
  109. {
  110. PROFILE_SCOPE(TamlBinaryParser_ParseCustomElements);
  111. U32 customNodeCount = 0;
  112. stream.read(&customNodeCount);
  113. if (customNodeCount == 0)
  114. return;
  115. TamlVisitor::PropertyState state;
  116. for (U32 nodeIndex = 0; nodeIndex < customNodeCount; ++nodeIndex)
  117. {
  118. StringTableEntry nodeName = stream.readSTString();
  119. state.setObjectName(nodeName, false);
  120. U32 nodeChildrenCount = 0;
  121. stream.read(&nodeChildrenCount);
  122. if (nodeChildrenCount == 0)
  123. return;
  124. for(U32 nodeChild = 0; nodeChild < nodeChildrenCount; ++nodeChild)
  125. parseCustomNode(stream, visitor, versionId, state);
  126. }
  127. }
  128. //-----------------------------------------------------------------------------
  129. bool TamlBinaryParser::parseCustomNode(Stream& stream, TamlVisitor& visitor, const U32 versionId, TamlVisitor::PropertyState& state)
  130. {
  131. PROFILE_SCOPE(TamlBinaryParser_ParseCustomNode);
  132. bool isProxyObject;
  133. stream.read(&isProxyObject);
  134. if (isProxyObject)
  135. {
  136. // Parse nested proxy element.
  137. return parseElement(stream, visitor, versionId);
  138. }
  139. StringTableEntry nodeName = stream.readSTString();
  140. char nodeValue[MAX_TAML_NODE_FIELDVALUE_LENGTH];
  141. stream.readLongString(MAX_TAML_NODE_FIELDVALUE_LENGTH, nodeValue);
  142. U32 childCount;
  143. stream.read(&childCount);
  144. for (U32 i = 0; i < childCount; ++i)
  145. {
  146. if (!parseCustomNode(stream, visitor, versionId, state))
  147. return false;
  148. }
  149. U32 fieldCount;
  150. stream.read(&fieldCount);
  151. if (fieldCount > 0)
  152. {
  153. char valueBuffer[MAX_TAML_NODE_FIELDVALUE_LENGTH];
  154. for (U32 f = 0; f < fieldCount; ++f)
  155. {
  156. StringTableEntry fieldName = stream.readSTString();
  157. stream.readLongString(MAX_TAML_NODE_FIELDVALUE_LENGTH, valueBuffer);
  158. state.setProperty(fieldName, valueBuffer);
  159. const bool visitStatus = visitor.visit(*this, state);
  160. if (!visitStatus)
  161. return false;
  162. }
  163. }
  164. return true;
  165. }