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

View File

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

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

View File

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

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

View File

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

View File

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

View File

@ -31,9 +31,9 @@ namespace detail
private:
/**
* An unsigned integer type with the same size as the floating point type
* ValueT.
*/
* An unsigned integer type with the same size as the floating point type
* ValueT.
*/
using uint_type = typename bits<bitsizeof<ValueT>::value>::uint_type;
};
}

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -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;
load_object(dest, segment_stream);
}
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);
}

View File

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

View File

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

View File

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