etc: Make Type::read_from return a Value instead of reading into one

This commit is contained in:
Joshua Scott 2018-12-10 21:26:34 +00:00
parent 28eee3699c
commit c61a723174
17 changed files with 373 additions and 304 deletions

View File

@ -1,7 +1,6 @@
#pragma once
#include "ki/pclass/types/EnumType.h"
#include "ki/pclass/types/PrimitiveType.h"
#include "ki/util/BitTypes.h"
namespace ki
{
@ -10,125 +9,36 @@ namespace pclass
/**
* TODO: Documentation
*/
class IEnum
class Enum
{
public:
explicit IEnum(const Type &type);
virtual ~IEnum() {}
explicit Enum(const Type &type, enum_value_t value = 0);
explicit Enum(const Type &type, const std::string &element_name);
Enum &operator=(const Enum &that);
const EnumType &get_type() const;
virtual void write_to(BitStream &stream) const = 0;
virtual void read_from(BitStream &stream) = 0;
enum_value_t get_value() const;
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:
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;
enum_value_t m_value;
const EnumType *m_type;
};
}
}

View File

@ -248,12 +248,16 @@ namespace pclass
{
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)
{
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
>
{
using type = typename std::remove_pointer<ValueT>::type;
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)
{
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>();
}
};

View File

@ -200,7 +200,17 @@ namespace pclass
~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>
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>
const T &get() const
{
// Do we need to attempt casting?
// Make sure they requested the correct type
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 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>
T &get()
{
// Do we need to attempt casting?
// Make sure they requested the correct type
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);
}
/**
* @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.
* @param[in] value The initial value.
@ -278,11 +331,7 @@ namespace pclass
private:
void *m_value_ptr;
bool m_ptr_is_owned;
std::size_t m_type_hash;
bool m_value_is_object;
bool m_value_is_enum;
ValueCaster *m_caster;
detail::ValueDeallocator m_deallocator;
@ -295,15 +344,6 @@ namespace pclass
template <typename T>
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_caster = &ValueCaster::get<T>();
m_deallocator = detail::ValueDeallocator::make<T>();

View File

@ -227,7 +227,11 @@ namespace pclass
// Ensure index is within bounds
if (index < 0 || index >= prop.size())
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)
@ -235,7 +239,9 @@ namespace pclass
// Ensure index is within bounds
if (index < 0 || index >= prop.size())
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
>
{
using type = typename std::remove_pointer<ValueT>::type;
static void write_value_to(const VectorProperty<ValueT> &prop, BitStream &stream, const int index)
{
// Ensure index is within bounds
if (index < 0 || index >= prop.size())
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)
@ -263,7 +274,9 @@ namespace pclass
if (index < 0 || index >= prop.size())
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>();
}
};

View File

@ -1,9 +1,9 @@
#pragma once
#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
{
@ -19,14 +19,10 @@ namespace pclass
const Type *base_class, const TypeSystem &type_system);
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;
protected:
virtual const PropertyClass &get_object_from_value(const Value &value) const = 0;
virtual PropertyClass &get_object_from_value(Value &value) const = 0;
void write_to(BitStream &stream, Value value) const override = 0;
Value read_from(BitStream &stream) const override = 0;
private:
const IClassType *m_base_class;
@ -44,21 +40,29 @@ namespace pclass
public:
ClassType(const std::string &name,
const Type *base_class, const TypeSystem &type_system)
: IClassType(name, base_class, type_system) {}
: IClassType(name, base_class, type_system)
{}
PropertyClass *instantiate() const override
{
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);
}
};
}

View File

@ -7,7 +7,7 @@ namespace ki
{
namespace pclass
{
typedef uint64_t enum_value_t;
typedef uint32_t enum_value_t;
/**
* TODO: Documentation
@ -42,8 +42,8 @@ namespace pclass
EnumType &add_element(const std::string &name, enum_value_t value);
void write_to(BitStream& stream, const Value& value) const override;
void read_from(BitStream& stream, Value& value) const override;
void write_to(BitStream &stream, Value value) const override;
Value read_from(BitStream &stream) const override;
private:
std::vector<Element *> m_elements;
@ -68,17 +68,20 @@ namespace pclass
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(
stream, reinterpret_cast<const underlying_type &>(value.get<EnumT>())
);
auto &enum_reference = 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(
stream, reinterpret_cast<underlying_type &>(value.get<EnumT>())
Value read_result =
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)
);
}
};

View File

@ -5,9 +5,11 @@
namespace ki
{
namespace pclass
{
namespace detail
{
template <typename ValueT>
struct PrimitiveTypeWriter<
struct primitive_type_helper<
ValueT,
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);
}
private:
/**
* 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 Value read_from(BitStream &stream)
{
static void read_from(BitStream &stream, ValueT &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);
uint_type uint_value = stream.read<uint_type>(bitsizeof<ValueT>::value);
return Value::make_value<ValueT>(*reinterpret_cast<ValueT *>(&uint_value));
}
private:
@ -53,3 +38,4 @@ namespace pclass
};
}
}
}

View File

@ -5,9 +5,11 @@
namespace ki
{
namespace pclass
{
namespace detail
{
template <typename ValueT>
struct PrimitiveTypeWriter<
struct primitive_type_helper<
ValueT,
typename std::enable_if<is_integral<ValueT>::value>::type
>
@ -16,18 +18,14 @@ namespace pclass
{
stream.write<ValueT>(value);
}
};
template <typename ValueT>
struct PrimitiveTypeReader<
ValueT,
typename std::enable_if<is_integral<ValueT>::value>::type
>
static Value read_from(BitStream &stream)
{
static void read_from(BitStream &stream, ValueT &value)
{
value = stream.read<ValueT>();
return Value::make_value<ValueT>(
stream.read<ValueT>()
);
}
};
}
}
}

View File

@ -5,37 +5,42 @@ namespace ki
{
namespace pclass
{
namespace detail
{
/**
* TODO: Documentation
*/
template <typename ValueT, typename Enable = void>
struct PrimitiveTypeWriter
struct primitive_type_helper
{
/**
* TODO: Documentation
*/
static void write_to(BitStream &stream, const ValueT &value)
{
// Provide a compiler error if this is not specialized
static_assert(
sizeof(ValueT) == 0,
"Missing specialization of PrimitiveTypeWriter::write_to"
"Missing specialization of primitive_type_writer::write_to"
);
}
};
/**
* TODO: Documentation
*/
template <typename ValueT, typename Enable = void>
struct PrimitiveTypeReader
{
static void read_from(BitStream &stream, ValueT &value)
static Value read_from(BitStream &stream)
{
// Provide a compiler error if this is not specialized
static_assert(
sizeof(ValueT) == 0,
"Missing specialization of PrimitiveTypeReader::read_from"
);
// This should be impossible to reach.
throw runtime_error("Missing specialization of PrimitiveTypeReader::read_from");
}
};
}
/**
* TODO: Documentation
@ -50,11 +55,16 @@ namespace pclass
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
{
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)
{
@ -64,11 +74,11 @@ namespace pclass
}
}
void read_from(BitStream &stream, Value &value) const override
Value read_from(BitStream &stream) const override
{
try
{
PrimitiveTypeReader<ValueT>::read_from(stream, value.get<ValueT>());
return detail::primitive_type_helper<ValueT>::read_from(stream);
}
catch (runtime_error &e)
{

View File

@ -4,13 +4,15 @@
namespace ki
{
namespace pclass
{
namespace detail
{
template <
typename _Elem,
typename _Traits,
typename _Alloc
>
struct PrimitiveTypeWriter<std::basic_string<_Elem, _Traits, _Alloc>>
struct primitive_type_helper<std::basic_string<_Elem, _Traits, _Alloc>>
{
private:
using type = std::basic_string<_Elem, _Traits, _Alloc>;
@ -25,29 +27,21 @@ namespace pclass
for (auto it = value.begin(); it != value.end(); ++it)
stream.write<_Elem>(*it);
}
};
template <
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)
static Value read_from(BitStream &stream)
{
// Read the length and create a new string with the correct capacity
auto length = stream.read<uint16_t>();
value = type(length, ' ');
auto value = type(length, ' ');;
// Read each character into the string
for (auto it = value.begin(); it != value.end(); ++it)
*it = stream.read<_Elem>();
// Copy string value into the return value
return Value::make_value<type>(value);
}
};
}
}
}

View File

@ -48,8 +48,8 @@ namespace pclass
const TypeSystem &get_type_system() const;
virtual PropertyClass *instantiate() const;
virtual void write_to(BitStream &stream, const Value &value) const;
virtual void read_from(BitStream &stream, Value &value) const;
virtual void write_to(BitStream &stream, Value value) const;
virtual Value read_from(BitStream &stream) const;
protected:
kind m_kind;

View File

@ -28,22 +28,6 @@ namespace pclass
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
{
// Types do not technically inherit from themselves, but it is more useful

View File

@ -4,6 +4,116 @@ namespace ki
{
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);
}
}
}

View File

@ -1,6 +1,7 @@
#include "ki/pclass/types/EnumType.h"
#include "ki/util/exception.h"
#include <sstream>
#include "ki/pclass/Enum.h"
namespace ki
{
@ -109,14 +110,17 @@ namespace pclass
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);
}
}
}

View File

@ -39,14 +39,14 @@ namespace pclass
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;
oss << "Type '" << m_name << "' does not implement Type::write_to.";
throw runtime_error(oss.str());
}
void Type::read_from(BitStream &stream, Value& value) const
Value Type::read_from(BitStream &stream) const
{
std::ostringstream oss;
oss << "Type '" << m_name << "' does not implement Type::read_from.";

View File

@ -69,8 +69,6 @@ namespace pclass
m_value_ptr = value_ptr;
m_ptr_is_owned = owned;
m_type_hash = 0;
m_value_is_object = false;
m_value_is_enum = false;
m_caster = nullptr;
m_deallocator = detail::ValueDeallocator();
}
@ -82,9 +80,6 @@ namespace pclass
m_value_ptr = that.m_value_ptr;
m_ptr_is_owned = that.m_ptr_is_owned;
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_caster = that.m_caster;
m_deallocator = std::move(that.m_deallocator);
@ -101,9 +96,6 @@ namespace pclass
m_value_ptr = that.m_value_ptr;
m_ptr_is_owned = that.m_ptr_is_owned;
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_caster = that.m_caster;
m_deallocator = std::move(that.m_deallocator);

View File

@ -45,16 +45,22 @@ struct Vector3D
void write_to(BitStream &stream) const
{
pclass::PrimitiveTypeWriter<float>::write_to(stream, m_x);
pclass::PrimitiveTypeWriter<float>::write_to(stream, m_y);
pclass::PrimitiveTypeWriter<float>::write_to(stream, m_z);
pclass::detail::primitive_type_helper<float>
::write_to(stream, m_x);
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)
{
pclass::PrimitiveTypeReader<float>::read_from(stream, m_x);
pclass::PrimitiveTypeReader<float>::read_from(stream, m_y);
pclass::PrimitiveTypeReader<float>::read_from(stream, m_z);
m_x = pclass::detail::primitive_type_helper<float>
::read_from(stream).get<float>();
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:
@ -63,29 +69,34 @@ private:
float m_z;
};
/**
* Type Writer for custom primitive type (Vector3D).
*/
template <>
struct pclass::PrimitiveTypeWriter<Vector3D>
namespace ki
{
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)
{
value.write_to(stream);
}
};
/**
* Type Reader for custom primitive type (Vector3D).
*/
template <>
struct pclass::PrimitiveTypeReader<Vector3D>
{
static void read_from(BitStream &stream, Vector3D &value)
static Value read_from(BitStream &stream)
{
Vector3D value;
value.read_from(stream);
return Value::make_value<Vector3D>(value);
}
};
};
}
}
}
/**
* Enumeration used to test enum serialization.