135 lines
3.5 KiB
C++
135 lines
3.5 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.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<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(""));
|
|
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<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;
|
|
}
|
|
} |