summaryrefslogtreecommitdiff
path: root/Runtime/Serialize/TransferFunctions/YAMLRead.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Serialize/TransferFunctions/YAMLRead.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Serialize/TransferFunctions/YAMLRead.cpp')
-rw-r--r--Runtime/Serialize/TransferFunctions/YAMLRead.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/Runtime/Serialize/TransferFunctions/YAMLRead.cpp b/Runtime/Serialize/TransferFunctions/YAMLRead.cpp
new file mode 100644
index 0000000..4a9ca42
--- /dev/null
+++ b/Runtime/Serialize/TransferFunctions/YAMLRead.cpp
@@ -0,0 +1,238 @@
+#include "UnityPrefix.h"
+#include "YAMLRead.h"
+#include "../FileCache.h"
+
+int YAMLRead::GetDataVersion ()
+{
+ if (m_Versions.back() == -1)
+ {
+ yaml_node_t *node = m_CurrentNode;
+ int i = m_MetaParents.size();
+ do
+ {
+ yaml_node_t *versionNode = GetValueForKey(node, "serializedVersion");
+ if (versionNode)
+ {
+ Assert (versionNode->type == YAML_SCALAR_NODE);
+ sscanf ((char*)versionNode->data.scalar.value, "%d", &m_Versions.back());
+ return m_Versions.back();
+ }
+ // If "serializedVersion" is not found, look for "importerVersion" for backwards compatibility.
+ versionNode = GetValueForKey(node, "importerVersion");
+ if (versionNode)
+ {
+ Assert (versionNode->type == YAML_SCALAR_NODE);
+ sscanf ((char*)versionNode->data.scalar.value, "%d", &m_Versions.back());
+ return m_Versions.back();
+ }
+ if (i>0)
+ node = m_MetaParents[--i];
+ else
+ node = NULL;
+ }
+ while (node != NULL);
+ m_Versions.back() = 1;
+ }
+ return m_Versions.back();
+}
+
+yaml_node_t *YAMLRead::GetValueForKey (yaml_node_t* parentNode, const char* keystr)
+{
+ if (parentNode && parentNode->type == YAML_MAPPING_NODE)
+ {
+ // The code below does not handle empty yaml arrays.
+ if (parentNode->data.mapping.pairs.top == parentNode->data.mapping.pairs.start)
+ return NULL;
+
+ yaml_node_pair_t* start;
+ if (m_CachedIndex < parentNode->data.mapping.pairs.top
+ && m_CachedIndex >= parentNode->data.mapping.pairs.start)
+ start = m_CachedIndex;
+ else
+ start = parentNode->data.mapping.pairs.start;
+
+ yaml_node_pair_t* top = parentNode->data.mapping.pairs.top;
+ yaml_node_pair_t* i = start;
+
+ do
+ {
+ yaml_node_pair_t* next = i+1;
+ if (next == top)
+ next = parentNode->data.mapping.pairs.start;
+
+ yaml_node_t* key = yaml_document_get_node(m_ActiveDocument, i->key);
+ if (key == NULL)
+ {
+ // I've seen a crash bug report with no repro, indicating that this is happening.
+ // If you ever get this error and can repro it, let me know! jonas.
+ ErrorString ("YAML Node is NULL!\n");
+ }
+ else
+ {
+ Assert (key->type == YAML_SCALAR_NODE);
+
+ if (strcmp((char*)key->data.scalar.value, keystr) == 0)
+ {
+ m_CachedIndex = next;
+ return yaml_document_get_node(m_ActiveDocument, i->value);
+ }
+ }
+ i = next;
+ }
+ while (i != start);
+ }
+ return NULL;
+}
+
+
+void YAMLRead::Init(int flags, yaml_read_handler_t *handler, std::string *debugFileName, int debugLineCount)
+{
+ m_UserData = NULL;
+ m_CurrentVersion = 0;
+ m_Flags = flags;
+ m_CachedIndex = NULL;
+ m_ReadHandler = handler;
+
+ yaml_parser_t parser;
+
+ memset(&parser, 0, sizeof(parser));
+ memset(&m_Document, 0, sizeof(m_Document));
+
+ if (!yaml_parser_initialize(&parser))
+ {
+ ErrorString("Could not initialize yaml parser\n");
+ return;
+ }
+
+ yaml_parser_set_input(&parser, handler, this );
+ yaml_parser_load(&parser, &m_Document);
+
+ if (parser.error != YAML_NO_ERROR)
+ {
+ if (debugFileName != NULL)
+ {
+ ErrorStringMsg("Unable to parse file %s: [%s] at line %d\n", debugFileName->c_str(), parser.problem, debugLineCount + (int)parser.problem_mark.line);
+ }
+ else
+ {
+ ErrorStringMsg("Unable to parse YAML file: [%s] at line %d\n", parser.problem, debugLineCount + (int)parser.problem_mark.line);
+ }
+ }
+
+ yaml_parser_delete(&parser);
+
+ m_Versions.push_back(-1);
+ m_CurrentNode = yaml_document_get_root_node(&m_Document);
+ m_ActiveDocument = &m_Document;
+ m_DidReadLastProperty = false;
+}
+
+YAMLRead::YAMLRead (yaml_document_t* yamlDocument, int flags)
+: m_ReadHandler (NULL)
+, m_ActiveDocument (yamlDocument)
+, m_CurrentVersion (0)
+, m_CachedIndex (0)
+, m_DidReadLastProperty (false)
+{
+ m_Flags = flags;
+ memset(&m_Document, 0, sizeof(m_Document));
+ m_Versions.push_back(-1);
+ m_CurrentNode = yaml_document_get_root_node(m_ActiveDocument);
+}
+
+
+int YAMLRead::YAMLReadCacheHandler(void *data, unsigned char *buffer, size_t size, size_t *size_read)
+{
+ YAMLRead *read = (YAMLRead*)data;
+
+ if (read->m_ReadOffset + size > read->m_EndOffset)
+ size = read->m_EndOffset - read->m_ReadOffset;
+
+ ReadFileCache (*(CacheReaderBase*)read->m_ReadData, buffer, read->m_ReadOffset, size);
+ read->m_ReadOffset += size;
+ *size_read = size;
+
+ return true;
+}
+
+int YAMLRead::YAMLReadStringHandler(void *data, unsigned char *buffer, size_t size, size_t *size_read)
+{
+ YAMLRead *read = (YAMLRead*)data;
+
+ if (read->m_ReadOffset + size > read->m_EndOffset)
+ size = read->m_EndOffset - read->m_ReadOffset;
+
+ const char* readData = reinterpret_cast<const char*> (read->m_ReadData);
+
+ memcpy (buffer, readData + read->m_ReadOffset, size);
+ read->m_ReadOffset += size;
+ *size_read = size;
+
+ return true;
+}
+
+YAMLRead::YAMLRead (const char* strBuffer, int size, int flags, std::string *debugFileName, int debugLineCount)
+{
+ m_ReadOffset = 0;
+ m_EndOffset = size;
+ m_ReadData = const_cast<char*> (strBuffer);
+
+ Init (flags, YAMLReadStringHandler, debugFileName, debugLineCount);
+}
+
+YAMLRead::YAMLRead (const CacheReaderBase *input, size_t readOffset, size_t endOffset, int flags, std::string *debugFileName, int debugLineCount)
+{
+ m_ReadOffset = readOffset;
+ m_EndOffset = endOffset;
+ m_ReadData = (void*)input;
+
+ Init (flags, YAMLReadCacheHandler, debugFileName, debugLineCount);
+}
+
+YAMLRead::~YAMLRead()
+{
+ yaml_document_delete(&m_Document);
+}
+
+YAMLNode* YAMLRead::GetCurrentNode ()
+{
+ return YAMLDocNodeToNode(m_ActiveDocument, m_CurrentNode);
+}
+
+YAMLNode* YAMLRead::GetValueNodeForKey (const char* key)
+{
+ return YAMLDocNodeToNode (m_ActiveDocument, GetValueForKey (m_CurrentNode, key));
+}
+
+int YAMLRead::StringOutputHandler(void *data, unsigned char *buffer, size_t size)
+{
+ string* theString = reinterpret_cast<string*> (data);
+ theString->append( (char *) buffer, size);
+ return 1;
+}
+
+void YAMLRead::BeginMetaGroup (std::string name)
+{
+ m_MetaParents.push_back(m_CurrentNode);
+ m_CurrentNode = GetValueForKey(m_CurrentNode, name.c_str());
+}
+
+void YAMLRead::EndMetaGroup ()
+{
+ m_CurrentNode = m_MetaParents.back();
+ m_MetaParents.pop_back();
+}
+
+void YAMLRead::TransferTypelessData (unsigned size, void* data, int metaFlag)
+{
+ UnityStr dataString;
+ Transfer(dataString, "_typelessdata", metaFlag);
+ dataString.resize (size * 2);
+ HexStringToBytes (&dataString[0], size, data);
+}
+
+bool YAMLRead::HasNode (const char* name)
+{
+ return GetValueForKey(m_CurrentNode, name) != NULL;
+}
+