#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.IsValid()) { return {}; } auto it = FuncMap.find(any.cls); if (it != FuncMap.end()) { return Node{ it->second.first(any)}; } Node result; if (any.IsContainer()) { auto docker = any.ToContainer(); for (auto obj : docker) { 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; } 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.IsValid()) { 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 (res.IsSequence() && any.IsContainer()) { auto docker = any.ToContainer(); docker.construct(); char memory[STACK_MEMORY_SIZE]; Any any = docker.try_malloc(&memory, STACK_MEMORY_SIZE); for (std::size_t i = 0; i < res.size(); i++) { Unserialize(res[i], 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("")); if (fieldList.size() != res.size()) { return false; } auto ft = fieldList.begin(); auto rt = res.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; } }