etc: Start using smart pointers

This commit is contained in:
Joshua Scott 2018-12-13 22:12:04 +00:00
parent 1955e72bb9
commit a2c577ce47
19 changed files with 208 additions and 148 deletions

View File

@ -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;
}; };

View File

@ -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);
}; };

View File

@ -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);
} }

View File

@ -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;
} }
}; };

View File

@ -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);
} }

View File

@ -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

View File

@ -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;
}; };
/** /**

View File

@ -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.

View File

@ -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:

View File

@ -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.
@ -215,7 +217,9 @@ 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)

16
include/ki/util/unique.h Normal file
View File

@ -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

View File

@ -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.");

View File

@ -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.";

View File

@ -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));
} }
} }
} }

View File

@ -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 void SerializerBinary::preload_object(
delete buffer; std::unique_ptr<pclass::PropertyClass> &dest, BitStream &stream) const
}
void SerializerBinary::preload_object(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);
} }

View File

@ -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(

View File

@ -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)

View File

@ -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;
} }
} }