mirror of https://github.com/SeanOMik/libki.git
serialization: Implement JsonSerializer loading functionality
This commit is contained in:
parent
f9ab6560d9
commit
f3aa42578d
|
@ -34,6 +34,12 @@ namespace detail
|
||||||
template <>
|
template <>
|
||||||
struct is_json_assignable<std::string> : std::true_type {};
|
struct is_json_assignable<std::string> : std::true_type {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* std::u16string can be assigned to a json object.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct is_json_assignable<std::u16string> : std::true_type {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* value_caster specialization for the generic case of casting
|
* value_caster specialization for the generic case of casting
|
||||||
* any json-assignable value to a json object.
|
* any json-assignable value to a json object.
|
||||||
|
@ -163,6 +169,34 @@ namespace detail
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caster implementation for casting from json to any
|
||||||
|
* primitive type.
|
||||||
|
*/
|
||||||
|
template <typename DestT>
|
||||||
|
struct value_caster<nlohmann::json, DestT>
|
||||||
|
: value_caster_impl<nlohmann::json, DestT>
|
||||||
|
{
|
||||||
|
DestT cast_value(const nlohmann::json &value) const override
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caster implementation for casting from json to a
|
||||||
|
* std::string.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct value_caster<nlohmann::json, std::string>
|
||||||
|
: value_caster_impl<nlohmann::json, std::string>
|
||||||
|
{
|
||||||
|
std::string cast_value(const nlohmann::json &value) const override
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility to call ValueCaster::declare<SrcT, DestT> with
|
* A utility to call ValueCaster::declare<SrcT, DestT> with
|
||||||
* bi<N> and bui<N> as the destination type.
|
* bi<N> and bui<N> as the destination type.
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace pclass
|
||||||
virtual bool is_dynamic() const;
|
virtual bool is_dynamic() const;
|
||||||
|
|
||||||
virtual Value get_value() const = 0;
|
virtual Value get_value() const = 0;
|
||||||
|
virtual void set_value(Value value) = 0;
|
||||||
|
|
||||||
virtual const PropertyClass *get_object() const = 0;
|
virtual const PropertyClass *get_object() const = 0;
|
||||||
virtual void set_object(std::unique_ptr<PropertyClass> &object) = 0;
|
virtual void set_object(std::unique_ptr<PropertyClass> &object) = 0;
|
||||||
|
|
||||||
|
@ -70,12 +72,14 @@ namespace pclass
|
||||||
virtual void set_element_count(std::size_t size) = 0;
|
virtual void set_element_count(std::size_t size) = 0;
|
||||||
|
|
||||||
Value get_value() const final override;
|
Value get_value() const final override;
|
||||||
|
void set_value(Value value) final override;
|
||||||
const PropertyClass *get_object() const final override;
|
const PropertyClass *get_object() const final override;
|
||||||
void set_object(std::unique_ptr<PropertyClass> &object) final override;
|
void set_object(std::unique_ptr<PropertyClass> &object) final override;
|
||||||
void write_value_to(BitStream &stream) const final override;
|
void write_value_to(BitStream &stream) const final override;
|
||||||
void read_value_from(BitStream &stream) final override;
|
void read_value_from(BitStream &stream) final override;
|
||||||
|
|
||||||
virtual Value get_value(int index) const = 0;
|
virtual Value get_value(int index) const = 0;
|
||||||
|
virtual void set_value(Value value, int index) = 0;
|
||||||
virtual const PropertyClass *get_object(int index) const = 0;
|
virtual const PropertyClass *get_object(int index) const = 0;
|
||||||
virtual void set_object(std::unique_ptr<PropertyClass> &object, int index) = 0;
|
virtual void set_object(std::unique_ptr<PropertyClass> &object, int index) = 0;
|
||||||
virtual void write_value_to(BitStream &stream, int index) const = 0;
|
virtual void write_value_to(BitStream &stream, int index) const = 0;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "ki/pclass/Property.h"
|
#include "ki/pclass/Property.h"
|
||||||
|
#include "ki/pclass/PropertyClass.h"
|
||||||
#include "ki/util/exception.h"
|
#include "ki/util/exception.h"
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
|
@ -42,6 +43,13 @@ namespace pclass
|
||||||
return Value::make_reference<ValueT>(prop.m_value);
|
return Value::make_reference<ValueT>(prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_value(StaticProperty<ValueT> &prop, Value value)
|
||||||
|
{
|
||||||
|
prop.m_value = value
|
||||||
|
.dereference<ValueT>()
|
||||||
|
.get<ValueT>();
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
|
@ -106,6 +114,13 @@ namespace pclass
|
||||||
return Value::make_reference<nonpointer_type>(*prop.m_value);
|
return Value::make_reference<nonpointer_type>(*prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_value(StaticProperty<ValueT> &prop, Value value)
|
||||||
|
{
|
||||||
|
prop.m_value = value
|
||||||
|
.dereference<nonpointer_type>()
|
||||||
|
.take<nonpointer_type>();
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
|
@ -173,6 +188,13 @@ namespace pclass
|
||||||
return Value::make_reference<nonpointer_type>(*prop.m_value);
|
return Value::make_reference<nonpointer_type>(*prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_value(StaticProperty<ValueT> &prop, Value value)
|
||||||
|
{
|
||||||
|
prop.m_value = value
|
||||||
|
.dereference<nonpointer_type>()
|
||||||
|
.take<nonpointer_type>();
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does derive from PropertyClass, and we have a pointer to an instance
|
// ValueT does derive from PropertyClass, and we have a pointer to an instance
|
||||||
|
@ -241,6 +263,13 @@ namespace pclass
|
||||||
return Value::make_reference<ValueT>(prop.m_value);
|
return Value::make_reference<ValueT>(prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_value(StaticProperty<ValueT> &prop, Value value)
|
||||||
|
{
|
||||||
|
prop.m_value = value
|
||||||
|
.dereference<ValueT>()
|
||||||
|
.get<ValueT>();
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
// ValueT does derive from PropertyClass, and we have an instance of ValueT,
|
// ValueT does derive from PropertyClass, and we have an instance of ValueT,
|
||||||
|
@ -343,6 +372,11 @@ namespace pclass
|
||||||
return value_object_helper<ValueT>::get_value(prop);
|
return value_object_helper<ValueT>::get_value(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_value(StaticProperty<ValueT> &prop, Value value)
|
||||||
|
{
|
||||||
|
return value_object_helper<ValueT>::set_value(prop, value);
|
||||||
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
static const PropertyClass *get_object(const StaticProperty<ValueT> &prop)
|
||||||
{
|
{
|
||||||
return value_object_helper<ValueT>::get_object(prop);
|
return value_object_helper<ValueT>::get_object(prop);
|
||||||
|
@ -414,6 +448,11 @@ namespace pclass
|
||||||
return value_helper<ValueT>::get_value(*this);
|
return value_helper<ValueT>::get_value(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_value(Value value) override
|
||||||
|
{
|
||||||
|
value_helper<ValueT>::set_value(*this, value);
|
||||||
|
}
|
||||||
|
|
||||||
const PropertyClass *get_object() const override
|
const PropertyClass *get_object() const override
|
||||||
{
|
{
|
||||||
return value_helper<ValueT>::get_object(*this);
|
return value_helper<ValueT>::get_object(*this);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <json.hpp>
|
||||||
#include "ki/pclass/HashCalculator.h"
|
#include "ki/pclass/HashCalculator.h"
|
||||||
#include "ki/pclass/Casters.h"
|
#include "ki/pclass/Casters.h"
|
||||||
#include "ki/pclass/types/Type.h"
|
#include "ki/pclass/types/Type.h"
|
||||||
|
@ -32,6 +33,8 @@ namespace pclass
|
||||||
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
||||||
{
|
{
|
||||||
detail::caster_declarer<ValueT>::declare();
|
detail::caster_declarer<ValueT>::declare();
|
||||||
|
ValueCaster::declare<nlohmann::json, ValueT>();
|
||||||
|
|
||||||
auto *type = new PrimitiveType<ValueT>(name, *this);
|
auto *type = new PrimitiveType<ValueT>(name, *this);
|
||||||
define_type(std::unique_ptr<Type>(
|
define_type(std::unique_ptr<Type>(
|
||||||
dynamic_cast<Type *>(type)
|
dynamic_cast<Type *>(type)
|
||||||
|
@ -58,6 +61,8 @@ namespace pclass
|
||||||
CppEnumType<EnumT> &define_enum(const std::string &name)
|
CppEnumType<EnumT> &define_enum(const std::string &name)
|
||||||
{
|
{
|
||||||
detail::caster_declarer<EnumT>::declare();
|
detail::caster_declarer<EnumT>::declare();
|
||||||
|
ValueCaster::declare<nlohmann::json, EnumT>();
|
||||||
|
|
||||||
auto *type = new CppEnumType<EnumT>(name, *this);
|
auto *type = new CppEnumType<EnumT>(name, *this);
|
||||||
define_type(std::unique_ptr<Type>(
|
define_type(std::unique_ptr<Type>(
|
||||||
dynamic_cast<Type *>(type)
|
dynamic_cast<Type *>(type)
|
||||||
|
|
|
@ -79,6 +79,11 @@ namespace pclass
|
||||||
* @param[in] ptr The pointer to deallocate.
|
* @param[in] ptr The pointer to deallocate.
|
||||||
*/
|
*/
|
||||||
virtual void deallocate(void *ptr) const = 0;
|
virtual void deallocate(void *ptr) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a copy of this deallocator.
|
||||||
|
*/
|
||||||
|
virtual value_deallocator_base *copy() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,18 +97,25 @@ namespace pclass
|
||||||
// By default, now that we have the proper type, just delete it.
|
// By default, now that we have the proper type, just delete it.
|
||||||
delete static_cast<T *>(ptr);
|
delete static_cast<T *>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_deallocator_base *copy() const override
|
||||||
|
{
|
||||||
|
return new value_deallocator<T>();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
*/
|
*/
|
||||||
class ValueDeallocator
|
class ValueDeallocator
|
||||||
{
|
{
|
||||||
// Allow Value to call make<T>() and the default constructor
|
// Allow Value to call make<T>() and the default constructor
|
||||||
friend Value;
|
friend Value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ValueDeallocator(ValueDeallocator &that);
|
||||||
ValueDeallocator(ValueDeallocator &&that) noexcept;
|
ValueDeallocator(ValueDeallocator &&that) noexcept;
|
||||||
|
ValueDeallocator &operator=(ValueDeallocator &that);
|
||||||
ValueDeallocator &operator=(ValueDeallocator &&that) noexcept;
|
ValueDeallocator &operator=(ValueDeallocator &&that) noexcept;
|
||||||
~ValueDeallocator();
|
~ValueDeallocator();
|
||||||
|
|
||||||
|
@ -220,7 +232,9 @@ namespace pclass
|
||||||
class Value
|
class Value
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Value(Value &that);
|
||||||
Value(Value &&that) noexcept;
|
Value(Value &&that) noexcept;
|
||||||
|
Value &operator=(Value &that);
|
||||||
Value &operator=(Value &&that) noexcept;
|
Value &operator=(Value &&that) noexcept;
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,15 @@ namespace pclass
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
return Value::make_reference(prop.at(index));
|
return Value::make_reference<ValueT>(prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(VectorProperty<ValueT> &prop,
|
||||||
|
Value value, const int index)
|
||||||
|
{
|
||||||
|
prop.at(index) = value
|
||||||
|
.dereference<ValueT>()
|
||||||
|
.get<ValueT>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
@ -79,6 +87,8 @@ namespace pclass
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
using nonpointer_type = typename std::remove_pointer<ValueT>::type;
|
||||||
|
|
||||||
static ValueT copy(VectorProperty<ValueT> &prop, const int index)
|
static ValueT copy(VectorProperty<ValueT> &prop, const int index)
|
||||||
{
|
{
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
|
@ -95,7 +105,15 @@ namespace pclass
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
return Value::make_reference(*prop.at(index));
|
return Value::make_reference<nonpointer_type>(*prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(VectorProperty<ValueT> &prop,
|
||||||
|
Value value, const int index)
|
||||||
|
{
|
||||||
|
prop.at(index) = value
|
||||||
|
.dereference<nonpointer_type>()
|
||||||
|
.take<nonpointer_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
@ -135,6 +153,8 @@ namespace pclass
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
using nonpointer_type = typename std::remove_pointer<ValueT>::type;
|
||||||
|
|
||||||
static ValueT copy(VectorProperty<ValueT> &prop, const int index)
|
static ValueT copy(VectorProperty<ValueT> &prop, const int index)
|
||||||
{
|
{
|
||||||
// The copy constructor for all pointers is to copy the pointer
|
// The copy constructor for all pointers is to copy the pointer
|
||||||
|
@ -147,7 +167,15 @@ namespace pclass
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
return Value::make_reference(*prop.at(index));
|
return Value::make_reference<nonpointer_type>(*prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(VectorProperty<ValueT> &prop,
|
||||||
|
Value value, const int index)
|
||||||
|
{
|
||||||
|
prop.at(index) = value
|
||||||
|
.dereference<nonpointer_type>()
|
||||||
|
.take<nonpointer_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
@ -214,7 +242,15 @@ namespace pclass
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
return Value::make_reference(prop.at(index));
|
return Value::make_reference<ValueT>(prop.at(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(VectorProperty<ValueT> &prop,
|
||||||
|
Value value, const int index)
|
||||||
|
{
|
||||||
|
prop.at(index) = value
|
||||||
|
.dereference<ValueT>()
|
||||||
|
.get<ValueT>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop, const int index)
|
||||||
|
@ -326,18 +362,24 @@ namespace pclass
|
||||||
return vector_value_object_helper<ValueT>::copy(prop, index);
|
return vector_value_object_helper<ValueT>::copy(prop, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop,
|
|
||||||
const int index)
|
|
||||||
{
|
|
||||||
return vector_value_object_helper<ValueT>::get_object(prop, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Value get_value(const VectorProperty<ValueT> &prop,
|
static Value get_value(const VectorProperty<ValueT> &prop,
|
||||||
const int index)
|
const int index)
|
||||||
{
|
{
|
||||||
return vector_value_object_helper<ValueT>::get_value(prop, index);
|
return vector_value_object_helper<ValueT>::get_value(prop, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_value(VectorProperty<ValueT> &prop,
|
||||||
|
Value value, const int index)
|
||||||
|
{
|
||||||
|
vector_value_object_helper<ValueT>::set_value(prop, value, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop,
|
||||||
|
const int index)
|
||||||
|
{
|
||||||
|
return vector_value_object_helper<ValueT>::get_object(prop, index);
|
||||||
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop,
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
std::unique_ptr<PropertyClass> &object, const int index)
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
|
@ -405,6 +447,13 @@ namespace pclass
|
||||||
return vector_value_helper<ValueT>::get_value(*this, index);
|
return vector_value_helper<ValueT>::get_value(*this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_value(Value value, int index) override
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= this->size())
|
||||||
|
throw runtime_error("Index out of bounds.");
|
||||||
|
return vector_value_helper<ValueT>::set_value(*this, value, index);
|
||||||
|
}
|
||||||
|
|
||||||
const PropertyClass *get_object(const int index) const override
|
const PropertyClass *get_object(const int index) const override
|
||||||
{
|
{
|
||||||
return vector_value_helper<ValueT>::get_object(*this, index);
|
return vector_value_helper<ValueT>::get_object(*this, index);
|
||||||
|
|
|
@ -30,6 +30,11 @@ namespace serialization
|
||||||
nlohmann::json save_object(const pclass::PropertyClass *object) const;
|
nlohmann::json save_object(const pclass::PropertyClass *object) const;
|
||||||
void save_property(nlohmann::json &j, const pclass::IProperty &prop) const;
|
void save_property(nlohmann::json &j, const pclass::IProperty &prop) const;
|
||||||
void save_dynamic_property(nlohmann::json &j, const pclass::IDynamicProperty &prop) const;
|
void save_dynamic_property(nlohmann::json &j, const pclass::IDynamicProperty &prop) const;
|
||||||
|
|
||||||
|
virtual bool preload_object(std::unique_ptr<pclass::PropertyClass> &dest, nlohmann::json &j) const;
|
||||||
|
void load_object(std::unique_ptr<pclass::PropertyClass> &dest, nlohmann::json &j) const;
|
||||||
|
void load_property(pclass::IProperty &prop, nlohmann::json &j) const;
|
||||||
|
void load_dynamic_property(pclass::IDynamicProperty &prop, nlohmann::json &j) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,12 @@ namespace pclass
|
||||||
throw runtime_error("Called get_value() on a dynamic property. Use get_value(index) instead.");
|
throw runtime_error("Called get_value() on a dynamic property. Use get_value(index) instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IDynamicProperty::set_value(Value value)
|
||||||
|
{
|
||||||
|
// The caller must specify an index
|
||||||
|
throw runtime_error("Called set_value() on a dynamic property. Use set_value(index) instead.");
|
||||||
|
}
|
||||||
|
|
||||||
const PropertyClass *IDynamicProperty::get_object() const
|
const PropertyClass *IDynamicProperty::get_object() const
|
||||||
{
|
{
|
||||||
// The caller must specify an index
|
// The caller must specify an index
|
||||||
|
|
|
@ -24,12 +24,23 @@ namespace pclass
|
||||||
m_deallocator = deallocator;
|
m_deallocator = deallocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueDeallocator::ValueDeallocator(ValueDeallocator &that)
|
||||||
|
{
|
||||||
|
m_deallocator = that.m_deallocator->copy();
|
||||||
|
}
|
||||||
|
|
||||||
ValueDeallocator::ValueDeallocator(ValueDeallocator &&that) noexcept
|
ValueDeallocator::ValueDeallocator(ValueDeallocator &&that) noexcept
|
||||||
{
|
{
|
||||||
m_deallocator = that.m_deallocator;
|
m_deallocator = that.m_deallocator;
|
||||||
that.m_deallocator = nullptr;
|
that.m_deallocator = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueDeallocator &ValueDeallocator::operator=(ValueDeallocator &that)
|
||||||
|
{
|
||||||
|
m_deallocator = that.m_deallocator->copy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
ValueDeallocator& ValueDeallocator::operator=(ValueDeallocator &&that) noexcept
|
ValueDeallocator& ValueDeallocator::operator=(ValueDeallocator &&that) noexcept
|
||||||
{
|
{
|
||||||
m_deallocator = that.m_deallocator;
|
m_deallocator = that.m_deallocator;
|
||||||
|
@ -76,6 +87,15 @@ namespace pclass
|
||||||
m_deallocator = detail::ValueDeallocator();
|
m_deallocator = detail::ValueDeallocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value::Value(Value& that)
|
||||||
|
{
|
||||||
|
m_value_ptr = that.m_value_ptr;
|
||||||
|
m_ptr_is_owned = false;
|
||||||
|
m_type_hash = that.m_type_hash;
|
||||||
|
m_caster = that.m_caster;
|
||||||
|
m_deallocator = that.m_deallocator;
|
||||||
|
}
|
||||||
|
|
||||||
Value::Value(Value &&that) noexcept
|
Value::Value(Value &&that) noexcept
|
||||||
{
|
{
|
||||||
// Move pointer to this Value object, and take ownership if
|
// Move pointer to this Value object, and take ownership if
|
||||||
|
@ -88,6 +108,17 @@ namespace pclass
|
||||||
m_deallocator = std::move(that.m_deallocator);
|
m_deallocator = std::move(that.m_deallocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value &Value::operator=(Value &that)
|
||||||
|
{
|
||||||
|
m_value_ptr = that.m_value_ptr;
|
||||||
|
m_ptr_is_owned = false;
|
||||||
|
m_type_hash = that.m_type_hash;
|
||||||
|
m_caster = that.m_caster;
|
||||||
|
m_deallocator = that.m_deallocator;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Value &Value::operator=(Value &&that) noexcept
|
Value &Value::operator=(Value &&that) noexcept
|
||||||
{
|
{
|
||||||
// If the current pointer is owned, deallocate it
|
// If the current pointer is owned, deallocate it
|
||||||
|
|
|
@ -435,6 +435,5 @@ namespace serialization
|
||||||
prop.read_value_from(stream, i);
|
prop.read_value_from(stream, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ki/serialization/JsonSerializer.h"
|
#include "ki/serialization/JsonSerializer.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
|
|
||||||
|
@ -54,7 +55,6 @@ namespace serialization
|
||||||
{
|
{
|
||||||
if (prop.is_dynamic())
|
if (prop.is_dynamic())
|
||||||
{
|
{
|
||||||
// Cast the property to a IDynamicProperty
|
|
||||||
const auto &dynamic_property =
|
const auto &dynamic_property =
|
||||||
dynamic_cast<const pclass::IDynamicProperty &>(prop);
|
dynamic_cast<const pclass::IDynamicProperty &>(prop);
|
||||||
return save_dynamic_property(j, dynamic_property);
|
return save_dynamic_property(j, dynamic_property);
|
||||||
|
@ -94,12 +94,108 @@ namespace serialization
|
||||||
j[prop.get_name()] = property_value;
|
j[prop.get_name()] = property_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonSerializer::load(std::unique_ptr<pclass::PropertyClass>& dest,
|
void JsonSerializer::load(std::unique_ptr<pclass::PropertyClass> &dest,
|
||||||
const std::string& json_string) const
|
const std::string &json_string) const
|
||||||
{
|
{
|
||||||
// TODO: JSON Deserialization
|
try
|
||||||
auto j = json::parse(json_string);
|
{
|
||||||
dest = nullptr;
|
auto j = json::parse(json_string);
|
||||||
|
load_object(dest, j);
|
||||||
|
}
|
||||||
|
catch (json::exception &e)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to deserialize JSON - " << e.what();
|
||||||
|
throw runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JsonSerializer::preload_object(
|
||||||
|
std::unique_ptr<pclass::PropertyClass>& dest, json& j) const
|
||||||
|
{
|
||||||
|
// If meta information is not present, assume that the type hash is null.
|
||||||
|
if (!j.count("_pclass_meta"))
|
||||||
|
dest = nullptr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use the type hash to instantiate an object
|
||||||
|
const auto type_hash = j["_pclass_meta"].value("type_hash", NULL);
|
||||||
|
if (type_hash != 0)
|
||||||
|
{
|
||||||
|
const auto &type = m_type_system->get_type(type_hash);
|
||||||
|
dest = type.instantiate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dest = nullptr;
|
||||||
|
}
|
||||||
|
return dest != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonSerializer::load_object(
|
||||||
|
std::unique_ptr<pclass::PropertyClass> &dest, json &j) const
|
||||||
|
{
|
||||||
|
if (!preload_object(dest, j))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto &property_list = dest->get_properties();
|
||||||
|
for (auto it = property_list.begin();
|
||||||
|
it != property_list.end(); ++it)
|
||||||
|
{
|
||||||
|
auto &prop = *it;
|
||||||
|
load_property(prop, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonSerializer::load_property(
|
||||||
|
pclass::IProperty &prop, json &j) const
|
||||||
|
{
|
||||||
|
if (!j.count(prop.get_name()))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "JSON object missing property: '" << prop.get_name() << "' "
|
||||||
|
<< "(type='" << prop.get_instance().get_type().get_name() << "').";
|
||||||
|
throw runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &property_j = j[prop.get_name()];
|
||||||
|
if (prop.is_dynamic())
|
||||||
|
{
|
||||||
|
auto &dynamic_property =
|
||||||
|
dynamic_cast<pclass::IDynamicProperty &>(prop);
|
||||||
|
return load_dynamic_property(dynamic_property, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop.get_type().get_kind() == pclass::Type::kind::CLASS)
|
||||||
|
{
|
||||||
|
std::unique_ptr<pclass::PropertyClass> other_object = nullptr;
|
||||||
|
load_object(other_object, property_j);
|
||||||
|
prop.set_object(other_object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prop.set_value(
|
||||||
|
pclass::Value::make_reference<json>(property_j)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonSerializer::load_dynamic_property(
|
||||||
|
pclass::IDynamicProperty &prop, json &j) const
|
||||||
|
{
|
||||||
|
auto &property_j = j[prop.get_name()];
|
||||||
|
prop.set_element_count(property_j.size());
|
||||||
|
|
||||||
|
for (auto i = 0; i < prop.get_element_count(); ++i)
|
||||||
|
{
|
||||||
|
if (prop.get_type().get_kind() == pclass::Type::kind::CLASS)
|
||||||
|
{
|
||||||
|
std::unique_ptr<pclass::PropertyClass> other_object = nullptr;
|
||||||
|
load_object(other_object, property_j.at(i));
|
||||||
|
prop.set_object(other_object, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prop.set_value(
|
||||||
|
pclass::Value::make_reference<json>(property_j.at(i)), i
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace detail
|
||||||
struct value_caster<Vector3D, nlohmann::json>
|
struct value_caster<Vector3D, nlohmann::json>
|
||||||
: value_caster_impl<Vector3D, nlohmann::json>
|
: value_caster_impl<Vector3D, nlohmann::json>
|
||||||
{
|
{
|
||||||
nlohmann::json cast_value(const Vector3D &value) const
|
nlohmann::json cast_value(const Vector3D &value) const override
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
{ "x", value.m_x },
|
{ "x", value.m_x },
|
||||||
|
@ -125,7 +125,7 @@ namespace detail
|
||||||
struct value_caster<nlohmann::json, Vector3D>
|
struct value_caster<nlohmann::json, Vector3D>
|
||||||
: value_caster_impl<nlohmann::json, Vector3D>
|
: value_caster_impl<nlohmann::json, Vector3D>
|
||||||
{
|
{
|
||||||
Vector3D cast_value(const nlohmann::json &value) const
|
Vector3D cast_value(const nlohmann::json &value) const override
|
||||||
{
|
{
|
||||||
return Vector3D(
|
return Vector3D(
|
||||||
value["x"].get<float>(),
|
value["x"].get<float>(),
|
||||||
|
@ -562,13 +562,11 @@ void test_serializer(
|
||||||
serializer.load(object, sample);
|
serializer.load(object, sample);
|
||||||
|
|
||||||
// Set test_object so that it is validated by the caller
|
// Set test_object so that it is validated by the caller
|
||||||
/*
|
|
||||||
REQUIRE(object != nullptr);
|
REQUIRE(object != nullptr);
|
||||||
test_object = std::unique_ptr<TestObject>(
|
test_object = std::unique_ptr<TestObject>(
|
||||||
dynamic_cast<TestObject *>(object.release())
|
dynamic_cast<TestObject *>(object.release())
|
||||||
);
|
);
|
||||||
REQUIRE(test_object != nullptr);
|
REQUIRE(test_object != nullptr);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue