pclass: Introduce the PUBLIC property flag, along with the WRITE_PUBLIC_ONLY serializer flag

Also fixed issues with serializer tests.
This commit is contained in:
pythonology 2019-06-27 19:42:18 -04:00
parent 4d48485d4c
commit 5a0ec6f2d7
12 changed files with 87 additions and 43 deletions

View File

@ -4,6 +4,7 @@
#include "ki/pclass/HashCalculator.h" #include "ki/pclass/HashCalculator.h"
#include "ki/pclass/Value.h" #include "ki/pclass/Value.h"
#include "ki/util/BitStream.h" #include "ki/util/BitStream.h"
#include "ki/util/FlagsEnum.h"
namespace ki namespace ki
{ {
@ -19,12 +20,27 @@ namespace pclass
class IProperty class IProperty
{ {
public: public:
/**
* These flags can be used to define special rules for the property.
*/
enum class flags : uint32_t
{
NONE = 0,
/**
* When enabled, the property is marked as public.
* This can be used in conjunction with the WRITE_PUBLIC_ONLY serializer flag.
*/
PUBLIC = 0x04
};
// Do not allow copy assignment. Once a property has been constructed, // Do not allow copy assignment. Once a property has been constructed,
// it shouldn't be able to change. // it shouldn't be able to change.
virtual IProperty &operator=(const IProperty &that) = delete; virtual IProperty &operator=(const IProperty &that) = delete;
IProperty(PropertyClass &object, IProperty(PropertyClass &object,
const std::string &name, const Type &type); const std::string &name, const Type &type, flags flags);
IProperty(PropertyClass &object, IProperty(PropertyClass &object,
const IProperty &that); const IProperty &that);
@ -34,6 +50,7 @@ namespace pclass
hash_t get_name_hash() const; hash_t get_name_hash() const;
hash_t get_full_hash() const; hash_t get_full_hash() const;
const Type &get_type() const; const Type &get_type() const;
flags get_flags() const;
/** /**
* @returns A reference to the instance of PropertyClass that this property * @returns A reference to the instance of PropertyClass that this property
@ -116,6 +133,10 @@ namespace pclass
hash_t m_name_hash; hash_t m_name_hash;
hash_t m_full_hash; hash_t m_full_hash;
const Type *m_type; const Type *m_type;
flags m_flags;
}; };
} }
} }
// Make sure the flags enum can be used like a bitflag
MAKE_FLAGS_ENUM(ki::pclass::IProperty::flags);

View File

@ -39,14 +39,14 @@ _KI_PCLASS_COPY_CONSTRUCTOR(derived) \
#define TYPE(n) type_system.get_type(n) #define TYPE(n) type_system.get_type(n)
#define INIT_PROPERTY(identifier, type) \ #define INIT_PROPERTY(identifier, type, flags) \
, identifier(*this, #identifier, TYPE(type)) , identifier(*this, #identifier, TYPE(type), flags)
#define INIT_PROPERTY_COPY(identifier) \ #define INIT_PROPERTY_COPY(identifier) \
, identifier(*this, that.identifier) , identifier(*this, that.identifier)
#define INIT_PROPERTY_VALUE(identifier, type, value) \ #define INIT_PROPERTY_VALUE(identifier, type, flags, value) \
, identifier(*this, #identifier, TYPE(type), value) , identifier(*this, #identifier, TYPE(type), flags, value)
namespace ki namespace ki
{ {

View File

@ -458,14 +458,14 @@ namespace pclass
StaticProperty<ValueT> &operator=(const StaticProperty<ValueT> &that) = delete; StaticProperty<ValueT> &operator=(const StaticProperty<ValueT> &that) = delete;
StaticProperty(PropertyClass &object, StaticProperty(PropertyClass &object,
const std::string &name, const Type &type) const std::string &name, const Type &type, IProperty::flags flags)
: IStaticProperty<ValueT>(object, name, type) : IStaticProperty<ValueT>(object, name, type, flags)
, m_value(detail::static_object_helper<ValueT>::construct(type)) , m_value(detail::static_object_helper<ValueT>::construct(type))
{} {}
StaticProperty(PropertyClass &object, StaticProperty(PropertyClass &object,
const std::string &name, const Type &type, ValueT value) const std::string &name, const Type &type, IProperty::flags flags, ValueT value)
: IStaticProperty<ValueT>(object, name, type) : IStaticProperty<ValueT>(object, name, type, flags)
{ {
m_value = value; m_value = value;
} }
@ -563,8 +563,8 @@ namespace pclass
StaticProperty<ValueT[N]> &operator=(const StaticProperty<ValueT[N]> &that) = delete; StaticProperty<ValueT[N]> &operator=(const StaticProperty<ValueT[N]> &that) = delete;
StaticProperty(PropertyClass &object, StaticProperty(PropertyClass &object,
const std::string &name, const Type &type) const std::string &name, const Type &type, IProperty::flags flags)
: IStaticProperty<ValueT[N]>(object, name, type) : IStaticProperty<ValueT[N]>(object, name, type, flags)
{ {
for (auto i = 0; i < N; ++i) for (auto i = 0; i < N; ++i)
m_value[i] = detail::static_object_helper<ValueT>::construct(type); m_value[i] = detail::static_object_helper<ValueT>::construct(type);

View File

@ -251,8 +251,8 @@ namespace pclass
VectorProperty<ValueT> &operator=(const VectorProperty<ValueT> &that) = delete; VectorProperty<ValueT> &operator=(const VectorProperty<ValueT> &that) = delete;
VectorProperty(PropertyClass &object, VectorProperty(PropertyClass &object,
const std::string &name, const Type &type) const std::string &name, const Type &type, IProperty::flags flags)
: IProperty(object, name, type) : IProperty(object, name, type, flags)
{} {}
VectorProperty(PropertyClass &object, VectorProperty(PropertyClass &object,

View File

@ -30,6 +30,12 @@ namespace serialization
*/ */
WRITE_SERIALIZER_FLAGS = 0x01, WRITE_SERIALIZER_FLAGS = 0x01,
/**
* When enabled, only properties that were declared with the PUBLIC flag
* will be written.
*/
WRITE_PUBLIC_ONLY = 0x04,
/** /**
* When enabled, the serialized data (after the flags, if present) is * When enabled, the serialized data (after the flags, if present) is
* potentially compressed. This is based on an added compression header. * potentially compressed. This is based on an added compression header.

View File

@ -8,7 +8,7 @@
#define SET_FLAG(v, f) v |= f #define SET_FLAG(v, f) v |= f
#define UNSET_FLAG(v, f) v &= ~f #define UNSET_FLAG(v, f) v &= ~f
#define FLAG_IS_SET(v, f) (v & f) == f #define FLAG_IS_SET(v, f) ((v & f) == f)
namespace ki namespace ki
{ {

View File

@ -8,7 +8,7 @@ namespace ki
namespace pclass namespace pclass
{ {
IProperty::IProperty(PropertyClass &object, IProperty::IProperty(PropertyClass &object,
const std::string &name, const Type &type) const std::string &name, const Type &type, IProperty::flags flags)
{ {
m_instance = &object; m_instance = &object;
m_name = name; m_name = name;
@ -18,6 +18,7 @@ namespace pclass
.calculate_property_hash(name); .calculate_property_hash(name);
m_full_hash = m_name_hash + type.get_hash(); m_full_hash = m_name_hash + type.get_hash();
m_type = &type; m_type = &type;
m_flags = flags;
// Add this property to the object's property list // Add this property to the object's property list
object.add_property(*this); object.add_property(*this);
@ -31,6 +32,7 @@ namespace pclass
m_name_hash = that.m_name_hash; m_name_hash = that.m_name_hash;
m_full_hash = that.m_full_hash; m_full_hash = that.m_full_hash;
m_type = that.m_type; m_type = that.m_type;
m_flags = that.m_flags;
// Add this property to the object's property list // Add this property to the object's property list
object.add_property(*this); object.add_property(*this);
@ -61,6 +63,11 @@ namespace pclass
return *m_type; return *m_type;
} }
IProperty::flags IProperty::get_flags() const
{
return m_flags;
}
bool IProperty::is_pointer() const bool IProperty::is_pointer() const
{ {
return false; return false;

View File

@ -163,6 +163,11 @@ namespace serialization
void BinarySerializer::save_property(const pclass::IProperty &prop, BitStream &stream) const void BinarySerializer::save_property(const pclass::IProperty &prop, BitStream &stream) const
{ {
// Ignore non-public properties if the WRITE_PUBLIC_ONLY flag is set
if (FLAG_IS_SET(m_flags, flags::WRITE_PUBLIC_ONLY) &&
!FLAG_IS_SET(prop.get_flags(), pclass::IProperty::flags::PUBLIC))
return;
// Realign the stream if we're going to write a prefix for this property // Realign the stream if we're going to write a prefix for this property
if (prop.is_dynamic() || m_is_file) if (prop.is_dynamic() || m_is_file)
stream.realign(); stream.realign();
@ -373,6 +378,11 @@ namespace serialization
void BinarySerializer::load_property(pclass::IProperty &prop, BitStream &stream) const void BinarySerializer::load_property(pclass::IProperty &prop, BitStream &stream) const
{ {
// Ignore non-public properties if the WRITE_PUBLIC_ONLY flag is set
if (FLAG_IS_SET(m_flags, flags::WRITE_PUBLIC_ONLY) &&
!FLAG_IS_SET(prop.get_flags(), pclass::IProperty::flags::PUBLIC))
return;
// Re-align the stream if we're going to read a prefix for this property // Re-align the stream if we're going to read a prefix for this property
if (prop.is_dynamic()) if (prop.is_dynamic())
stream.realign(); stream.realign();

Binary file not shown.

View File

@ -202,7 +202,7 @@ PCLASS(NestedTestObject)
{ {
public: public:
PCLASS_CONSTRUCTOR(NestedTestObject) PCLASS_CONSTRUCTOR(NestedTestObject)
INIT_PROPERTY(m_kind, "enum NestedObjectKind") INIT_PROPERTY(m_kind, "enum NestedObjectKind", pclass::IProperty::flags::PUBLIC)
{ {
m_kind = NestedObjectKind::OBJECT; m_kind = NestedObjectKind::OBJECT;
} }
@ -231,7 +231,7 @@ DERIVED_PCLASS(NestedTestObjectA, NestedTestObject)
{ {
public: public:
DERIVED_PCLASS_CONSTRUCTOR(NestedTestObjectA, NestedTestObject) DERIVED_PCLASS_CONSTRUCTOR(NestedTestObjectA, NestedTestObject)
INIT_PROPERTY(extra_value, "int") INIT_PROPERTY(extra_value, "int", pclass::IProperty::flags::PUBLIC)
{ {
m_kind = NestedObjectKind::OBJECT_A; m_kind = NestedObjectKind::OBJECT_A;
extra_value = 10; extra_value = 10;
@ -271,32 +271,32 @@ PCLASS(TestObject)
{ {
public: public:
PCLASS_CONSTRUCTOR(TestObject) PCLASS_CONSTRUCTOR(TestObject)
INIT_PROPERTY(int4, "bi4") INIT_PROPERTY(int4, "bi4", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(uint4, "bui4") INIT_PROPERTY(uint4, "bui4", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int8, "char") INIT_PROPERTY(int8, "char", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int16, "short") INIT_PROPERTY(int16, "short", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int24, "s24") INIT_PROPERTY(int24, "s24", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int32, "int") INIT_PROPERTY(int32, "int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int64, "long") INIT_PROPERTY(int64, "long", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(uint8, "unsigned char") INIT_PROPERTY(uint8, "unsigned char", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(uint16, "unsigned short") INIT_PROPERTY(uint16, "unsigned short", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(uint24, "u24") INIT_PROPERTY(uint24, "u24", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(uint32, "unsigned int") INIT_PROPERTY(uint32, "unsigned int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(uint64, "unsigned long") INIT_PROPERTY(uint64, "unsigned long", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(string, "std::string") INIT_PROPERTY(string, "std::string", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(wstring, "std::wstring") INIT_PROPERTY(wstring, "std::wstring", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(float32, "float") INIT_PROPERTY(float32, "float", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(float64, "double") INIT_PROPERTY(float64, "double", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(vector3d, "struct Vector3D") INIT_PROPERTY(vector3d, "struct Vector3D", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int_ptr, "int") INIT_PROPERTY(int_ptr, "int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int_array, "int") INIT_PROPERTY(int_array, "int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int_ptr_array, "int") INIT_PROPERTY(int_ptr_array, "int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(object, "class NestedTestObjectA") INIT_PROPERTY(object, "class NestedTestObjectA", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(object_ptr, "class NestedTestObject") INIT_PROPERTY(object_ptr, "class NestedTestObject", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(null_object_ptr, "class NestedTestObject") INIT_PROPERTY(null_object_ptr, "class NestedTestObject", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int_vector, "int") INIT_PROPERTY(int_vector, "int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(int_ptr_vector, "int") INIT_PROPERTY(int_ptr_vector, "int", pclass::IProperty::flags::PUBLIC)
INIT_PROPERTY(object_ptr_vector, "class NestedTestObject") INIT_PROPERTY(object_ptr_vector, "class NestedTestObject", pclass::IProperty::flags::PUBLIC)
{} {}
// Test signed and unsigned integers with a bit length less than 8 // Test signed and unsigned integers with a bit length less than 8