mirror of https://github.com/SeanOMik/libki.git
etc: Make Type::read_from return a Value instead of reading into one
This commit is contained in:
parent
28eee3699c
commit
c61a723174
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "ki/pclass/types/EnumType.h"
|
#include "ki/pclass/types/EnumType.h"
|
||||||
#include "ki/pclass/types/PrimitiveType.h"
|
#include "ki/pclass/types/PrimitiveType.h"
|
||||||
#include "ki/util/BitTypes.h"
|
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
|
@ -10,125 +9,36 @@ namespace pclass
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
*/
|
*/
|
||||||
class IEnum
|
class Enum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit IEnum(const Type &type);
|
explicit Enum(const Type &type, enum_value_t value = 0);
|
||||||
virtual ~IEnum() {}
|
explicit Enum(const Type &type, const std::string &element_name);
|
||||||
|
Enum &operator=(const Enum &that);
|
||||||
|
|
||||||
const EnumType &get_type() const;
|
const EnumType &get_type() const;
|
||||||
|
|
||||||
virtual void write_to(BitStream &stream) const = 0;
|
enum_value_t get_value() const;
|
||||||
virtual void read_from(BitStream &stream) = 0;
|
void set_value(enum_value_t value);
|
||||||
|
void set_value(const std::string &element_name);
|
||||||
|
|
||||||
|
void write_to(BitStream& stream) const;
|
||||||
|
void read_from(BitStream& stream);
|
||||||
|
|
||||||
|
operator enum_value_t() const;
|
||||||
|
void operator=(enum_value_t value);
|
||||||
|
bool operator==(const enum_value_t &rhs) const;
|
||||||
|
|
||||||
|
operator std::string() const;
|
||||||
|
void operator=(const std::string &element_name);
|
||||||
|
bool operator==(const std::string &rhs) const;
|
||||||
|
|
||||||
|
bool operator==(const Enum &rhs) const;
|
||||||
|
bool operator!=(const Enum &rhs) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EnumType *m_type;
|
enum_value_t m_value;
|
||||||
};
|
const EnumType *m_type;
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Documentation
|
|
||||||
*/
|
|
||||||
template <typename UnderlyingT>
|
|
||||||
class Enum : public IEnum
|
|
||||||
{
|
|
||||||
// Make sure UnderlyingT is integral
|
|
||||||
static_assert(
|
|
||||||
is_integral<UnderlyingT>::value,
|
|
||||||
"The underlying type of an enum must be integral."
|
|
||||||
);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Enum(const Type &type, UnderlyingT value = 0)
|
|
||||||
: IEnum(type)
|
|
||||||
{
|
|
||||||
set_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Enum(const Type &type, const std::string &element_name)
|
|
||||||
: IEnum(type)
|
|
||||||
{
|
|
||||||
set_value(element_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
UnderlyingT get_value() const
|
|
||||||
{
|
|
||||||
return m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void set_value(UnderlyingT value)
|
|
||||||
{
|
|
||||||
if (value != 0 && !get_type().has_element(value))
|
|
||||||
{
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "Enum '" << get_type().get_name()
|
|
||||||
<< "' has no element with value: " << value << ".";
|
|
||||||
throw runtime_error(oss.str());
|
|
||||||
}
|
|
||||||
m_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_value(const std::string &element_name)
|
|
||||||
{
|
|
||||||
m_value = get_type().get_element(element_name).get_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_to(BitStream& stream) const override
|
|
||||||
{
|
|
||||||
PrimitiveTypeWriter<UnderlyingT>::write_to(stream, m_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_from(BitStream& stream) override
|
|
||||||
{
|
|
||||||
UnderlyingT value;
|
|
||||||
PrimitiveTypeReader<UnderlyingT>::read_from(stream, value);
|
|
||||||
set_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator UnderlyingT() const
|
|
||||||
{
|
|
||||||
return get_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(UnderlyingT value)
|
|
||||||
{
|
|
||||||
set_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const UnderlyingT &rhs) const
|
|
||||||
{
|
|
||||||
return m_value == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::string() const
|
|
||||||
{
|
|
||||||
return get_type().get_element(m_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(const std::string &element_name)
|
|
||||||
{
|
|
||||||
set_value(element_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const std::string &rhs) const
|
|
||||||
{
|
|
||||||
if (!get_type().has_element(rhs))
|
|
||||||
return false;
|
|
||||||
return m_value == get_type().get_element(rhs).get_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Enum<UnderlyingT> &rhs) const
|
|
||||||
{
|
|
||||||
return get_type() == &rhs.get_type() &&
|
|
||||||
m_value == rhs.m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const Enum<UnderlyingT> &rhs) const
|
|
||||||
{
|
|
||||||
return !(*this == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
UnderlyingT m_value;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -248,12 +248,16 @@ namespace pclass
|
||||||
{
|
{
|
||||||
static void write(const StaticProperty<ValueT> &prop, BitStream &stream)
|
static void write(const StaticProperty<ValueT> &prop, BitStream &stream)
|
||||||
{
|
{
|
||||||
prop.get_type().write_to(stream, Value::make_reference(prop.m_value));
|
prop.get_type().write_to(
|
||||||
|
stream,
|
||||||
|
Value::make_reference<ValueT>(prop.m_value)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read(StaticProperty<ValueT> &prop, BitStream &stream)
|
static void read(StaticProperty<ValueT> &prop, BitStream &stream)
|
||||||
{
|
{
|
||||||
prop.get_type().read_from(stream, Value::make_reference(prop.m_value));
|
Value value = prop.get_type().read_from(stream);
|
||||||
|
prop.m_value = value.get<ValueT>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,14 +276,20 @@ namespace pclass
|
||||||
>::type
|
>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
using type = typename std::remove_pointer<ValueT>::type;
|
||||||
|
|
||||||
static void write(const StaticProperty<ValueT> &prop, BitStream &stream)
|
static void write(const StaticProperty<ValueT> &prop, BitStream &stream)
|
||||||
{
|
{
|
||||||
prop.get_type().write_to(stream, Value::make_reference(*prop.m_value));
|
prop.get_type().write_to(
|
||||||
|
stream,
|
||||||
|
Value::make_reference<type>(*prop.m_value)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read(StaticProperty<ValueT> &prop, BitStream &stream)
|
static void read(StaticProperty<ValueT> &prop, BitStream &stream)
|
||||||
{
|
{
|
||||||
prop.get_type().read_from(stream, Value::make_reference(*prop.m_value));
|
Value value = prop.get_type().read_from(stream);
|
||||||
|
prop.m_value = value.take<type>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,17 @@ namespace pclass
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Whether or not the value being held is of type T.
|
* @returns Whether or the not the value is holding a reference or a value.
|
||||||
|
*/
|
||||||
|
bool is_reference() const
|
||||||
|
{
|
||||||
|
// If the pointer isn't owned, then it isn't this Value's responsibility
|
||||||
|
// to clean it up, so we say it's referencing something.
|
||||||
|
return !m_ptr_is_owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns Whether or not the value being held is of type T.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool is() const
|
bool is() const
|
||||||
|
@ -210,29 +220,72 @@ namespace pclass
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A reference to the value being held as the specified type.
|
* @tparam T
|
||||||
|
* @returns A new Value instance that owns it's value.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
Value dereference() const
|
||||||
|
{
|
||||||
|
// Do we need to attempt casting?
|
||||||
|
if (!is<T>())
|
||||||
|
return m_caster->cast_value<T>(*this);
|
||||||
|
return Value::make_value<T>(*static_cast<T *>(m_value_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @tparam T The expected type.
|
||||||
|
* @returns A reference to the value being held.
|
||||||
|
* @throws ki::runtime_error The expected type and the type of the value being held are not the same.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const T &get() const
|
const T &get() const
|
||||||
{
|
{
|
||||||
// Do we need to attempt casting?
|
// Make sure they requested the correct type
|
||||||
if (!is<T>())
|
if (!is<T>())
|
||||||
return m_caster->cast_value<T>(*this).get<T>();
|
throw runtime_error("Invalid call to Value::get<T>.");
|
||||||
|
|
||||||
|
// Return a reference to the value being held
|
||||||
return *static_cast<T *>(m_value_ptr);
|
return *static_cast<T *>(m_value_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A reference to the value being held as the specified type.
|
* @tparam T The expected type.
|
||||||
|
* @returns A reference to the value being held.
|
||||||
|
* @throws ki::runtime_error If the expected type and the type of the value being held are not the same.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T &get()
|
T &get()
|
||||||
{
|
{
|
||||||
// Do we need to attempt casting?
|
// Make sure they requested the correct type
|
||||||
if (!is<T>())
|
if (!is<T>())
|
||||||
return m_caster->cast_value<T>(*this).get<T>();
|
throw runtime_error("Invalid call to Value::get<T>.");
|
||||||
|
|
||||||
|
// Return a reference to the value being held
|
||||||
return *static_cast<T *>(m_value_ptr);
|
return *static_cast<T *>(m_value_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @tparam T The expected type.
|
||||||
|
* @returns A pointer to the value being held (that the caller takes ownership of).
|
||||||
|
* @throws ki::runtime_error If the Value is a reference.
|
||||||
|
* @throws ki::runtime_error If the expected type and the type of the value being held are not the same.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T *take()
|
||||||
|
{
|
||||||
|
// Make sure this Value is not a reference
|
||||||
|
if (is_reference())
|
||||||
|
throw runtime_error("Cannot take ownership from a reference Value.");
|
||||||
|
|
||||||
|
// Make sure they requested the correct type
|
||||||
|
if (!is<T>())
|
||||||
|
throw runtime_error("Invalid call to Value::get<T>.");
|
||||||
|
|
||||||
|
// Give up the pointer (this Value becomes a reference)
|
||||||
|
m_ptr_is_owned = false;
|
||||||
|
return static_cast<T *>(m_value_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @tparam T The type of value to hold.
|
* @tparam T The type of value to hold.
|
||||||
* @param[in] value The initial value.
|
* @param[in] value The initial value.
|
||||||
|
@ -278,11 +331,7 @@ namespace pclass
|
||||||
private:
|
private:
|
||||||
void *m_value_ptr;
|
void *m_value_ptr;
|
||||||
bool m_ptr_is_owned;
|
bool m_ptr_is_owned;
|
||||||
|
|
||||||
std::size_t m_type_hash;
|
std::size_t m_type_hash;
|
||||||
bool m_value_is_object;
|
|
||||||
bool m_value_is_enum;
|
|
||||||
|
|
||||||
ValueCaster *m_caster;
|
ValueCaster *m_caster;
|
||||||
detail::ValueDeallocator m_deallocator;
|
detail::ValueDeallocator m_deallocator;
|
||||||
|
|
||||||
|
@ -295,15 +344,6 @@ namespace pclass
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void construct()
|
void construct()
|
||||||
{
|
{
|
||||||
m_value_is_object = std::is_base_of<
|
|
||||||
PropertyClass,
|
|
||||||
typename std::decay<T>::type
|
|
||||||
>::value;
|
|
||||||
m_value_is_enum = std::is_base_of<
|
|
||||||
IEnum,
|
|
||||||
typename std::decay<T>::type
|
|
||||||
>::value;
|
|
||||||
|
|
||||||
m_type_hash = typeid(T).hash_code();
|
m_type_hash = typeid(T).hash_code();
|
||||||
m_caster = &ValueCaster::get<T>();
|
m_caster = &ValueCaster::get<T>();
|
||||||
m_deallocator = detail::ValueDeallocator::make<T>();
|
m_deallocator = detail::ValueDeallocator::make<T>();
|
||||||
|
|
|
@ -227,7 +227,11 @@ namespace pclass
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
prop.get_type().write_to(stream, prop.at(index));
|
|
||||||
|
prop.get_type().write_to(
|
||||||
|
stream,
|
||||||
|
Value::make_reference<ValueT>(prop.at(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)
|
||||||
|
@ -235,7 +239,9 @@ namespace pclass
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
prop.get_type().read_from(stream, Value(prop.at(index)));
|
|
||||||
|
Value value = prop.get_type().read_from(stream);
|
||||||
|
prop.at(index) = value.get<ValueT>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,13 +254,18 @@ namespace pclass
|
||||||
typename std::enable_if<std::is_pointer<ValueT>::value>::type
|
typename std::enable_if<std::is_pointer<ValueT>::value>::type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
|
using type = typename std::remove_pointer<ValueT>::type;
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
// Ensure index is within bounds
|
// Ensure index is within bounds
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
|
|
||||||
prop.get_type().write_to(stream, Value::make_reference(*prop.at(index)));
|
prop.get_type().write_to(
|
||||||
|
stream,
|
||||||
|
Value::make_reference<type>(*prop.at(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)
|
||||||
|
@ -263,7 +274,9 @@ namespace pclass
|
||||||
if (index < 0 || index >= prop.size())
|
if (index < 0 || index >= prop.size())
|
||||||
throw runtime_error("Index out of bounds.");
|
throw runtime_error("Index out of bounds.");
|
||||||
|
|
||||||
prop.get_type().read_from(stream, Value::make_reference(*prop.at(index)));
|
Value value = prop.get_type().read_from(stream);
|
||||||
|
ValueT &value_ref = prop.at(index);
|
||||||
|
value_ref = value.take<type>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#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
|
||||||
{
|
{
|
||||||
|
@ -19,14 +19,10 @@ namespace pclass
|
||||||
const Type *base_class, const TypeSystem &type_system);
|
const Type *base_class, const TypeSystem &type_system);
|
||||||
virtual ~IClassType() {}
|
virtual ~IClassType() {}
|
||||||
|
|
||||||
void write_to(BitStream &stream, const Value &value) const override;
|
|
||||||
void read_from(BitStream &stream, Value &value) const override;
|
|
||||||
|
|
||||||
bool inherits(const Type &type) const;
|
bool inherits(const Type &type) const;
|
||||||
|
|
||||||
protected:
|
void write_to(BitStream &stream, Value value) const override = 0;
|
||||||
virtual const PropertyClass &get_object_from_value(const Value &value) const = 0;
|
Value read_from(BitStream &stream) const override = 0;
|
||||||
virtual PropertyClass &get_object_from_value(Value &value) const = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const IClassType *m_base_class;
|
const IClassType *m_base_class;
|
||||||
|
@ -44,21 +40,29 @@ namespace pclass
|
||||||
public:
|
public:
|
||||||
ClassType(const std::string &name,
|
ClassType(const std::string &name,
|
||||||
const Type *base_class, const TypeSystem &type_system)
|
const Type *base_class, const TypeSystem &type_system)
|
||||||
: IClassType(name, base_class, type_system) {}
|
: IClassType(name, base_class, type_system)
|
||||||
|
{}
|
||||||
|
|
||||||
PropertyClass *instantiate() const override
|
PropertyClass *instantiate() const override
|
||||||
{
|
{
|
||||||
return new ClassT(*this, get_type_system());
|
return new ClassT(*this, get_type_system());
|
||||||
}
|
}
|
||||||
|
|
||||||
const PropertyClass& get_object_from_value(const Value& value) const override
|
void write_to(BitStream &stream, Value value) const override
|
||||||
{
|
{
|
||||||
return dynamic_cast<const PropertyClass &>(value.get<ClassT>());
|
const auto &object = value.get<ClassT>();
|
||||||
|
const auto &properties = object.get_properties();
|
||||||
|
for (auto it = properties.begin(); it != properties.end(); ++it)
|
||||||
|
it->write_value_to(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyClass& get_object_from_value(Value& value) const override
|
Value read_from(BitStream &stream) const override
|
||||||
{
|
{
|
||||||
return dynamic_cast<PropertyClass &>(value.get<ClassT>());
|
auto object = ClassT(*this, get_type_system());
|
||||||
|
auto &properties = object.get_properties();
|
||||||
|
for (auto it = properties.begin(); it != properties.end(); ++it)
|
||||||
|
it->read_value_from(stream);
|
||||||
|
return Value::make_value<ClassT>(object);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
{
|
{
|
||||||
typedef uint64_t enum_value_t;
|
typedef uint32_t enum_value_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
|
@ -42,8 +42,8 @@ namespace pclass
|
||||||
|
|
||||||
EnumType &add_element(const std::string &name, enum_value_t value);
|
EnumType &add_element(const std::string &name, enum_value_t value);
|
||||||
|
|
||||||
void write_to(BitStream& stream, const Value& value) const override;
|
void write_to(BitStream &stream, Value value) const override;
|
||||||
void read_from(BitStream& stream, Value& value) const override;
|
Value read_from(BitStream &stream) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Element *> m_elements;
|
std::vector<Element *> m_elements;
|
||||||
|
@ -68,17 +68,20 @@ namespace pclass
|
||||||
m_kind = kind::ENUM;
|
m_kind = kind::ENUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_to(BitStream& stream, const Value &value) const override
|
void write_to(BitStream &stream, const Value value) const override
|
||||||
{
|
{
|
||||||
PrimitiveTypeWriter<underlying_type>::write_to(
|
auto &enum_reference = value.get<EnumT>();
|
||||||
stream, reinterpret_cast<const underlying_type &>(value.get<EnumT>())
|
auto &underlying_reference = reinterpret_cast<const underlying_type &>(enum_reference);
|
||||||
);
|
detail::primitive_type_helper<underlying_type>::write_to(stream, underlying_reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_from(BitStream& stream, Value &value) const override
|
Value read_from(BitStream &stream) const override
|
||||||
{
|
{
|
||||||
PrimitiveTypeReader<underlying_type>::read_from(
|
Value read_result =
|
||||||
stream, reinterpret_cast<underlying_type &>(value.get<EnumT>())
|
detail::primitive_type_helper<underlying_type>::read_from(stream);
|
||||||
|
auto underlying_value = read_result.get<underlying_type>();
|
||||||
|
return Value::make_value<EnumT>(
|
||||||
|
static_cast<EnumT>(underlying_value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename ValueT>
|
template <typename ValueT>
|
||||||
struct PrimitiveTypeWriter<
|
struct primitive_type_helper<
|
||||||
ValueT,
|
ValueT,
|
||||||
typename std::enable_if<std::is_floating_point<ValueT>::value>::type
|
typename std::enable_if<std::is_floating_point<ValueT>::value>::type
|
||||||
>
|
>
|
||||||
|
@ -21,27 +23,10 @@ namespace pclass
|
||||||
stream.write<uint_type>(v, bitsizeof<ValueT>::value);
|
stream.write<uint_type>(v, bitsizeof<ValueT>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
static Value read_from(BitStream &stream)
|
||||||
/**
|
|
||||||
* An unsigned integer type with the same size as the floating point type
|
|
||||||
* ValueT.
|
|
||||||
*/
|
|
||||||
using uint_type = typename bits<bitsizeof<ValueT>::value>::uint_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ValueT>
|
|
||||||
struct PrimitiveTypeReader<
|
|
||||||
ValueT,
|
|
||||||
typename std::enable_if<std::is_floating_point<ValueT>::value>::type
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
static void read_from(BitStream &stream, ValueT &value)
|
uint_type uint_value = stream.read<uint_type>(bitsizeof<ValueT>::value);
|
||||||
{
|
return Value::make_value<ValueT>(*reinterpret_cast<ValueT *>(&uint_value));
|
||||||
// Reinterpret the reference as a reference to an integer
|
|
||||||
uint_type &v = *(
|
|
||||||
reinterpret_cast<uint_type *>(&value)
|
|
||||||
);
|
|
||||||
v = stream.read<uint_type>(bitsizeof<ValueT>::value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -53,3 +38,4 @@ namespace pclass
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename ValueT>
|
template <typename ValueT>
|
||||||
struct PrimitiveTypeWriter<
|
struct primitive_type_helper<
|
||||||
ValueT,
|
ValueT,
|
||||||
typename std::enable_if<is_integral<ValueT>::value>::type
|
typename std::enable_if<is_integral<ValueT>::value>::type
|
||||||
>
|
>
|
||||||
|
@ -16,18 +18,14 @@ namespace pclass
|
||||||
{
|
{
|
||||||
stream.write<ValueT>(value);
|
stream.write<ValueT>(value);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ValueT>
|
static Value read_from(BitStream &stream)
|
||||||
struct PrimitiveTypeReader<
|
|
||||||
ValueT,
|
|
||||||
typename std::enable_if<is_integral<ValueT>::value>::type
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
static void read_from(BitStream &stream, ValueT &value)
|
return Value::make_value<ValueT>(
|
||||||
{
|
stream.read<ValueT>()
|
||||||
value = stream.read<ValueT>();
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,37 +5,42 @@ namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
*/
|
*/
|
||||||
template <typename ValueT, typename Enable = void>
|
template <typename ValueT, typename Enable = void>
|
||||||
struct PrimitiveTypeWriter
|
struct primitive_type_helper
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* TODO: Documentation
|
||||||
|
*/
|
||||||
static void write_to(BitStream &stream, const ValueT &value)
|
static void write_to(BitStream &stream, const ValueT &value)
|
||||||
{
|
{
|
||||||
// Provide a compiler error if this is not specialized
|
// Provide a compiler error if this is not specialized
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof(ValueT) == 0,
|
sizeof(ValueT) == 0,
|
||||||
"Missing specialization of PrimitiveTypeWriter::write_to"
|
"Missing specialization of primitive_type_writer::write_to"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
*/
|
*/
|
||||||
template <typename ValueT, typename Enable = void>
|
static Value read_from(BitStream &stream)
|
||||||
struct PrimitiveTypeReader
|
|
||||||
{
|
|
||||||
static void read_from(BitStream &stream, ValueT &value)
|
|
||||||
{
|
{
|
||||||
// Provide a compiler error if this is not specialized
|
// Provide a compiler error if this is not specialized
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof(ValueT) == 0,
|
sizeof(ValueT) == 0,
|
||||||
"Missing specialization of PrimitiveTypeReader::read_from"
|
"Missing specialization of PrimitiveTypeReader::read_from"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// This should be impossible to reach.
|
||||||
|
throw runtime_error("Missing specialization of PrimitiveTypeReader::read_from");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Documentation
|
* TODO: Documentation
|
||||||
|
@ -50,11 +55,16 @@ namespace pclass
|
||||||
m_kind = kind::PRIMITIVE;
|
m_kind = kind::PRIMITIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_to(BitStream &stream, const Value &value) const override
|
void write_to(BitStream &stream, const Value value) const override
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PrimitiveTypeWriter<ValueT>::write_to(stream, value.get<ValueT>());
|
// Dereference the value to the correct type
|
||||||
|
Value deref_value = value.dereference<ValueT>();
|
||||||
|
detail::primitive_type_helper<ValueT>::write_to(
|
||||||
|
stream,
|
||||||
|
deref_value.get<ValueT>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
catch (runtime_error &e)
|
catch (runtime_error &e)
|
||||||
{
|
{
|
||||||
|
@ -64,11 +74,11 @@ namespace pclass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_from(BitStream &stream, Value &value) const override
|
Value read_from(BitStream &stream) const override
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PrimitiveTypeReader<ValueT>::read_from(stream, value.get<ValueT>());
|
return detail::primitive_type_helper<ValueT>::read_from(stream);
|
||||||
}
|
}
|
||||||
catch (runtime_error &e)
|
catch (runtime_error &e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
{
|
{
|
||||||
template <
|
template <
|
||||||
typename _Elem,
|
typename _Elem,
|
||||||
typename _Traits,
|
typename _Traits,
|
||||||
typename _Alloc
|
typename _Alloc
|
||||||
>
|
>
|
||||||
struct PrimitiveTypeWriter<std::basic_string<_Elem, _Traits, _Alloc>>
|
struct primitive_type_helper<std::basic_string<_Elem, _Traits, _Alloc>>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using type = std::basic_string<_Elem, _Traits, _Alloc>;
|
using type = std::basic_string<_Elem, _Traits, _Alloc>;
|
||||||
|
@ -25,29 +27,21 @@ namespace pclass
|
||||||
for (auto it = value.begin(); it != value.end(); ++it)
|
for (auto it = value.begin(); it != value.end(); ++it)
|
||||||
stream.write<_Elem>(*it);
|
stream.write<_Elem>(*it);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <
|
static Value read_from(BitStream &stream)
|
||||||
typename _Elem,
|
|
||||||
typename _Traits,
|
|
||||||
typename _Alloc
|
|
||||||
>
|
|
||||||
struct PrimitiveTypeReader<std::basic_string<_Elem, _Traits, _Alloc>>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using type = std::basic_string<_Elem, _Traits, _Alloc>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void read_from(BitStream &stream, type &value)
|
|
||||||
{
|
{
|
||||||
// Read the length and create a new string with the correct capacity
|
// Read the length and create a new string with the correct capacity
|
||||||
auto length = stream.read<uint16_t>();
|
auto length = stream.read<uint16_t>();
|
||||||
value = type(length, ' ');
|
auto value = type(length, ' ');;
|
||||||
|
|
||||||
// Read each character into the string
|
// Read each character into the string
|
||||||
for (auto it = value.begin(); it != value.end(); ++it)
|
for (auto it = value.begin(); it != value.end(); ++it)
|
||||||
*it = stream.read<_Elem>();
|
*it = stream.read<_Elem>();
|
||||||
|
|
||||||
|
// Copy string value into the return value
|
||||||
|
return Value::make_value<type>(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ namespace pclass
|
||||||
const TypeSystem &get_type_system() const;
|
const TypeSystem &get_type_system() const;
|
||||||
|
|
||||||
virtual PropertyClass *instantiate() const;
|
virtual PropertyClass *instantiate() const;
|
||||||
virtual void write_to(BitStream &stream, const Value &value) const;
|
virtual void write_to(BitStream &stream, Value value) const;
|
||||||
virtual void read_from(BitStream &stream, Value &value) const;
|
virtual Value read_from(BitStream &stream) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
kind m_kind;
|
kind m_kind;
|
||||||
|
|
|
@ -28,22 +28,6 @@ namespace pclass
|
||||||
m_base_class = nullptr;
|
m_base_class = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IClassType::write_to(BitStream &stream, const Value &value) const
|
|
||||||
{
|
|
||||||
const auto &object = get_object_from_value(value);
|
|
||||||
const auto &properties = object.get_properties();
|
|
||||||
for (auto it = properties.begin(); it != properties.end(); ++it)
|
|
||||||
it->write_value_to(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IClassType::read_from(BitStream &stream, Value &value) const
|
|
||||||
{
|
|
||||||
auto &object = get_object_from_value(value);
|
|
||||||
auto &properties = object.get_properties();
|
|
||||||
for (auto it = properties.begin(); it != properties.end(); ++it)
|
|
||||||
it->read_value_from(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IClassType::inherits(const Type &type) const
|
bool IClassType::inherits(const Type &type) const
|
||||||
{
|
{
|
||||||
// Types do not technically inherit from themselves, but it is more useful
|
// Types do not technically inherit from themselves, but it is more useful
|
||||||
|
|
|
@ -4,6 +4,116 @@ namespace ki
|
||||||
{
|
{
|
||||||
namespace pclass
|
namespace pclass
|
||||||
{
|
{
|
||||||
// TODO: Runtime Enum implementation
|
Enum::Enum(const Type &type, const enum_value_t value)
|
||||||
|
{
|
||||||
|
// Make sure the type we've been given is an enum type
|
||||||
|
if (type.get_kind() != Type::kind::ENUM)
|
||||||
|
throw runtime_error("Enum constructor was supplied with a non-enum type.");
|
||||||
|
|
||||||
|
m_type = &dynamic_cast<const EnumType &>(type);
|
||||||
|
set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum::Enum(const Type &type, const std::string &element_name)
|
||||||
|
{
|
||||||
|
// Make sure the type we've been given is an enum type
|
||||||
|
if (type.get_kind() != Type::kind::ENUM)
|
||||||
|
throw runtime_error("Enum constructor was supplied with a non-enum type.");
|
||||||
|
|
||||||
|
m_type = &dynamic_cast<const EnumType &>(type);
|
||||||
|
set_value(element_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum& Enum::operator=(const Enum& that)
|
||||||
|
{
|
||||||
|
// Are the types the same?
|
||||||
|
if (&get_type() != &that.get_type())
|
||||||
|
throw runtime_error("Cannot change Enum type after it's constructed.");
|
||||||
|
set_value(that.m_value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EnumType &Enum::get_type() const
|
||||||
|
{
|
||||||
|
return *m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum_value_t Enum::get_value() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::set_value(const enum_value_t value)
|
||||||
|
{
|
||||||
|
// Make sure the given value is valid for this enum type
|
||||||
|
if (value != 0 && !get_type().has_element(value))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Enum '" << get_type().get_name()
|
||||||
|
<< "' has no element with value: " << value << ".";
|
||||||
|
throw runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
m_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::set_value(const std::string& element_name)
|
||||||
|
{
|
||||||
|
m_value = get_type().get_element(element_name).get_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::write_to(BitStream& stream) const
|
||||||
|
{
|
||||||
|
detail::primitive_type_helper<enum_value_t>::write_to(stream, m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::read_from(BitStream& stream)
|
||||||
|
{
|
||||||
|
const auto value = detail::primitive_type_helper<enum_value_t>
|
||||||
|
::read_from(stream).get<enum_value_t>();
|
||||||
|
set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum::operator enum_value_t() const
|
||||||
|
{
|
||||||
|
return get_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::operator=(const enum_value_t value)
|
||||||
|
{
|
||||||
|
set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Enum::operator==(const enum_value_t &rhs) const
|
||||||
|
{
|
||||||
|
return m_value == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum::operator std::basic_string<char>() const
|
||||||
|
{
|
||||||
|
return get_type().get_element(m_value).get_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::operator=(const std::string& element_name)
|
||||||
|
{
|
||||||
|
set_value(element_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Enum::operator==(const std::string& rhs) const
|
||||||
|
{
|
||||||
|
if (!get_type().has_element(rhs))
|
||||||
|
return false;
|
||||||
|
return m_value == get_type().get_element(rhs).get_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Enum::operator==(const Enum &rhs) const
|
||||||
|
{
|
||||||
|
return &get_type() == &rhs.get_type() &&
|
||||||
|
m_value == rhs.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Enum::operator!=(const Enum& rhs) const
|
||||||
|
{
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "ki/pclass/types/EnumType.h"
|
#include "ki/pclass/types/EnumType.h"
|
||||||
#include "ki/util/exception.h"
|
#include "ki/util/exception.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include "ki/pclass/Enum.h"
|
||||||
|
|
||||||
namespace ki
|
namespace ki
|
||||||
{
|
{
|
||||||
|
@ -109,14 +110,17 @@ namespace pclass
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnumType::write_to(BitStream& stream, const Value &value) const
|
void EnumType::write_to(BitStream &stream, const Value value) const
|
||||||
{
|
{
|
||||||
// TODO: Extend Value to get IEnum values
|
// Get an Enum reference and use it to write to the stream
|
||||||
|
value.get<Enum>().write_to(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnumType::read_from(BitStream& stream, Value &value) const
|
Value EnumType::read_from(BitStream &stream) const
|
||||||
{
|
{
|
||||||
// TODO: Extend Value to get IEnum values
|
auto value = Enum(*this);
|
||||||
|
value.read_from(stream);
|
||||||
|
return Value::make_value<Enum>(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,14 @@ namespace pclass
|
||||||
return m_type_system;
|
return m_type_system;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Type::write_to(BitStream &stream, const Value& value) const
|
void Type::write_to(BitStream &stream, Value value) const
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Type '" << m_name << "' does not implement Type::write_to.";
|
oss << "Type '" << m_name << "' does not implement Type::write_to.";
|
||||||
throw runtime_error(oss.str());
|
throw runtime_error(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Type::read_from(BitStream &stream, Value& value) const
|
Value Type::read_from(BitStream &stream) const
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "Type '" << m_name << "' does not implement Type::read_from.";
|
oss << "Type '" << m_name << "' does not implement Type::read_from.";
|
||||||
|
|
|
@ -69,8 +69,6 @@ namespace pclass
|
||||||
m_value_ptr = value_ptr;
|
m_value_ptr = value_ptr;
|
||||||
m_ptr_is_owned = owned;
|
m_ptr_is_owned = owned;
|
||||||
m_type_hash = 0;
|
m_type_hash = 0;
|
||||||
m_value_is_object = false;
|
|
||||||
m_value_is_enum = false;
|
|
||||||
m_caster = nullptr;
|
m_caster = nullptr;
|
||||||
m_deallocator = detail::ValueDeallocator();
|
m_deallocator = detail::ValueDeallocator();
|
||||||
}
|
}
|
||||||
|
@ -82,9 +80,6 @@ namespace pclass
|
||||||
m_value_ptr = that.m_value_ptr;
|
m_value_ptr = that.m_value_ptr;
|
||||||
m_ptr_is_owned = that.m_ptr_is_owned;
|
m_ptr_is_owned = that.m_ptr_is_owned;
|
||||||
that.m_ptr_is_owned = false;
|
that.m_ptr_is_owned = false;
|
||||||
|
|
||||||
m_value_is_object = that.m_value_is_object;
|
|
||||||
m_value_is_enum = that.m_value_is_enum;
|
|
||||||
m_type_hash = that.m_type_hash;
|
m_type_hash = that.m_type_hash;
|
||||||
m_caster = that.m_caster;
|
m_caster = that.m_caster;
|
||||||
m_deallocator = std::move(that.m_deallocator);
|
m_deallocator = std::move(that.m_deallocator);
|
||||||
|
@ -101,9 +96,6 @@ namespace pclass
|
||||||
m_value_ptr = that.m_value_ptr;
|
m_value_ptr = that.m_value_ptr;
|
||||||
m_ptr_is_owned = that.m_ptr_is_owned;
|
m_ptr_is_owned = that.m_ptr_is_owned;
|
||||||
that.m_ptr_is_owned = false;
|
that.m_ptr_is_owned = false;
|
||||||
|
|
||||||
m_value_is_object = that.m_value_is_object;
|
|
||||||
m_value_is_enum = that.m_value_is_enum;
|
|
||||||
m_type_hash = that.m_type_hash;
|
m_type_hash = that.m_type_hash;
|
||||||
m_caster = that.m_caster;
|
m_caster = that.m_caster;
|
||||||
m_deallocator = std::move(that.m_deallocator);
|
m_deallocator = std::move(that.m_deallocator);
|
||||||
|
|
|
@ -45,16 +45,22 @@ struct Vector3D
|
||||||
|
|
||||||
void write_to(BitStream &stream) const
|
void write_to(BitStream &stream) const
|
||||||
{
|
{
|
||||||
pclass::PrimitiveTypeWriter<float>::write_to(stream, m_x);
|
pclass::detail::primitive_type_helper<float>
|
||||||
pclass::PrimitiveTypeWriter<float>::write_to(stream, m_y);
|
::write_to(stream, m_x);
|
||||||
pclass::PrimitiveTypeWriter<float>::write_to(stream, m_z);
|
pclass::detail::primitive_type_helper<float>
|
||||||
|
::write_to(stream, m_y);
|
||||||
|
pclass::detail::primitive_type_helper<float>
|
||||||
|
::write_to(stream, m_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_from(BitStream &stream)
|
void read_from(BitStream &stream)
|
||||||
{
|
{
|
||||||
pclass::PrimitiveTypeReader<float>::read_from(stream, m_x);
|
m_x = pclass::detail::primitive_type_helper<float>
|
||||||
pclass::PrimitiveTypeReader<float>::read_from(stream, m_y);
|
::read_from(stream).get<float>();
|
||||||
pclass::PrimitiveTypeReader<float>::read_from(stream, m_z);
|
m_y = pclass::detail::primitive_type_helper<float>
|
||||||
|
::read_from(stream).get<float>();
|
||||||
|
m_z = pclass::detail::primitive_type_helper<float>
|
||||||
|
::read_from(stream).get<float>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -63,29 +69,34 @@ private:
|
||||||
float m_z;
|
float m_z;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
namespace ki
|
||||||
* Type Writer for custom primitive type (Vector3D).
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
struct pclass::PrimitiveTypeWriter<Vector3D>
|
|
||||||
{
|
{
|
||||||
|
namespace pclass
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Helper for custom primitive type (Vector3D).
|
||||||
|
* Provides write_to and read_from implementations for PrimitiveType.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
struct primitive_type_helper<Vector3D>
|
||||||
|
{
|
||||||
static void write_to(BitStream &stream, const Vector3D &value)
|
static void write_to(BitStream &stream, const Vector3D &value)
|
||||||
{
|
{
|
||||||
value.write_to(stream);
|
value.write_to(stream);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
static Value read_from(BitStream &stream)
|
||||||
* Type Reader for custom primitive type (Vector3D).
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
struct pclass::PrimitiveTypeReader<Vector3D>
|
|
||||||
{
|
|
||||||
static void read_from(BitStream &stream, Vector3D &value)
|
|
||||||
{
|
{
|
||||||
|
Vector3D value;
|
||||||
value.read_from(stream);
|
value.read_from(stream);
|
||||||
|
return Value::make_value<Vector3D>(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enumeration used to test enum serialization.
|
* Enumeration used to test enum serialization.
|
||||||
|
|
Loading…
Reference in New Issue