zengine-old/engine/3rdparty/zlib/include/yaml/serialize/text.inl
2024-07-03 21:59:02 +08:00

143 lines
3.7 KiB
C++

#pragma once
#include "text.h"
namespace YAML
{
template<typename T>
inline string TextSerialize<T>::Serialize(const Any& any)
{
if constexpr (Check_IsString<T>) {
return string(*any.CastTo<T*>());
}
else if constexpr(Check_ToString<T>){
return std::to_string(*any.CastTo<T*>());
}
else {
return string(any.cls->name.GetView());
}
}
template<typename T>
inline bool TextSerialize<T>::Unserialize(const string& val, const Any& any)
{
if constexpr (Check_IsString<T>) {
return new (any.CastTo<T*>())T(val);
}
else if constexpr (std::is_arithmetic_v<T>) {
if constexpr (std::is_integral_v<T>) {
*any.CastTo<T*>() = std::stoul(val);
return true;
}
else if constexpr (std::is_floating_point_v<T>) {
*any.CastTo<T*>() = std::stold(val);
return true;
}
}
else {
return false;
}
}
inline StringFuncMap TextArchive::BuildStringMap()
{
StringFuncMap funcMap;
#define RegisterAny(T) funcMap.emplace(&TypeInfo<T>::StaticClass, std::make_pair(&TextSerialize<T>::Serialize, &TextSerialize<T>::Unserialize))
#include "register.inl"
#undef RegisterAny
return funcMap;
}
template<typename T>
inline void TextArchive::Register()
{
FuncMap.emplace(&TypeInfo<T>::StaticClass, std::make_pair(&TextSerialize<T>::Serialize, &TextSerialize<T>::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.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;
}
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<string>::StaticClass });
}
auto it = FuncMap.find(any.cls);
if (it != FuncMap.end()) {
return it->second.second(res.as<string>(),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(""));
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<string>())) {
return false;
}
Unserialize(rt->second, any.Member(*ft));
}
return true;
}
if (res.IsScalar() && any.IsObject()) {
const string& str = res.as<string>();
return any.Construct(Any{&str, &TypeInfo<string>::StaticClass});
}
return false;
}
}