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,
|
||||
const std::string &name, const Type &type);
|
||||
virtual ~IProperty() {}
|
||||
|
||||
IProperty(PropertyClass &object,
|
||||
const IProperty &that);
|
||||
|
||||
virtual ~IProperty() {}
|
||||
|
||||
const PropertyClass &get_instance() const;
|
||||
std::string get_name() const;
|
||||
hash_t get_name_hash() const;
|
||||
|
@ -35,7 +35,7 @@ namespace pclass
|
|||
|
||||
virtual Value get_value() 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 read_value_from(BitStream &stream) = 0;
|
||||
|
@ -60,24 +60,24 @@ namespace pclass
|
|||
|
||||
IDynamicProperty(PropertyClass &object,
|
||||
const std::string &name, const Type &type);
|
||||
virtual ~IDynamicProperty() {}
|
||||
|
||||
IDynamicProperty(PropertyClass &object,
|
||||
const IDynamicProperty &that);
|
||||
|
||||
virtual ~IDynamicProperty() {}
|
||||
|
||||
bool is_dynamic() const override;
|
||||
virtual std::size_t get_element_count() const = 0;
|
||||
virtual void set_element_count(std::size_t size) = 0;
|
||||
|
||||
Value get_value() 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 read_value_from(BitStream &stream) final override;
|
||||
|
||||
virtual Value get_value(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 read_value_from(BitStream &stream, int index) = 0;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "ki/pclass/HashCalculator.h"
|
||||
|
||||
|
@ -84,8 +84,8 @@ namespace pclass
|
|||
|
||||
private:
|
||||
std::vector<IProperty *> m_properties;
|
||||
std::map<std::string, IProperty *> m_property_name_lookup;
|
||||
std::map<hash_t, IProperty *> m_property_hash_lookup;
|
||||
std::unordered_map<std::string, IProperty *> m_property_name_lookup;
|
||||
std::unordered_map<hash_t, IProperty *> m_property_hash_lookup;
|
||||
|
||||
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
|
||||
// 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
|
||||
// storing an object.
|
||||
|
@ -158,7 +160,8 @@ namespace pclass
|
|||
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
|
||||
if (object)
|
||||
|
@ -166,7 +169,7 @@ namespace pclass
|
|||
|
||||
// ValueT does derive from PropertyClass, and we have a pointer to an instance
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
if (!object)
|
||||
|
@ -231,8 +235,7 @@ namespace pclass
|
|||
|
||||
// ValueT does derive from PropertyClass, but we don't store a pointer,
|
||||
// so we need to copy the value in.
|
||||
prop.m_value = *dynamic_cast<ValueT *>(object);
|
||||
delete object;
|
||||
prop.m_value = *dynamic_cast<ValueT *>(object.get());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -315,7 +318,8 @@ namespace pclass
|
|||
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);
|
||||
}
|
||||
|
@ -385,7 +389,7 @@ namespace pclass
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include "ki/pclass/HashCalculator.h"
|
||||
#include "ki/pclass/types/Type.h"
|
||||
#include "ki/pclass/types/PrimitiveType.h"
|
||||
|
@ -17,8 +17,7 @@ namespace pclass
|
|||
class TypeSystem
|
||||
{
|
||||
public:
|
||||
explicit TypeSystem(HashCalculator *hash_calculator);
|
||||
~TypeSystem();
|
||||
explicit TypeSystem(std::unique_ptr<HashCalculator> &hash_calculator);
|
||||
|
||||
const HashCalculator &get_hash_calculator() const;
|
||||
|
||||
|
@ -32,7 +31,9 @@ namespace pclass
|
|||
PrimitiveType<ValueT> &define_primitive(const std::string &name)
|
||||
{
|
||||
auto *type = new PrimitiveType<ValueT>(name, *this);
|
||||
define_type(type);
|
||||
define_type(std::unique_ptr<Type>(
|
||||
dynamic_cast<Type *>(type)
|
||||
));
|
||||
return *type;
|
||||
}
|
||||
|
||||
|
@ -53,25 +54,30 @@ namespace pclass
|
|||
CppEnumType<EnumT> &define_enum(const std::string &name)
|
||||
{
|
||||
auto *type = new CppEnumType<EnumT>(name, *this);
|
||||
define_type(type);
|
||||
define_type(std::unique_ptr<Type>(
|
||||
dynamic_cast<Type *>(type)
|
||||
));
|
||||
return *type;
|
||||
}
|
||||
|
||||
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);
|
||||
return dynamic_cast<ClassT *>(type.instantiate());
|
||||
auto object = type.instantiate();
|
||||
return std::unique_ptr<ClassT>(
|
||||
dynamic_cast<ClassT *>(object.release())
|
||||
);
|
||||
}
|
||||
|
||||
protected:
|
||||
void define_type(Type *type);
|
||||
void define_type(std::unique_ptr<Type> type);
|
||||
|
||||
private:
|
||||
TypeList m_types;
|
||||
TypeNameMap m_type_name_lookup;
|
||||
TypeHashMap m_type_hash_lookup;
|
||||
HashCalculator *m_hash_calculator;
|
||||
std::vector<std::unique_ptr<Type>> m_types;
|
||||
std::unordered_map<std::string, Type *> m_type_name_lookup;
|
||||
std::unordered_map<hash_t, Type *> m_type_hash_lookup;
|
||||
std::unique_ptr<HashCalculator> m_hash_calculator;
|
||||
|
||||
template <class ClassT>
|
||||
ClassType<ClassT> &define_class(
|
||||
|
@ -83,7 +89,9 @@ namespace pclass
|
|||
base_class = &get_type("class PropertyClass");
|
||||
|
||||
auto *type = new ClassType<ClassT>(name, base_class, *this);
|
||||
define_type(type);
|
||||
define_type(std::unique_ptr<Type>(
|
||||
dynamic_cast<Type *>(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
|
||||
// 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
|
||||
// storing an object.
|
||||
|
@ -135,7 +137,8 @@ namespace pclass
|
|||
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
|
||||
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
|
||||
// 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));
|
||||
}
|
||||
|
||||
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
|
||||
if (index < 0 || index >= prop.size())
|
||||
|
@ -208,8 +212,7 @@ namespace pclass
|
|||
|
||||
// ValueT does derive from PropertyClass, but we don't store a pointer,
|
||||
// so we need to copy the value in.
|
||||
prop.at(index) = *dynamic_cast<ValueT *>(object);
|
||||
delete object;
|
||||
prop.at(index) = *dynamic_cast<ValueT *>(object.get());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -291,22 +294,26 @@ namespace pclass
|
|||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -365,7 +372,7 @@ namespace pclass
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include "ki/pclass/Property.h"
|
||||
#include "ki/pclass/types/Type.h"
|
||||
#include "ki/pclass/PropertyClass.h"
|
||||
#include "ki/pclass/Property.h"
|
||||
|
||||
namespace ki
|
||||
{
|
||||
|
@ -43,9 +44,12 @@ namespace pclass
|
|||
: 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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include "ki/pclass/types/Type.h"
|
||||
#include "ki/pclass/types/PrimitiveType.h"
|
||||
|
||||
|
@ -47,8 +48,8 @@ namespace pclass
|
|||
|
||||
private:
|
||||
std::vector<Element *> m_elements;
|
||||
std::map<std::string, Element *> m_element_name_lookup;
|
||||
std::map<enum_value_t, Element *> m_element_value_lookup;
|
||||
std::unordered_map<std::string, Element *> m_element_name_lookup;
|
||||
std::unordered_map<enum_value_t, Element *> m_element_value_lookup;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "ki/pclass/HashCalculator.h"
|
||||
#include "ki/pclass/Value.h"
|
||||
#include "ki/util/BitStream.h"
|
||||
|
@ -47,7 +47,7 @@ namespace pclass
|
|||
kind get_kind() 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 Value read_from(BitStream &stream) const;
|
||||
|
||||
|
@ -60,10 +60,6 @@ namespace pclass
|
|||
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] 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);
|
||||
virtual ~SerializerBinary() {}
|
||||
|
||||
/**
|
||||
* @param object
|
||||
* @param 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:
|
||||
/**
|
||||
* @param object
|
||||
* @param stream
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* @param prop
|
||||
* @param stream
|
||||
*/
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace ki
|
|||
void set_bit(int bit);
|
||||
};
|
||||
|
||||
virtual ~IBitBuffer() {};
|
||||
virtual ~IBitBuffer() {}
|
||||
|
||||
/**
|
||||
* @returns
|
||||
|
@ -77,7 +77,9 @@ namespace ki
|
|||
* @param[in] bitsize The size of the segment in bits.
|
||||
* @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.
|
||||
|
@ -214,8 +216,10 @@ namespace ki
|
|||
|
||||
std::size_t size() const override;
|
||||
void resize(std::size_t new_size) override;
|
||||
uint8_t* data() const override;
|
||||
BitBufferSegment *segment(buffer_pos from, std::size_t bitsize) override;
|
||||
uint8_t *data() const override;
|
||||
std::unique_ptr<BitBufferSegment> segment(
|
||||
buffer_pos from, std::size_t bitsize
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @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.");
|
||||
}
|
||||
|
||||
void IDynamicProperty::set_object(PropertyClass *object)
|
||||
void IDynamicProperty::set_object(std::unique_ptr<PropertyClass> &object)
|
||||
{
|
||||
// The caller must specify an index
|
||||
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());
|
||||
}
|
||||
|
||||
PropertyClass *Type::instantiate() const
|
||||
std::unique_ptr<PropertyClass> Type::instantiate() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Type '" << m_name << "' does not implement Type::instantiate.";
|
||||
|
|
|
@ -32,9 +32,9 @@ namespace pclass
|
|||
template <>
|
||||
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
|
||||
// Define integer types
|
||||
|
@ -74,20 +74,6 @@ namespace pclass
|
|||
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
|
||||
{
|
||||
// Make sure the hash calculator isn't null
|
||||
|
@ -132,14 +118,11 @@ namespace pclass
|
|||
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?
|
||||
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
|
||||
std::ostringstream oss;
|
||||
oss << "Type '" << type->get_name() << "' is already defined.";
|
||||
|
@ -149,9 +132,6 @@ namespace pclass
|
|||
// Does a type with this hash already exist?
|
||||
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
|
||||
auto &other_type = get_type(type->get_hash());
|
||||
std::ostringstream oss;
|
||||
|
@ -161,9 +141,9 @@ namespace pclass
|
|||
}
|
||||
|
||||
// This type is safe to add to our lookups
|
||||
m_types.push_back(type);
|
||||
m_type_name_lookup[type->get_name()] = type;
|
||||
m_type_hash_lookup[type->get_hash()] = type;
|
||||
m_type_name_lookup[type->get_name()] = type.get();
|
||||
m_type_hash_lookup[type->get_hash()] = type.get();
|
||||
m_types.push_back(std::move(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "ki/serialization/SerializerBinary.h"
|
||||
#include <zlib.h>
|
||||
#include <cassert>
|
||||
#include "ki/util/unique.h"
|
||||
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
stream.seek(stream.tell() + size * 8, false);
|
||||
|
||||
|
@ -267,21 +272,23 @@ namespace serialization
|
|||
segment_stream.read_copy(compressed.data(), data_available_bytes * 8);
|
||||
|
||||
// Uncompress the compressed buffer
|
||||
auto *uncompressed = new BitBuffer(uncompressed_size);
|
||||
auto uncompressed = ki::make_unique<BitBuffer>(uncompressed_size);
|
||||
uLong dest_len = uncompressed_size;
|
||||
uncompress(uncompressed->data(), &dest_len,
|
||||
compressed.data(), data_available_bytes);
|
||||
|
||||
// Delete the old buffer and use the new uncompressed buffer
|
||||
delete buffer;
|
||||
buffer = uncompressed;
|
||||
buffer = std::unique_ptr<IBitBuffer>(
|
||||
dynamic_cast<IBitBuffer *>(uncompressed.release())
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a segment of the current buffer as the new buffer
|
||||
auto *segment_buffer = buffer->segment(segment_stream.tell(), data_available_bytes);
|
||||
delete buffer;
|
||||
buffer = segment_buffer;
|
||||
segment_buffer = buffer->segment(segment_stream.tell(), data_available_bytes);
|
||||
buffer = std::unique_ptr<IBitBuffer>(
|
||||
dynamic_cast<IBitBuffer *>(segment_buffer.release())
|
||||
);
|
||||
}
|
||||
|
||||
// Create a new stream to read from the new buffer
|
||||
|
@ -289,21 +296,11 @@ namespace serialization
|
|||
}
|
||||
|
||||
// Load the root object
|
||||
try
|
||||
{
|
||||
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>();
|
||||
if (type_hash != 0)
|
||||
|
@ -317,7 +314,8 @@ namespace serialization
|
|||
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
|
||||
preload_object(dest, stream);
|
||||
|
@ -333,11 +331,11 @@ namespace serialization
|
|||
// ensure that data is only read from inside this region.
|
||||
const auto object_size =
|
||||
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.seek(stream.tell() + object_size, false);
|
||||
auto object_stream = BitStream(*object_buffer);
|
||||
stream.seek(stream.tell() + object_size, false);
|
||||
|
||||
// Instead of loading properties sequentially, the file format specifies
|
||||
// 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.
|
||||
const auto property_size =
|
||||
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
|
||||
);
|
||||
auto property_stream = BitStream(*property_buffer);
|
||||
|
@ -360,9 +358,7 @@ namespace serialization
|
|||
const auto property_hash = property_stream.read<uint32_t>();
|
||||
auto &prop = properties.get_property(property_hash);
|
||||
load_property(prop, property_stream);
|
||||
delete property_buffer;
|
||||
}
|
||||
delete object_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -402,7 +398,7 @@ namespace serialization
|
|||
if (property_type.get_kind() == pclass::Type::kind::CLASS)
|
||||
{
|
||||
// Read the object as a nested object
|
||||
pclass::PropertyClass *object = nullptr;
|
||||
std::unique_ptr<pclass::PropertyClass> object = nullptr;
|
||||
load_object(object, stream);
|
||||
dynamic_property.set_object(object, i);
|
||||
}
|
||||
|
@ -421,7 +417,7 @@ namespace serialization
|
|||
if (property_type.get_kind() == pclass::Type::kind::CLASS)
|
||||
{
|
||||
// Read the object as a nested object
|
||||
pclass::PropertyClass *object = nullptr;
|
||||
std::unique_ptr<pclass::PropertyClass> object = nullptr;
|
||||
load_object(object, stream);
|
||||
prop.set_object(object);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <limits>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include "ki/util/unique.h"
|
||||
|
||||
namespace ki
|
||||
{
|
||||
|
@ -141,10 +142,10 @@ namespace ki
|
|||
return copy;
|
||||
}
|
||||
|
||||
BitBufferSegment *IBitBuffer::segment(
|
||||
std::unique_ptr<BitBufferSegment> IBitBuffer::segment(
|
||||
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,
|
||||
|
@ -329,10 +330,12 @@ namespace ki
|
|||
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)
|
||||
{
|
||||
return new BitBufferSegment(*m_buffer, m_from + from, bitsize);
|
||||
return ki::make_unique<BitBufferSegment>(
|
||||
*m_buffer, m_from + from, bitsize
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t BitBufferSegment::read(
|
||||
|
|
|
@ -137,21 +137,19 @@ TEST_CASE("BitBuffer Functionality", "[bit-stream]")
|
|||
|
||||
SECTION("Create valid segment")
|
||||
{
|
||||
auto *segment = bit_buffer.segment(
|
||||
auto segment = bit_buffer.segment(
|
||||
BitBuffer::buffer_pos(0, 0), 8
|
||||
);
|
||||
REQUIRE(segment->size() == 1);
|
||||
delete segment;
|
||||
}
|
||||
|
||||
SECTION("Create invalid segment (invalid position)")
|
||||
{
|
||||
try
|
||||
{
|
||||
auto *segment = bit_buffer.segment(
|
||||
auto segment = bit_buffer.segment(
|
||||
BitBuffer::buffer_pos(1, 0), 8
|
||||
);
|
||||
delete segment;
|
||||
FAIL();
|
||||
}
|
||||
catch (runtime_error &e)
|
||||
|
@ -164,10 +162,9 @@ TEST_CASE("BitBuffer Functionality", "[bit-stream]")
|
|||
{
|
||||
try
|
||||
{
|
||||
auto *segment = bit_buffer.segment(
|
||||
auto segment = bit_buffer.segment(
|
||||
BitBuffer::buffer_pos(0, 0), 16
|
||||
);
|
||||
delete segment;
|
||||
FAIL();
|
||||
}
|
||||
catch (runtime_error &e)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <ki/pclass/StaticProperty.h>
|
||||
#include <ki/pclass/VectorProperty.h>
|
||||
#include <ki/serialization/SerializerBinary.h>
|
||||
#include "ki/util/unique.h"
|
||||
|
||||
using namespace ki;
|
||||
|
||||
|
@ -256,8 +257,9 @@ public:
|
|||
};
|
||||
|
||||
// Setup a global TypeSystem instance
|
||||
auto *g_hash_calculator = new pclass::WizardHashCalculator();
|
||||
pclass::TypeSystem *g_type_system = new pclass::TypeSystem(g_hash_calculator);
|
||||
std::unique_ptr<pclass::HashCalculator> 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;
|
||||
|
||||
/**
|
||||
|
@ -337,13 +339,13 @@ void configure_test_object(TestObject &object)
|
|||
|
||||
// Configure nested objects
|
||||
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.objects.push_back(
|
||||
g_type_system->instantiate<NestedTestObjectA>("class NestedTestObjectA")
|
||||
g_type_system->instantiate<NestedTestObjectA>("class NestedTestObjectA").release()
|
||||
);
|
||||
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.
|
||||
*/
|
||||
void test_serializer(
|
||||
TestObject *&test_object,
|
||||
std::unique_ptr<TestObject> &test_object,
|
||||
serialization::SerializerBinary &serializer,
|
||||
const std::string &file_suffix)
|
||||
{
|
||||
|
@ -425,12 +427,11 @@ void test_serializer(
|
|||
// Create a test object, configure it, and write it to our stream
|
||||
test_object = g_type_system->instantiate<TestObject>("class TestObject");
|
||||
configure_test_object(*test_object);
|
||||
serializer.save(test_object, stream);
|
||||
serializer.save(test_object.get(), stream);
|
||||
const auto end_pos = stream.tell();
|
||||
|
||||
// Delete the test object here so that it is not
|
||||
// unnecessarily validated by the caller
|
||||
delete test_object;
|
||||
test_object = nullptr;
|
||||
|
||||
// Validate the contents of the stream
|
||||
|
@ -452,12 +453,14 @@ void test_serializer(
|
|||
stream.seek(start_pos);
|
||||
|
||||
// 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);
|
||||
|
||||
// Set test_object so that it is validated by the caller
|
||||
REQUIRE(object != nullptr);
|
||||
test_object = dynamic_cast<TestObject *>(object);
|
||||
test_object = std::unique_ptr<TestObject>(
|
||||
dynamic_cast<TestObject *>(object.release())
|
||||
);
|
||||
REQUIRE(test_object != nullptr);
|
||||
}
|
||||
|
||||
|
@ -467,7 +470,7 @@ void test_serializer(
|
|||
|
||||
TEST_CASE("Serialization tests", "[serialization]")
|
||||
{
|
||||
TestObject *test_object = nullptr;
|
||||
std::unique_ptr<TestObject> test_object = nullptr;
|
||||
define_types();
|
||||
|
||||
SECTION("SerializerBinary")
|
||||
|
@ -475,7 +478,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
|||
SECTION("Regular format without compression")
|
||||
{
|
||||
serialization::SerializerBinary serializer(
|
||||
*g_type_system, false,
|
||||
*g_type_system.get(), false,
|
||||
serialization::SerializerBinary::flags::NONE
|
||||
);
|
||||
test_serializer(test_object, serializer, "_regular");
|
||||
|
@ -483,7 +486,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
|||
SECTION("File format without compression")
|
||||
{
|
||||
serialization::SerializerBinary serializer(
|
||||
*g_type_system, true,
|
||||
*g_type_system.get(), true,
|
||||
serialization::SerializerBinary::flags::WRITE_SERIALIZER_FLAGS
|
||||
);
|
||||
test_serializer(test_object, serializer, "_file");
|
||||
|
@ -491,7 +494,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
|||
SECTION("Regular format with compression")
|
||||
{
|
||||
serialization::SerializerBinary serializer(
|
||||
*g_type_system, false,
|
||||
*g_type_system.get(), false,
|
||||
serialization::SerializerBinary::flags::COMPRESSED
|
||||
);
|
||||
test_serializer(test_object, serializer, "_regular_compressed");
|
||||
|
@ -499,7 +502,7 @@ TEST_CASE("Serialization tests", "[serialization]")
|
|||
SECTION("File format with compression")
|
||||
{
|
||||
serialization::SerializerBinary serializer(
|
||||
*g_type_system, true,
|
||||
*g_type_system.get(), true,
|
||||
serialization::SerializerBinary::flags::WRITE_SERIALIZER_FLAGS |
|
||||
serialization::SerializerBinary::flags::COMPRESSED
|
||||
);
|
||||
|
@ -512,7 +515,6 @@ TEST_CASE("Serialization tests", "[serialization]")
|
|||
if (test_object)
|
||||
{
|
||||
validate_test_object(*test_object);
|
||||
delete test_object;
|
||||
test_object = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue