#pragma once #include "text.h" namespace YAML { template inline string TextSerialize::Serialize(const Any& any) { if constexpr (Check_IsString) { return string(*any.CastTo()); } else if constexpr(Check_ToString){ return std::to_string(*any.CastTo()); } else { return string(any.cls->name.GetView()); } } template inline bool TextSerialize::Unserialize(const string& val, const Any& any) { if constexpr (Check_IsString) { return new (any.CastTo())T(val); } else if constexpr (std::is_arithmetic_v) { if constexpr (std::is_integral_v) { *any.CastTo() = std::stoul(val); return true; } else if constexpr (std::is_floating_point_v) { *any.CastTo() = std::stold(val); return true; } } else { return false; } } inline StringFuncMap TextArchive::BuildStringMap() { StringFuncMap funcMap; #define RegisterAny(T) funcMap.emplace(&TypeInfo::StaticClass, std::make_pair(&TextSerialize::Serialize, &TextSerialize::Unserialize)) #include "register.inl" #undef RegisterAny return funcMap; } template inline void TextArchive::Register() { FuncMap.emplace(&TypeInfo::StaticClass, std::make_pair(&TextSerialize::Serialize, &TextSerialize::Unserialize)); } inline Node TextArchive::Serialize(const Any& any) { if (!any) { return {}; } auto it = FuncMap.find(any.cls); if (it != FuncMap.end()) { return Node{ it->second.first(any)}; } Node result; if (any.cls == &refl::TypeInfo::StaticClass) { Any obj = any.CastTo(); if (obj) { result["__class__"] = string(obj.cls->name); result["__data__"] = Serialize(obj); } return result; } if (any.IsContainer()) { auto docker = any.ToContainer(); bool isMap = any.IsMap(); auto fieldList = any.ContainerValue()->GetFields(refl::FIND_ALL_MEMBER, FName("")); for (auto obj : docker) { if (isMap) { Any first = obj.Member(*fieldList[0]); Any second = obj.Member(*fieldList[1]); result[Serialize(first)] = Serialize(second); } else { result.push_back(Serialize(obj)); } } return result; } if (any.IsArray()) { int n = any.ArraySize(); for (int i = 0; i < n; i++) { result.push_back(Serialize(any.Member(i))); } return result; } if (Any p = any.Parent()) { result["__parent__"] = Serialize(p); } auto fieldList = any.cls->GetFields(refl::FIND_ALL_MEMBER, FName("")); for (auto& field : fieldList) { Node child = Serialize(any.Member(field)); result[field.name.GetView()] = child; } return result; } inline bool TextArchive::Unserialize(const Node& res, const Any& any) { if (!any) { return false; } if (res.IsNull()) { const string& str = ""; return any.Construct(Any{ &str, &TypeInfo::StaticClass }); } auto it = FuncMap.find(any.cls); if (it != FuncMap.end()) { return it->second.second(res.as(),any); } if (any.cls == &refl::TypeInfo::StaticClass) { string name = res["__class__"].as(); auto cls = refl::UClass::Find(Name(name)); if (cls) { Any obj = cls->New(); *any.CastTo() = obj; return Unserialize(res["__data__"], obj); } *any.CastTo() = {}; return false; } if (any.IsContainer()) { auto docker = any.ToContainer(); docker.construct(); char memory[STACK_MEMORY_SIZE]; Any any = docker.try_malloc(&memory, STACK_MEMORY_SIZE); bool isMap = res.IsMap() && any.IsMap(); Any first, second; if (isMap) { auto fieldList = any.ContainerValue()->GetFields(refl::FIND_ALL_MEMBER, FName("")); first = any.Member(*fieldList.at(0)); second = any.Member(*fieldList.at(1)); } for (auto it : res) { if (isMap) { Unserialize(it.first, first); Unserialize(it.second, second); } else { Unserialize(it, any); } docker.insert(any); any.Destruct(); } docker.try_free(any, STACK_MEMORY_SIZE); return true; } if (res.IsSequence() && any.IsArray()) { for (std::size_t i = 0; i < res.size(); i++) { Unserialize(res[i], any.Member(i)); } return true; } if (res.IsMap() && any.IsObject()) { auto fieldList = any.cls->GetFields(refl::FIND_ALL_MEMBER, FName("")); auto rt = res.begin(); int diff = res.size() - fieldList.size(); if (diff == 1 && any.CheckParent()) { diff = 0; Unserialize(rt++->second, any.Parent()); } else if (diff != 0) { return false; } auto ft = fieldList.begin(); for (; ft != fieldList.end() && rt != res.end(); ++ft,++rt) { if (ft->name != Name(rt->first.as())) { return false; } Unserialize(rt->second, any.Member(*ft)); } return true; } if (res.IsScalar() && any.IsObject()) { const string& str = res.as(); return any.Construct(Any{&str, &TypeInfo::StaticClass}); } return false; } }