summaryrefslogtreecommitdiff
path: root/Runtime/Serialize/TransferFunctions/YAMLWrite.h
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/YAMLWrite.h
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Serialize/TransferFunctions/YAMLWrite.h')
-rw-r--r--Runtime/Serialize/TransferFunctions/YAMLWrite.h340
1 files changed, 340 insertions, 0 deletions
diff --git a/Runtime/Serialize/TransferFunctions/YAMLWrite.h b/Runtime/Serialize/TransferFunctions/YAMLWrite.h
new file mode 100644
index 0000000..89c509c
--- /dev/null
+++ b/Runtime/Serialize/TransferFunctions/YAMLWrite.h
@@ -0,0 +1,340 @@
+#ifndef YAMLWRITE_H
+#define YAMLWRITE_H
+
+#include "Runtime/Serialize/TransferFunctions/TransferBase.h"
+#include "YAMLSerializeTraits.h"
+#include "Editor/Src/Utility/YAMLNode.h"
+#include "External/yaml/include/yaml.h"
+#include "Runtime/Serialize/FloatStringConversion.h"
+
+class CachedWriter;
+struct YAMLConverterContext;
+
+class YAMLWrite : public TransferBase
+{
+private:
+
+ struct MetaParent
+ {
+ int node;
+ std::string name;
+ };
+
+ std::vector<MetaParent> m_MetaParents;
+ std::vector<int> m_MetaFlags;
+ yaml_document_t m_Document;
+ int m_CurrentNode;
+ bool m_Error;
+ std::string m_DebugFileName;
+
+ void TransferStringToCurrentNode (const char* str);
+ int NewMapping ();
+ int NewSequence ();
+ int GetNode ();
+ void AppendToNode(int parentNode, const char* keyStr, int valueNode);
+ static int StringOutputHandler(void *data, unsigned char *buffer, size_t size);
+ static int CacheOutputHandler(void *data, unsigned char *buffer, size_t size);
+
+ void OutputToHandler (yaml_write_handler_t *handler, void *data);
+
+public:
+
+ YAMLWrite (int flags, std::string *debugFileName = NULL);
+ ~YAMLWrite();
+
+ void OutputToCachedWriter (CachedWriter* writer);
+ void OutputToString (std::string& str);
+
+ // Sets the "version of the class currently transferred"
+ void SetVersion (int version);
+
+ bool HasError () { return m_Error; }
+ bool IsWriting () { return true; }
+ bool IsWritingPPtr () { return true; }
+ bool NeedsInstanceIDRemapping () { return m_Flags & kNeedsInstanceIDRemapping; }
+ bool AssetMetaDataOnly () { return m_Flags & kAssetMetaDataOnly; }
+ bool IsSerializingForGameRelease () { return false; }
+
+ void SetFlowMappingStyle (bool on);
+
+ yaml_document_t* GetDocument () { return &m_Document; }
+ int GetCurrentNodeIndex () { return m_CurrentNode; }
+
+ void PushMetaFlag (int flag) { m_MetaFlags.push_back(flag | m_MetaFlags.back());}
+ void PopMetaFlag () { m_MetaFlags.pop_back(); }
+ void AddMetaFlag(int mask) { m_MetaFlags.back() |= mask; }
+
+ void BeginMetaGroup (std::string name);
+ void EndMetaGroup ();
+ void StartSequence ();
+
+ template<class T>
+ void Transfer (T& data, const char* name, int metaFlag = 0);
+ template<class T>
+ void TransferWithTypeString (T& data, const char*, const char*, int metaFlag = 0);
+
+ void TransferTypeless (unsigned* value, const char* name, int metaFlag = 0)
+ {
+ Transfer(*value, name, metaFlag);
+ }
+
+ void TransferTypelessData (unsigned size, void* data, int metaFlag = 0);
+
+ template<class T>
+ void TransferBasicData (T& data);
+
+ template<class T>
+ void TransferPtr (bool, ReduceCopyData*){}
+
+ template<class T>
+ void TransferStringData (T& data);
+
+ template<class T>
+ void TransferSTLStyleArray (T& data, int metaFlag = 0);
+
+ template<class T>
+ void TransferSTLStyleMap (T& data, int metaFlag = 0);
+
+ template<class T>
+ void TransferSTLStyleSet (T& data, int metaFlag = 0);
+
+ template<class T>
+ void TransferPair (T& data, int metaFlag = 0, int parent = -1);
+};
+
+template<>
+inline void YAMLWrite::TransferBasicData<SInt64> (SInt64& data)
+{
+ char valueStr[17];
+ BytesToHexString (&data, sizeof(SInt64), valueStr);
+ valueStr[16] = '\0';
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<UInt64> (UInt64& data)
+{
+ char valueStr[17];
+ BytesToHexString (&data, sizeof(UInt64), valueStr);
+ valueStr[16] = '\0';
+ TransferStringToCurrentNode (valueStr);
+}
+
+// This are the definitions of std::numeric_limits<>::max_digits10, which we cannot use
+// because it is only in the C++11 standard.
+const int kMaxFloatDigits = std::floor(std::numeric_limits<float>::digits * 3010.0/10000.0 + 2);
+const int kMaxDoubleDigits = std::floor(std::numeric_limits<double>::digits * 3010.0/10000.0 + 2);
+
+template<>
+inline void YAMLWrite::TransferBasicData<float> (float& data)
+{
+ char valueStr[64];
+ if (FloatToStringAccurate(data, valueStr, 64))
+ TransferStringToCurrentNode (valueStr);
+ else
+ TransferStringToCurrentNode ("error");
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<double> (double& data)
+{
+ char valueStr[64];
+ if (DoubleToStringAccurate (data, valueStr, 64))
+ TransferStringToCurrentNode (valueStr);
+ else
+ TransferStringToCurrentNode ("error");
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<char> (char& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%hhd", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<SInt8> (SInt8& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%hhd", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<UInt8> (UInt8& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%hhu", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<SInt32> (SInt32& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%d", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<UInt32> (UInt32& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%u", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<SInt16> (SInt16& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%hd", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<>
+inline void YAMLWrite::TransferBasicData<UInt16> (UInt16& data)
+{
+ char valueStr[16];
+ snprintf(valueStr, 16, "%hu", data);
+ TransferStringToCurrentNode (valueStr);
+}
+
+template<class T>
+inline void YAMLWrite::TransferStringData (T& data)
+{
+ TransferStringToCurrentNode (data.c_str());
+}
+
+template<class T>
+void YAMLWrite::Transfer (T& data, const char* _name, int metaFlag)
+{
+ if (m_Error)
+ return;
+
+ if (metaFlag & kIgnoreInMetaFiles)
+ return;
+
+ std::string name = YAMLSerializeTraits<T>::ParseName(_name, AssetMetaDataOnly());
+
+ PushMetaFlag(0);
+
+ int parent = GetNode();
+ m_CurrentNode = -1;
+
+ YAMLSerializeTraits<T>::Transfer (data, *this);
+
+ if (m_CurrentNode != -1)
+ AppendToNode (parent, name.c_str(), m_CurrentNode);
+
+ PopMetaFlag();
+
+ m_CurrentNode = parent;
+}
+
+template<class T>
+void YAMLWrite::TransferWithTypeString (T& data, const char* name, const char*, int metaFlag)
+{
+ Transfer(data, name, metaFlag);
+}
+
+
+template<class T>
+void YAMLWrite::TransferSTLStyleArray (T& data, int metaFlag)
+{
+ typedef typename NonConstContainerValueType<T>::value_type non_const_value_type;
+ if (YAMLSerializeTraits<non_const_value_type>::ShouldSerializeArrayAsCompactString())
+ {
+#if UNITY_BIG_ENDIAN
+#error "Needs swapping to be implemented to work on big endian platforms!"
+#endif
+ std::string str;
+ size_t numElements = data.size();
+ size_t numBytes = numElements * sizeof(non_const_value_type);
+ str.resize (numBytes*2);
+
+ typename T::iterator dataIterator = data.begin ();
+ for (size_t i=0; i<numElements; i++)
+ {
+ BytesToHexString ((void*)&*dataIterator, sizeof(non_const_value_type), &str[i*2*sizeof(non_const_value_type)]);
+ ++dataIterator;
+ }
+
+ TransferStringData (str);
+ }
+ else
+ {
+ m_CurrentNode = NewSequence ();
+
+ typename T::iterator i = data.begin ();
+ typename T::iterator end = data.end ();
+ while (i != end)
+ {
+ Transfer (*i, "data", metaFlag);
+ ++i;
+ }
+ }
+}
+
+template<class T>
+void YAMLWrite::TransferSTLStyleMap (T& data, int metaFlag)
+{
+ m_CurrentNode = NewMapping ();
+
+ typename T::iterator i = data.begin ();
+ typename T::iterator end = data.end ();
+
+
+ // maps value_type is: pair<const First, Second>
+ // So we have to write to maps non-const value type
+ typedef typename NonConstContainerValueType<T>::value_type non_const_value_type;
+ typedef typename non_const_value_type::first_type first_type;
+ while (i != end)
+ {
+ non_const_value_type& p = (non_const_value_type&)(*i);
+ if (YAMLSerializeTraits<first_type>::IsBasicType())
+ TransferPair (p, metaFlag, m_CurrentNode);
+ else
+ Transfer (p, "data", metaFlag);
+ i++;
+ }
+}
+
+template<class T>
+void YAMLWrite::TransferSTLStyleSet (T& data, int metaFlag)
+{
+ m_CurrentNode = NewSequence ();
+
+ typename T::iterator i = data.begin ();
+ typename T::iterator end = data.end ();
+
+ typedef typename NonConstContainerValueType<T>::value_type non_const_value_type;
+ while (i != end)
+ {
+ non_const_value_type& p = (non_const_value_type&)(*i);
+ Transfer (p, "data", metaFlag);
+ ++i;
+ }
+}
+
+template<class T>
+void YAMLWrite::TransferPair (T& data, int /*metaFlag*/, int parent)
+{
+ typedef typename T::first_type first_type;
+ typedef typename T::second_type second_type;
+ if (parent == -1)
+ parent = NewMapping ();
+
+ m_CurrentNode = -1;
+ YAMLSerializeTraits<first_type>::Transfer (data.first, *this);
+ int key = m_CurrentNode;
+
+ m_CurrentNode = -1;
+ YAMLSerializeTraits<second_type>::Transfer (data.second, *this);
+
+ yaml_document_append_mapping_pair(&m_Document, parent, key, m_CurrentNode);
+
+ m_CurrentNode = parent;
+}
+#endif