mirror of https://github.com/SeanOMik/libki.git
etc: Start using smart pointers
This commit is contained in:
parent
1955e72bb9
commit
a2c577ce47
|
@ -19,11 +19,11 @@ namespace pclass
|
||||||
|
|
||||||
IProperty(PropertyClass &object,
|
IProperty(PropertyClass &object,
|
||||||
const std::string &name, const Type &type);
|
const std::string &name, const Type &type);
|
||||||
virtual ~IProperty() {}
|
|
||||||
|
|
||||||
IProperty(PropertyClass &object,
|
IProperty(PropertyClass &object,
|
||||||
const IProperty &that);
|
const IProperty &that);
|
||||||
|
|
||||||
|
virtual ~IProperty() {}
|
||||||
|
|
||||||
const PropertyClass &get_instance() const;
|
const PropertyClass &get_instance() const;
|
||||||
std::string get_name() const;
|
std::string get_name() const;
|
||||||
hash_t get_name_hash() const;
|
hash_t get_name_hash() const;
|
||||||
|
@ -35,7 +35,7 @@ namespace pclass
|
||||||
|
|
||||||
virtual Value get_value() const = 0;
|
virtual Value get_value() const = 0;
|
||||||
virtual const PropertyClass *get_object() const = 0;
|
virtual const PropertyClass *get_object() const = 0;
|
||||||
virtual void set_object(PropertyClass *object) = 0;
|
virtual void set_object(std::unique_ptr<PropertyClass> &object) = 0;
|
||||||
|
|
||||||
virtual void write_value_to(BitStream &stream) const = 0;
|
virtual void write_value_to(BitStream &stream) const = 0;
|
||||||
virtual void read_value_from(BitStream &stream) = 0;
|
virtual void read_value_from(BitStream &stream) = 0;
|
||||||
|
@ -60,24 +60,24 @@ namespace pclass
|
||||||
|
|
||||||
IDynamicProperty(PropertyClass &object,
|
IDynamicProperty(PropertyClass &object,
|
||||||
const std::string &name, const Type &type);
|
const std::string &name, const Type &type);
|
||||||
virtual ~IDynamicProperty() {}
|
|
||||||
|
|
||||||
IDynamicProperty(PropertyClass &object,
|
IDynamicProperty(PropertyClass &object,
|
||||||
const IDynamicProperty &that);
|
const IDynamicProperty &that);
|
||||||
|
|
||||||
|
virtual ~IDynamicProperty() {}
|
||||||
|
|
||||||
bool is_dynamic() const override;
|
bool is_dynamic() const override;
|
||||||
virtual std::size_t get_element_count() const = 0;
|
virtual std::size_t get_element_count() const = 0;
|
||||||
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;
|
||||||
const PropertyClass *get_object() const final override;
|
const PropertyClass *get_object() const final override;
|
||||||
void set_object(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 const PropertyClass *get_object(int index) const = 0;
|
virtual const PropertyClass *get_object(int index) const = 0;
|
||||||
virtual void set_object(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;
|
||||||
virtual void read_value_from(BitStream &stream, int index) = 0;
|
virtual void read_value_from(BitStream &stream, int index) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "ki/pclass/HashCalculator.h"
|
#include "ki/pclass/HashCalculator.h"
|
||||||
|
|
||||||
|
@ -84,8 +84,8 @@ namespace pclass
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<IProperty *> m_properties;
|
std::vector<IProperty *> m_properties;
|
||||||
std::map<std::string, IProperty *> m_property_name_lookup;
|
std::unordered_map<std::string, IProperty *> m_property_name_lookup;
|
||||||
std::map<hash_t, IProperty *> m_property_hash_lookup;
|
std::unordered_map<hash_t, IProperty *> m_property_hash_lookup;
|
||||||
|
|
||||||
void add_property(IProperty &prop);
|
void add_property(IProperty &prop);
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,7 +45,8 @@ namespace pclass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(StaticProperty<ValueT> &prop, PropertyClass *object)
|
static void set_object(StaticProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
// storing an object.
|
// storing an object.
|
||||||
|
@ -101,7 +102,8 @@ namespace pclass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(StaticProperty<ValueT> &prop, PropertyClass *object)
|
static void set_object(StaticProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
// storing an object.
|
// storing an object.
|
||||||
|
@ -158,7 +160,8 @@ namespace pclass
|
||||||
return dynamic_cast<const PropertyClass *>(prop.m_value);
|
return dynamic_cast<const PropertyClass *>(prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(StaticProperty<ValueT> &prop, PropertyClass *object)
|
static void set_object(StaticProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object)
|
||||||
{
|
{
|
||||||
// Ensure that object inherits the type of the property
|
// Ensure that object inherits the type of the property
|
||||||
if (object)
|
if (object)
|
||||||
|
@ -166,7 +169,7 @@ namespace pclass
|
||||||
|
|
||||||
// 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
|
||||||
// of PropertyClass, so cast the pointer up to a ValueT.
|
// of PropertyClass, so cast the pointer up to a ValueT.
|
||||||
prop.m_value = dynamic_cast<ValueT>(object);
|
prop.m_value = dynamic_cast<ValueT>(object.release());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -220,7 +223,8 @@ namespace pclass
|
||||||
return dynamic_cast<const PropertyClass *>(&prop.m_value);
|
return dynamic_cast<const PropertyClass *>(&prop.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(StaticProperty<ValueT> &prop, PropertyClass *object)
|
static void set_object(StaticProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object)
|
||||||
{
|
{
|
||||||
// Ensure that object is not nullptr
|
// Ensure that object is not nullptr
|
||||||
if (!object)
|
if (!object)
|
||||||
|
@ -231,8 +235,7 @@ namespace pclass
|
||||||
|
|
||||||
// ValueT does derive from PropertyClass, but we don't store a pointer,
|
// ValueT does derive from PropertyClass, but we don't store a pointer,
|
||||||
// so we need to copy the value in.
|
// so we need to copy the value in.
|
||||||
prop.m_value = *dynamic_cast<ValueT *>(object);
|
prop.m_value = *dynamic_cast<ValueT *>(object.get());
|
||||||
delete object;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -315,7 +318,8 @@ namespace pclass
|
||||||
return value_object_helper<ValueT>::get_object(prop);
|
return value_object_helper<ValueT>::get_object(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(StaticProperty<ValueT> &prop, PropertyClass *object)
|
static void set_object(StaticProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object)
|
||||||
{
|
{
|
||||||
value_object_helper<ValueT>::set_object(prop, object);
|
value_object_helper<ValueT>::set_object(prop, object);
|
||||||
}
|
}
|
||||||
|
@ -385,7 +389,7 @@ namespace pclass
|
||||||
return value_helper<ValueT>::get_object(*this);
|
return value_helper<ValueT>::get_object(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_object(PropertyClass *object) override
|
void set_object(std::unique_ptr<PropertyClass> &object) override
|
||||||
{
|
{
|
||||||
return value_helper<ValueT>::set_object(*this, object);
|
return value_helper<ValueT>::set_object(*this, object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include "ki/pclass/HashCalculator.h"
|
#include "ki/pclass/HashCalculator.h"
|
||||||
#include "ki/pclass/types/Type.h"
|
#include "ki/pclass/types/Type.h"
|
||||||
#include "ki/pclass/types/PrimitiveType.h"
|
#include "ki/pclass/types/PrimitiveType.h"
|
||||||
|
@ -17,8 +17,7 @@ namespace pclass
|
||||||
class TypeSystem
|
class TypeSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TypeSystem(HashCalculator *hash_calculator);
|
explicit TypeSystem(std::unique_ptr<HashCalculator> &hash_calculator);
|
||||||
~TypeSystem();
|
|
||||||
|
|
||||||
const HashCalculator &get_hash_calculator() const;
|
const HashCalculator &get_hash_calculator() const;
|
||||||
|
|
||||||
|
@ -32,7 +31,9 @@ namespace pclass
|
||||||
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
||||||
{
|
{
|
||||||
auto *type = new PrimitiveType<ValueT>(name, *this);
|
auto *type = new PrimitiveType<ValueT>(name, *this);
|
||||||
define_type(type);
|
define_type(std::unique_ptr<Type>(
|
||||||
|
dynamic_cast<Type *>(type)
|
||||||
|
));
|
||||||
return *type;
|
return *type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,25 +54,30 @@ namespace pclass
|
||||||
CppEnumType<EnumT> &define_enum(const std::string &name)
|
CppEnumType<EnumT> &define_enum(const std::string &name)
|
||||||
{
|
{
|
||||||
auto *type = new CppEnumType<EnumT>(name, *this);
|
auto *type = new CppEnumType<EnumT>(name, *this);
|
||||||
define_type(type);
|
define_type(std::unique_ptr<Type>(
|
||||||
|
dynamic_cast<Type *>(type)
|
||||||
|
));
|
||||||
return *type;
|
return *type;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ClassT>
|
template <typename ClassT>
|
||||||
ClassT *instantiate(const std::string &name) const
|
std::unique_ptr<ClassT> instantiate(const std::string &name) const
|
||||||
{
|
{
|
||||||
const auto &type = get_type(name);
|
const auto &type = get_type(name);
|
||||||
return dynamic_cast<ClassT *>(type.instantiate());
|
auto object = type.instantiate();
|
||||||
|
return std::unique_ptr<ClassT>(
|
||||||
|
dynamic_cast<ClassT *>(object.release())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void define_type(Type *type);
|
void define_type(std::unique_ptr<Type> type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TypeList m_types;
|
std::vector<std::unique_ptr<Type>> m_types;
|
||||||
TypeNameMap m_type_name_lookup;
|
std::unordered_map<std::string, Type *> m_type_name_lookup;
|
||||||
TypeHashMap m_type_hash_lookup;
|
std::unordered_map<hash_t, Type *> m_type_hash_lookup;
|
||||||
HashCalculator *m_hash_calculator;
|
std::unique_ptr<HashCalculator> m_hash_calculator;
|
||||||
|
|
||||||
template <class ClassT>
|
template <class ClassT>
|
||||||
ClassType<ClassT> &define_class(
|
ClassType<ClassT> &define_class(
|
||||||
|
@ -83,7 +89,9 @@ namespace pclass
|
||||||
base_class = &get_type("class PropertyClass");
|
base_class = &get_type("class PropertyClass");
|
||||||
|
|
||||||
auto *type = new ClassType<ClassT>(name, base_class, *this);
|
auto *type = new ClassType<ClassT>(name, base_class, *this);
|
||||||
define_type(type);
|
define_type(std::unique_ptr<Type>(
|
||||||
|
dynamic_cast<Type *>(type)
|
||||||
|
));
|
||||||
return *type;
|
return *type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace pclass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop, PropertyClass *object, const int index)
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
// storing an object.
|
// storing an object.
|
||||||
|
@ -90,7 +91,8 @@ namespace pclass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop, PropertyClass *object, const int index)
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
// ValueT does not derive from PropertyClass, and so, this property is not
|
// ValueT does not derive from PropertyClass, and so, this property is not
|
||||||
// storing an object.
|
// storing an object.
|
||||||
|
@ -135,7 +137,8 @@ namespace pclass
|
||||||
return dynamic_cast<PropertyClass *>(prop.at(index));
|
return dynamic_cast<PropertyClass *>(prop.at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop, PropertyClass *object, const int index)
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
|
@ -147,7 +150,7 @@ namespace pclass
|
||||||
|
|
||||||
// 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
|
||||||
// of PropertyClass, so cast the pointer up to a ValueT.
|
// of PropertyClass, so cast the pointer up to a ValueT.
|
||||||
prop.at(index) = dynamic_cast<ValueT>(object);
|
prop.at(index) = dynamic_cast<ValueT>(object.release());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,7 +196,8 @@ namespace pclass
|
||||||
return dynamic_cast<const PropertyClass *>(&prop.at(index));
|
return dynamic_cast<const PropertyClass *>(&prop.at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop, PropertyClass *object, const int index)
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
|
@ -208,8 +212,7 @@ namespace pclass
|
||||||
|
|
||||||
// ValueT does derive from PropertyClass, but we don't store a pointer,
|
// ValueT does derive from PropertyClass, but we don't store a pointer,
|
||||||
// so we need to copy the value in.
|
// so we need to copy the value in.
|
||||||
prop.at(index) = *dynamic_cast<ValueT *>(object);
|
prop.at(index) = *dynamic_cast<ValueT *>(object.get());
|
||||||
delete object;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -291,22 +294,26 @@ 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)
|
static const PropertyClass *get_object(const VectorProperty<ValueT> &prop,
|
||||||
|
const int index)
|
||||||
{
|
{
|
||||||
return vector_value_object_helper<ValueT>::get_object(prop, index);
|
return vector_value_object_helper<ValueT>::get_object(prop, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_object(VectorProperty<ValueT> &prop, PropertyClass *object, const int index)
|
static void set_object(VectorProperty<ValueT> &prop,
|
||||||
|
std::unique_ptr<PropertyClass> &object, const int index)
|
||||||
{
|
{
|
||||||
vector_value_object_helper<ValueT>::set_object(prop, object, index);
|
vector_value_object_helper<ValueT>::set_object(prop, object, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_value_to(const VectorProperty<ValueT> &prop, BitStream &stream, const int index)
|
static void write_value_to(const VectorProperty<ValueT> &prop,
|
||||||
|
BitStream &stream, const int index)
|
||||||
{
|
{
|
||||||
vector_value_rw_helper<ValueT>::write_value_to(prop, stream, index);
|
vector_value_rw_helper<ValueT>::write_value_to(prop, stream, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_value_from(VectorProperty<ValueT> &prop, BitStream &stream, const int index)
|
static void read_value_from(VectorProperty<ValueT> &prop,
|
||||||
|
BitStream &stream, const int index)
|
||||||
{
|
{
|
||||||
vector_value_rw_helper<ValueT>::read_value_from(prop, stream, index);
|
vector_value_rw_helper<ValueT>::read_value_from(prop, stream, index);
|
||||||
}
|
}
|
||||||
|
@ -365,7 +372,7 @@ namespace pclass
|
||||||
return vector_value_helper<ValueT>::get_object(*this, index);
|
return vector_value_helper<ValueT>::get_object(*this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_object(PropertyClass *object, int index) override
|
void set_object(std::unique_ptr<PropertyClass> &object, int index) override
|
||||||
{
|
{
|
||||||
return vector_value_helper<ValueT>::set_object(*this, object, index);
|
return vector_value_helper<ValueT>::set_object(*this, object, index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "ki/pclass/Property.h"
|
||||||
#include "ki/pclass/types/Type.h"
|
#include "ki/pclass/types/Type.h"
|
||||||
#include "ki/pclass/PropertyClass.h"
|
#include "ki/pclass/PropertyClass.h"
|
||||||
#include "ki/pclass/Property.h"
|
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
|
@ -43,9 +44,12 @@ namespace pclass
|
||||||
: IClassType(name, base_class, type_system)
|
: IClassType(name, base_class, type_system)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
PropertyClass *instantiate() const override
|
std::unique_ptr<PropertyClass> instantiate() const override
|
||||||
{
|
{
|
||||||
return new ClassT(*this, get_type_system());
|
auto *instance = new ClassT(*this, get_type_system());
|
||||||
|
return std::unique_ptr<PropertyClass>(
|
||||||
|
dynamic_cast<PropertyClass *>(instance)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_to(BitStream &stream, Value value) const override
|
void write_to(BitStream &stream, Value value) const override
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <unordered_map>
|
||||||
#include "ki/pclass/types/Type.h"
|
#include "ki/pclass/types/Type.h"
|
||||||
#include "ki/pclass/types/PrimitiveType.h"
|
#include "ki/pclass/types/PrimitiveType.h"
|
||||||
|
|
||||||
|
@ -47,8 +48,8 @@ namespace pclass
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Element *> m_elements;
|
std::vector<Element *> m_elements;
|
||||||
std::map<std::string, Element *> m_element_name_lookup;
|
std::unordered_map<std::string, Element *> m_element_name_lookup;
|
||||||
std::map<enum_value_t, Element *> m_element_value_lookup;
|
std::unordered_map<enum_value_t, Element *> m_element_value_lookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,9 +31,9 @@ namespace detail
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* An unsigned integer type with the same size as the floating point type
|
* An unsigned integer type with the same size as the floating point type
|
||||||
* ValueT.
|
* ValueT.
|
||||||
*/
|
*/
|
||||||
using uint_type = typename bits<bitsizeof<ValueT>::value>::uint_type;
|
using uint_type = typename bits<bitsizeof<ValueT>::value>::uint_type;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
#include "ki/pclass/HashCalculator.h"
|
#include "ki/pclass/HashCalculator.h"
|
||||||
#include "ki/pclass/Value.h"
|
#include "ki/pclass/Value.h"
|
||||||
#include "ki/util/BitStream.h"
|
#include "ki/util/BitStream.h"
|
||||||
|
@ -47,7 +47,7 @@ namespace pclass
|
||||||
kind get_kind() const;
|
kind get_kind() const;
|
||||||
const TypeSystem &get_type_system() const;
|
const TypeSystem &get_type_system() const;
|
||||||
|
|
||||||
virtual PropertyClass *instantiate() const;
|
virtual std::unique_ptr<PropertyClass> instantiate() const;
|
||||||
virtual void write_to(BitStream &stream, Value value) const;
|
virtual void write_to(BitStream &stream, Value value) const;
|
||||||
virtual Value read_from(BitStream &stream) const;
|
virtual Value read_from(BitStream &stream) const;
|
||||||
|
|
||||||
|
@ -60,10 +60,6 @@ namespace pclass
|
||||||
const TypeSystem &m_type_system;
|
const TypeSystem &m_type_system;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Type *> TypeList;
|
|
||||||
typedef std::map<std::string, Type *> TypeNameMap;
|
|
||||||
typedef std::map<hash_t, Type *> TypeHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param[in] expected The Type that is expected to match with the actual Type.
|
* @param[in] expected The Type that is expected to match with the actual Type.
|
||||||
* @param[in] actual The Type that is being checked for a match with the expected Type.
|
* @param[in] actual The Type that is being checked for a match with the expected Type.
|
||||||
|
|
|
@ -45,16 +45,58 @@ namespace serialization
|
||||||
bool is_file, flags flags);
|
bool is_file, flags flags);
|
||||||
virtual ~SerializerBinary() {}
|
virtual ~SerializerBinary() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param object
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
void save(const pclass::PropertyClass *object, BitStream &stream);
|
void save(const pclass::PropertyClass *object, BitStream &stream);
|
||||||
void load(pclass::PropertyClass *&dest, BitStream &stream, std::size_t size);
|
|
||||||
|
/**
|
||||||
|
* @param dest
|
||||||
|
* @param stream
|
||||||
|
* @param size
|
||||||
|
*/
|
||||||
|
void load(std::unique_ptr<pclass::PropertyClass> &dest,
|
||||||
|
BitStream &stream, std::size_t size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* @param object
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
virtual void presave_object(const pclass::PropertyClass *object, BitStream &stream) const;
|
virtual void presave_object(const pclass::PropertyClass *object, BitStream &stream) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param object
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
void save_object(const pclass::PropertyClass *object, BitStream &stream) const;
|
void save_object(const pclass::PropertyClass *object, BitStream &stream) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prop
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
void save_property(const pclass::IProperty &prop, BitStream &stream) const;
|
void save_property(const pclass::IProperty &prop, BitStream &stream) const;
|
||||||
|
|
||||||
virtual void preload_object(pclass::PropertyClass *&dest, BitStream &stream) const;
|
/**
|
||||||
void load_object(pclass::PropertyClass *&dest, BitStream &stream) const;
|
* Read an object header, and instantiate the necessary PropertyClass.
|
||||||
|
* @param dest
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
|
virtual void preload_object(
|
||||||
|
std::unique_ptr<pclass::PropertyClass> &dest, BitStream &stream) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dest
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
|
void load_object(
|
||||||
|
std::unique_ptr<pclass::PropertyClass> &dest, BitStream &stream) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prop
|
||||||
|
* @param stream
|
||||||
|
*/
|
||||||
void load_property(pclass::IProperty &prop, BitStream &stream) const;
|
void load_property(pclass::IProperty &prop, BitStream &stream) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace ki
|
||||||
void set_bit(int bit);
|
void set_bit(int bit);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~IBitBuffer() {};
|
virtual ~IBitBuffer() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns
|
* @returns
|
||||||
|
@ -77,7 +77,9 @@ namespace ki
|
||||||
* @param[in] bitsize The size of the segment in bits.
|
* @param[in] bitsize The size of the segment in bits.
|
||||||
* @returns A new segment of this buffer.
|
* @returns A new segment of this buffer.
|
||||||
*/
|
*/
|
||||||
virtual BitBufferSegment *segment(buffer_pos from, std::size_t bitsize);
|
virtual std::unique_ptr<BitBufferSegment> segment(
|
||||||
|
buffer_pos from, std::size_t bitsize
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a value from the buffer.
|
* Reads a value from the buffer.
|
||||||
|
@ -214,8 +216,10 @@ namespace ki
|
||||||
|
|
||||||
std::size_t size() const override;
|
std::size_t size() const override;
|
||||||
void resize(std::size_t new_size) override;
|
void resize(std::size_t new_size) override;
|
||||||
uint8_t* data() const override;
|
uint8_t *data() const override;
|
||||||
BitBufferSegment *segment(buffer_pos from, std::size_t bitsize) override;
|
std::unique_ptr<BitBufferSegment> segment(
|
||||||
|
buffer_pos from, std::size_t bitsize
|
||||||
|
) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc IBitBuffer::read<ValueT>(buffer_pos, uint8_t)
|
* @copydoc IBitBuffer::read<ValueT>(buffer_pos, uint8_t)
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#if __cplusplus <= 201103L
|
||||||
|
namespace ki
|
||||||
|
{
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
std::unique_ptr<T> make_unique(Args&&... args)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<T>(
|
||||||
|
new T(std::forward<Args>(args)...)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -98,7 +98,7 @@ namespace pclass
|
||||||
throw runtime_error("Called get_object() on a dynamic property. Use get_object(index) instead.");
|
throw runtime_error("Called get_object() on a dynamic property. Use get_object(index) instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDynamicProperty::set_object(PropertyClass *object)
|
void IDynamicProperty::set_object(std::unique_ptr<PropertyClass> &object)
|
||||||
{
|
{
|
||||||
// The caller must specify an index
|
// The caller must specify an index
|
||||||
throw runtime_error("Called set_object() on a dynamic property. Use set_object(index) instead.");
|
throw runtime_error("Called set_object() on a dynamic property. Use set_object(index) instead.");
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace pclass
|
||||||
throw runtime_error(oss.str());
|
throw runtime_error(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyClass *Type::instantiate() const
|
std::unique_ptr<PropertyClass> Type::instantiate() const
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Type '" << m_name << "' does not implement Type::instantiate.";
|
oss << "Type '" << m_name << "' does not implement Type::instantiate.";
|
||||||
|
|
|
@ -32,9 +32,9 @@ namespace pclass
|
||||||
template <>
|
template <>
|
||||||
void define_bit_integer_primitive<0>(TypeSystem &type_system) {}
|
void define_bit_integer_primitive<0>(TypeSystem &type_system) {}
|
||||||
|
|
||||||
TypeSystem::TypeSystem(HashCalculator *hash_calculator)
|
TypeSystem::TypeSystem(std::unique_ptr<HashCalculator> &hash_calculator)
|
||||||
{
|
{
|
||||||
m_hash_calculator = hash_calculator;
|
m_hash_calculator = std::move(hash_calculator);
|
||||||
|
|
||||||
// Pre-define C++ primitive types
|
// Pre-define C++ primitive types
|
||||||
// Define integer types
|
// Define integer types
|
||||||
|
@ -74,20 +74,6 @@ namespace pclass
|
||||||
define_class<PropertyClass>("class PropertyClass");
|
define_class<PropertyClass>("class PropertyClass");
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSystem::~TypeSystem()
|
|
||||||
{
|
|
||||||
// Delete all type declarations
|
|
||||||
for (auto it = m_types.begin(); it != m_types.end(); ++it)
|
|
||||||
delete *it;
|
|
||||||
|
|
||||||
// Clear lookups
|
|
||||||
m_type_name_lookup.clear();
|
|
||||||
m_type_hash_lookup.clear();
|
|
||||||
|
|
||||||
// Delete the hash calculator
|
|
||||||
delete m_hash_calculator;
|
|
||||||
}
|
|
||||||
|
|
||||||
const HashCalculator &TypeSystem::get_hash_calculator() const
|
const HashCalculator &TypeSystem::get_hash_calculator() const
|
||||||
{
|
{
|
||||||
// Make sure the hash calculator isn't null
|
// Make sure the hash calculator isn't null
|
||||||
|
@ -132,14 +118,11 @@ namespace pclass
|
||||||
return *it->second;
|
return *it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeSystem::define_type(Type *type)
|
void TypeSystem::define_type(std::unique_ptr<Type> type)
|
||||||
{
|
{
|
||||||
// Does a type with this name already exist?
|
// Does a type with this name already exist?
|
||||||
if (m_type_name_lookup.find(type->get_name()) != m_type_name_lookup.end())
|
if (m_type_name_lookup.find(type->get_name()) != m_type_name_lookup.end())
|
||||||
{
|
{
|
||||||
// This pointer will become lost since it isn't being added to the lookups.
|
|
||||||
delete type;
|
|
||||||
|
|
||||||
// Throw an error
|
// Throw an error
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Type '" << type->get_name() << "' is already defined.";
|
oss << "Type '" << type->get_name() << "' is already defined.";
|
||||||
|
@ -149,9 +132,6 @@ namespace pclass
|
||||||
// Does a type with this hash already exist?
|
// Does a type with this hash already exist?
|
||||||
if (m_type_name_lookup.find(type->get_name()) != m_type_name_lookup.end())
|
if (m_type_name_lookup.find(type->get_name()) != m_type_name_lookup.end())
|
||||||
{
|
{
|
||||||
// This pointer will become lost since it isn't being added to the lookups.
|
|
||||||
delete type;
|
|
||||||
|
|
||||||
// Throw an error
|
// Throw an error
|
||||||
auto &other_type = get_type(type->get_hash());
|
auto &other_type = get_type(type->get_hash());
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
@ -161,9 +141,9 @@ namespace pclass
|
||||||
}
|
}
|
||||||
|
|
||||||
// This type is safe to add to our lookups
|
// This type is safe to add to our lookups
|
||||||
m_types.push_back(type);
|
m_type_name_lookup[type->get_name()] = type.get();
|
||||||
m_type_name_lookup[type->get_name()] = type;
|
m_type_hash_lookup[type->get_hash()] = type.get();
|
||||||
m_type_hash_lookup[type->get_hash()] = type;
|
m_types.push_back(std::move(type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "ki/serialization/SerializerBinary.h"
|
#include "ki/serialization/SerializerBinary.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include "ki/util/unique.h"
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
|
@ -235,11 +236,15 @@ namespace serialization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerializerBinary::load(pclass::PropertyClass *&dest,
|
void SerializerBinary::load(
|
||||||
|
std::unique_ptr<pclass::PropertyClass> &dest,
|
||||||
BitStream &stream, const std::size_t size)
|
BitStream &stream, const std::size_t size)
|
||||||
{
|
{
|
||||||
// Create a new stream that reads a segment of the stream given to us
|
// Create a new stream that reads a segment of the stream given to us
|
||||||
IBitBuffer *buffer = stream.buffer().segment(stream.tell(), size * 8);
|
auto segment_buffer = stream.buffer().segment(stream.tell(), size * 8);
|
||||||
|
auto buffer = std::unique_ptr<IBitBuffer>(
|
||||||
|
dynamic_cast<IBitBuffer *>(segment_buffer.release())
|
||||||
|
);
|
||||||
auto segment_stream = BitStream(*buffer);
|
auto segment_stream = BitStream(*buffer);
|
||||||
stream.seek(stream.tell() + size * 8, false);
|
stream.seek(stream.tell() + size * 8, false);
|
||||||
|
|
||||||
|
@ -267,21 +272,23 @@ namespace serialization
|
||||||
segment_stream.read_copy(compressed.data(), data_available_bytes * 8);
|
segment_stream.read_copy(compressed.data(), data_available_bytes * 8);
|
||||||
|
|
||||||
// Uncompress the compressed buffer
|
// Uncompress the compressed buffer
|
||||||
auto *uncompressed = new BitBuffer(uncompressed_size);
|
auto uncompressed = ki::make_unique<BitBuffer>(uncompressed_size);
|
||||||
uLong dest_len = uncompressed_size;
|
uLong dest_len = uncompressed_size;
|
||||||
uncompress(uncompressed->data(), &dest_len,
|
uncompress(uncompressed->data(), &dest_len,
|
||||||
compressed.data(), data_available_bytes);
|
compressed.data(), data_available_bytes);
|
||||||
|
|
||||||
// Delete the old buffer and use the new uncompressed buffer
|
// Delete the old buffer and use the new uncompressed buffer
|
||||||
delete buffer;
|
buffer = std::unique_ptr<IBitBuffer>(
|
||||||
buffer = uncompressed;
|
dynamic_cast<IBitBuffer *>(uncompressed.release())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Use a segment of the current buffer as the new buffer
|
// Use a segment of the current buffer as the new buffer
|
||||||
auto *segment_buffer = buffer->segment(segment_stream.tell(), data_available_bytes);
|
segment_buffer = buffer->segment(segment_stream.tell(), data_available_bytes);
|
||||||
delete buffer;
|
buffer = std::unique_ptr<IBitBuffer>(
|
||||||
buffer = segment_buffer;
|
dynamic_cast<IBitBuffer *>(segment_buffer.release())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new stream to read from the new buffer
|
// Create a new stream to read from the new buffer
|
||||||
|
@ -289,21 +296,11 @@ namespace serialization
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the root object
|
// Load the root object
|
||||||
try
|
load_object(dest, segment_stream);
|
||||||
{
|
|
||||||
load_object(dest, segment_stream);
|
|
||||||
}
|
|
||||||
catch (runtime_error &e)
|
|
||||||
{
|
|
||||||
delete buffer;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
delete buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerializerBinary::preload_object(pclass::PropertyClass *&dest, BitStream &stream) const
|
void SerializerBinary::preload_object(
|
||||||
|
std::unique_ptr<pclass::PropertyClass> &dest, BitStream &stream) const
|
||||||
{
|
{
|
||||||
const auto type_hash = stream.read<pclass::hash_t>();
|
const auto type_hash = stream.read<pclass::hash_t>();
|
||||||
if (type_hash != 0)
|
if (type_hash != 0)
|
||||||
|
@ -317,7 +314,8 @@ namespace serialization
|
||||||
dest = nullptr;
|
dest = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerializerBinary::load_object(pclass::PropertyClass *&dest, BitStream &stream) const
|
void SerializerBinary::load_object(
|
||||||
|
std::unique_ptr<pclass::PropertyClass> &dest, BitStream &stream) const
|
||||||
{
|
{
|
||||||
// Read the object header
|
// Read the object header
|
||||||
preload_object(dest, stream);
|
preload_object(dest, stream);
|
||||||
|
@ -333,11 +331,11 @@ namespace serialization
|
||||||
// ensure that data is only read from inside this region.
|
// ensure that data is only read from inside this region.
|
||||||
const auto object_size =
|
const auto object_size =
|
||||||
stream.read<uint32_t>() - bitsizeof<uint32_t>::value;
|
stream.read<uint32_t>() - bitsizeof<uint32_t>::value;
|
||||||
auto *object_buffer = stream.buffer().segment(
|
auto object_buffer = stream.buffer().segment(
|
||||||
stream.tell(), object_size
|
stream.tell(), object_size
|
||||||
);
|
);
|
||||||
stream.seek(stream.tell() + object_size, false);
|
|
||||||
auto object_stream = BitStream(*object_buffer);
|
auto object_stream = BitStream(*object_buffer);
|
||||||
|
stream.seek(stream.tell() + object_size, false);
|
||||||
|
|
||||||
// Instead of loading properties sequentially, the file format specifies
|
// Instead of loading properties sequentially, the file format specifies
|
||||||
// the hash of a property before writing its value, so we just need to
|
// the hash of a property before writing its value, so we just need to
|
||||||
|
@ -349,7 +347,7 @@ namespace serialization
|
||||||
// ensure that data is only read from inside this region.
|
// ensure that data is only read from inside this region.
|
||||||
const auto property_size =
|
const auto property_size =
|
||||||
object_stream.read<uint32_t>() - bitsizeof<uint32_t>::value;
|
object_stream.read<uint32_t>() - bitsizeof<uint32_t>::value;
|
||||||
auto *property_buffer = object_buffer->segment(
|
const auto property_buffer = object_buffer->segment(
|
||||||
object_stream.tell(), property_size
|
object_stream.tell(), property_size
|
||||||
);
|
);
|
||||||
auto property_stream = BitStream(*property_buffer);
|
auto property_stream = BitStream(*property_buffer);
|
||||||
|
@ -360,9 +358,7 @@ namespace serialization
|
||||||
const auto property_hash = property_stream.read<uint32_t>();
|
const auto property_hash = property_stream.read<uint32_t>();
|
||||||
auto &prop = properties.get_property(property_hash);
|
auto &prop = properties.get_property(property_hash);
|
||||||
load_property(prop, property_stream);
|
load_property(prop, property_stream);
|
||||||
delete property_buffer;
|
|
||||||
}
|
}
|
||||||
delete object_buffer;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -402,7 +398,7 @@ namespace serialization
|
||||||
if (property_type.get_kind() == pclass::Type::kind::CLASS)
|
if (property_type.get_kind() == pclass::Type::kind::CLASS)
|
||||||
{
|
{
|
||||||
// Read the object as a nested object
|
// Read the object as a nested object
|
||||||
pclass::PropertyClass *object = nullptr;
|
std::unique_ptr<pclass::PropertyClass> object = nullptr;
|
||||||
load_object(object, stream);
|
load_object(object, stream);
|
||||||
dynamic_property.set_object(object, i);
|
dynamic_property.set_object(object, i);
|
||||||
}
|
}
|
||||||
|
@ -421,7 +417,7 @@ namespace serialization
|
||||||
if (property_type.get_kind() == pclass::Type::kind::CLASS)
|
if (property_type.get_kind() == pclass::Type::kind::CLASS)
|
||||||
{
|
{
|
||||||
// Read the object as a nested object
|
// Read the object as a nested object
|
||||||
pclass::PropertyClass *object = nullptr;
|
std::unique_ptr<pclass::PropertyClass> object = nullptr;
|
||||||
load_object(object, stream);
|
load_object(object, stream);
|
||||||
prop.set_object(object);
|
prop.set_object(object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include "ki/util/unique.h"
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
|
@ -141,10 +142,10 @@ namespace ki
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitBufferSegment *IBitBuffer::segment(
|
std::unique_ptr<BitBufferSegment> IBitBuffer::segment(
|
||||||
const buffer_pos from, const std::size_t bitsize)
|
const buffer_pos from, const std::size_t bitsize)
|
||||||
{
|
{
|
||||||
return new BitBufferSegment(*this, from, bitsize);
|
return ki::make_unique<BitBufferSegment>(*this, from, bitsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IBitBuffer::write_copy(uint8_t *src,
|
void IBitBuffer::write_copy(uint8_t *src,
|
||||||
|
@ -329,10 +330,12 @@ namespace ki
|
||||||
return &m_buffer->data()[m_from.get_byte()];
|
return &m_buffer->data()[m_from.get_byte()];
|
||||||
}
|
}
|
||||||
|
|
||||||
BitBufferSegment *BitBufferSegment::segment(
|
std::unique_ptr<BitBufferSegment> BitBufferSegment::segment(
|
||||||
const buffer_pos from, const std::size_t bitsize)
|
const buffer_pos from, const std::size_t bitsize)
|
||||||
{
|
{
|
||||||
return new BitBufferSegment(*m_buffer, m_from + from, bitsize);
|
return ki::make_unique<BitBufferSegment>(
|
||||||
|
*m_buffer, m_from + from, bitsize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t BitBufferSegment::read(
|
uint64_t BitBufferSegment::read(
|
||||||
|
|
|
@ -137,21 +137,19 @@ TEST_CASE("BitBuffer Functionality", "[bit-stream]")
|
||||||
|
|
||||||
SECTION("Create valid segment")
|
SECTION("Create valid segment")
|
||||||
{
|
{
|
||||||
auto *segment = bit_buffer.segment(
|
auto segment = bit_buffer.segment(
|
||||||
BitBuffer::buffer_pos(0, 0), 8
|
BitBuffer::buffer_pos(0, 0), 8
|
||||||
);
|
);
|
||||||
REQUIRE(segment->size() == 1);
|
REQUIRE(segment->size() == 1);
|
||||||
delete segment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Create invalid segment (invalid position)")
|
SECTION("Create invalid segment (invalid position)")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto *segment = bit_buffer.segment(
|
auto segment = bit_buffer.segment(
|
||||||
BitBuffer::buffer_pos(1, 0), 8
|
BitBuffer::buffer_pos(1, 0), 8
|
||||||
);
|
);
|
||||||
delete segment;
|
|
||||||
FAIL();
|
FAIL();
|
||||||
}
|
}
|
||||||
catch (runtime_error &e)
|
catch (runtime_error &e)
|
||||||
|
@ -164,10 +162,9 @@ TEST_CASE("BitBuffer Functionality", "[bit-stream]")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto *segment = bit_buffer.segment(
|
auto segment = bit_buffer.segment(
|
||||||
BitBuffer::buffer_pos(0, 0), 16
|
BitBuffer::buffer_pos(0, 0), 16
|
||||||
);
|
);
|
||||||
delete segment;
|
|
||||||
FAIL();
|
FAIL();
|
||||||
}
|
}
|
||||||
catch (runtime_error &e)
|
catch (runtime_error &e)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <ki/pclass/StaticProperty.h>
|
#include <ki/pclass/StaticProperty.h>
|
||||||
#include <ki/pclass/VectorProperty.h>
|
#include <ki/pclass/VectorProperty.h>
|
||||||
#include <ki/serialization/SerializerBinary.h>
|
#include <ki/serialization/SerializerBinary.h>
|
||||||
|
#include "ki/util/unique.h"
|
||||||
|
|
||||||
using namespace ki;
|
using namespace ki;
|
||||||
|
|
||||||
|
@ -256,8 +257,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup a global TypeSystem instance
|
// Setup a global TypeSystem instance
|
||||||
auto *g_hash_calculator = new pclass::WizardHashCalculator();
|
std::unique_ptr<pclass::HashCalculator> g_hash_calculator
|
||||||
pclass::TypeSystem *g_type_system = new pclass::TypeSystem(g_hash_calculator);
|
= ki::make_unique<pclass::WizardHashCalculator>();
|
||||||
|
auto g_type_system = ki::make_unique<pclass::TypeSystem>(g_hash_calculator);
|
||||||
bool g_types_defined = false;
|
bool g_types_defined = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -337,13 +339,13 @@ void configure_test_object(TestObject &object)
|
||||||
|
|
||||||
// Configure nested objects
|
// Configure nested objects
|
||||||
object.value_object.get().extra_value = EXPECTED_value_object_extra_value;
|
object.value_object.get().extra_value = EXPECTED_value_object_extra_value;
|
||||||
object.not_null_object = g_type_system->instantiate<NestedTestObject>("class NestedTestObject");
|
object.not_null_object = g_type_system->instantiate<NestedTestObject>("class NestedTestObject").release();
|
||||||
object.null_object = nullptr;
|
object.null_object = nullptr;
|
||||||
object.objects.push_back(
|
object.objects.push_back(
|
||||||
g_type_system->instantiate<NestedTestObjectA>("class NestedTestObjectA")
|
g_type_system->instantiate<NestedTestObjectA>("class NestedTestObjectA").release()
|
||||||
);
|
);
|
||||||
object.objects.push_back(
|
object.objects.push_back(
|
||||||
g_type_system->instantiate<NestedTestObjectB>("class NestedTestObjectB")
|
g_type_system->instantiate<NestedTestObjectB>("class NestedTestObjectB").release()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +397,7 @@ void validate_test_object(TestObject &object)
|
||||||
* Conduct save/load tests with a SerializerBinary instance.
|
* Conduct save/load tests with a SerializerBinary instance.
|
||||||
*/
|
*/
|
||||||
void test_serializer(
|
void test_serializer(
|
||||||
TestObject *&test_object,
|
std::unique_ptr<TestObject> &test_object,
|
||||||
serialization::SerializerBinary &serializer,
|
serialization::SerializerBinary &serializer,
|
||||||
const std::string &file_suffix)
|
const std::string &file_suffix)
|
||||||
{
|
{
|
||||||
|
@ -425,12 +427,11 @@ void test_serializer(
|
||||||
// Create a test object, configure it, and write it to our stream
|
// Create a test object, configure it, and write it to our stream
|
||||||
test_object = g_type_system->instantiate<TestObject>("class TestObject");
|
test_object = g_type_system->instantiate<TestObject>("class TestObject");
|
||||||
configure_test_object(*test_object);
|
configure_test_object(*test_object);
|
||||||
serializer.save(test_object, stream);
|
serializer.save(test_object.get(), stream);
|
||||||
const auto end_pos = stream.tell();
|
const auto end_pos = stream.tell();
|
||||||
|
|
||||||
// Delete the test object here so that it is not
|
// Delete the test object here so that it is not
|
||||||
// unnecessarily validated by the caller
|
// unnecessarily validated by the caller
|
||||||
delete test_object;
|
|
||||||
test_object = nullptr;
|
test_object = nullptr;
|
||||||
|
|
||||||
// Validate the contents of the stream
|
// Validate the contents of the stream
|
||||||
|
@ -452,12 +453,14 @@ void test_serializer(
|
||||||
stream.seek(start_pos);
|
stream.seek(start_pos);
|
||||||
|
|
||||||
// Load an object from the bit stream's contents
|
// Load an object from the bit stream's contents
|
||||||
pclass::PropertyClass *object = nullptr;
|
std::unique_ptr<pclass::PropertyClass> object = nullptr;
|
||||||
serializer.load(object, stream, sample_size);
|
serializer.load(object, stream, sample_size);
|
||||||
|
|
||||||
// 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 = dynamic_cast<TestObject *>(object);
|
test_object = std::unique_ptr<TestObject>(
|
||||||
|
dynamic_cast<TestObject *>(object.release())
|
||||||
|
);
|
||||||
REQUIRE(test_object != nullptr);
|
REQUIRE(test_object != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +470,7 @@ void test_serializer(
|
||||||
|
|
||||||
TEST_CASE("Serialization tests", "[serialization]")
|
TEST_CASE("Serialization tests", "[serialization]")
|
||||||
{
|
{
|
||||||
TestObject *test_object = nullptr;
|
std::unique_ptr<TestObject> test_object = nullptr;
|
||||||
define_types();
|
define_types();
|
||||||
|
|
||||||
SECTION("SerializerBinary")
|
SECTION("SerializerBinary")
|
||||||
|
@ -475,7 +478,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
||||||
SECTION("Regular format without compression")
|
SECTION("Regular format without compression")
|
||||||
{
|
{
|
||||||
serialization::SerializerBinary serializer(
|
serialization::SerializerBinary serializer(
|
||||||
*g_type_system, false,
|
*g_type_system.get(), false,
|
||||||
serialization::SerializerBinary::flags::NONE
|
serialization::SerializerBinary::flags::NONE
|
||||||
);
|
);
|
||||||
test_serializer(test_object, serializer, "_regular");
|
test_serializer(test_object, serializer, "_regular");
|
||||||
|
@ -483,7 +486,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
||||||
SECTION("File format without compression")
|
SECTION("File format without compression")
|
||||||
{
|
{
|
||||||
serialization::SerializerBinary serializer(
|
serialization::SerializerBinary serializer(
|
||||||
*g_type_system, true,
|
*g_type_system.get(), true,
|
||||||
serialization::SerializerBinary::flags::WRITE_SERIALIZER_FLAGS
|
serialization::SerializerBinary::flags::WRITE_SERIALIZER_FLAGS
|
||||||
);
|
);
|
||||||
test_serializer(test_object, serializer, "_file");
|
test_serializer(test_object, serializer, "_file");
|
||||||
|
@ -491,7 +494,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
||||||
SECTION("Regular format with compression")
|
SECTION("Regular format with compression")
|
||||||
{
|
{
|
||||||
serialization::SerializerBinary serializer(
|
serialization::SerializerBinary serializer(
|
||||||
*g_type_system, false,
|
*g_type_system.get(), false,
|
||||||
serialization::SerializerBinary::flags::COMPRESSED
|
serialization::SerializerBinary::flags::COMPRESSED
|
||||||
);
|
);
|
||||||
test_serializer(test_object, serializer, "_regular_compressed");
|
test_serializer(test_object, serializer, "_regular_compressed");
|
||||||
|
@ -499,7 +502,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
||||||
SECTION("File format with compression")
|
SECTION("File format with compression")
|
||||||
{
|
{
|
||||||
serialization::SerializerBinary serializer(
|
serialization::SerializerBinary serializer(
|
||||||
*g_type_system, true,
|
*g_type_system.get(), true,
|
||||||
serialization::SerializerBinary::flags::WRITE_SERIALIZER_FLAGS |
|
serialization::SerializerBinary::flags::WRITE_SERIALIZER_FLAGS |
|
||||||
serialization::SerializerBinary::flags::COMPRESSED
|
serialization::SerializerBinary::flags::COMPRESSED
|
||||||
);
|
);
|
||||||
|
@ -512,7 +515,6 @@ TEST_CASE("Serialization tests", "[serialization]")
|
||||||
if (test_object)
|
if (test_object)
|
||||||
{
|
{
|
||||||
validate_test_object(*test_object);
|
validate_test_object(*test_object);
|
||||||
delete test_object;
|
|
||||||
test_object = nullptr;
|
test_object = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue