From 5a0ec6f2d7a1b4c529bbcbe473fae544546b23a7 Mon Sep 17 00:00:00 2001 From: pythonology Date: Thu, 27 Jun 2019 19:42:18 -0400 Subject: [PATCH] pclass: Introduce the PUBLIC property flag, along with the WRITE_PUBLIC_ONLY serializer flag Also fixed issues with serializer tests. --- include/ki/pclass/Property.h | 23 ++++++- include/ki/pclass/PropertyClass.h | 8 +-- include/ki/pclass/StaticProperty.h | 12 ++-- include/ki/pclass/VectorProperty.h | 4 +- include/ki/serialization/BinarySerializer.h | 6 ++ include/ki/util/FlagsEnum.h | 2 +- src/pclass/Property.cpp | 9 ++- src/serialization/BinarySerializer.cpp | 10 ++++ test/samples/serialization/file.bin | Bin 1289 -> 1279 bytes .../samples/serialization/file_compressed.bin | Bin 577 -> 574 bytes .../serialization/regular_compressed.bin | Bin 332 -> 331 bytes test/src/unit-serialization.cpp | 56 +++++++++--------- 12 files changed, 87 insertions(+), 43 deletions(-) diff --git a/include/ki/pclass/Property.h b/include/ki/pclass/Property.h index 855ae24..a40a8d4 100644 --- a/include/ki/pclass/Property.h +++ b/include/ki/pclass/Property.h @@ -4,6 +4,7 @@ #include "ki/pclass/HashCalculator.h" #include "ki/pclass/Value.h" #include "ki/util/BitStream.h" +#include "ki/util/FlagsEnum.h" namespace ki { @@ -19,12 +20,27 @@ namespace pclass class IProperty { 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, // it shouldn't be able to change. virtual IProperty &operator=(const IProperty &that) = delete; IProperty(PropertyClass &object, - const std::string &name, const Type &type); + const std::string &name, const Type &type, flags flags); IProperty(PropertyClass &object, const IProperty &that); @@ -34,6 +50,7 @@ namespace pclass hash_t get_name_hash() const; hash_t get_full_hash() const; const Type &get_type() const; + flags get_flags() const; /** * @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_full_hash; 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); diff --git a/include/ki/pclass/PropertyClass.h b/include/ki/pclass/PropertyClass.h index 6472432..93219a3 100644 --- a/include/ki/pclass/PropertyClass.h +++ b/include/ki/pclass/PropertyClass.h @@ -39,14 +39,14 @@ _KI_PCLASS_COPY_CONSTRUCTOR(derived) \ #define TYPE(n) type_system.get_type(n) -#define INIT_PROPERTY(identifier, type) \ - , identifier(*this, #identifier, TYPE(type)) +#define INIT_PROPERTY(identifier, type, flags) \ + , identifier(*this, #identifier, TYPE(type), flags) #define INIT_PROPERTY_COPY(identifier) \ , identifier(*this, that.identifier) -#define INIT_PROPERTY_VALUE(identifier, type, value) \ - , identifier(*this, #identifier, TYPE(type), value) +#define INIT_PROPERTY_VALUE(identifier, type, flags, value) \ + , identifier(*this, #identifier, TYPE(type), flags, value) namespace ki { diff --git a/include/ki/pclass/StaticProperty.h b/include/ki/pclass/StaticProperty.h index 09d3c6f..623f8e8 100644 --- a/include/ki/pclass/StaticProperty.h +++ b/include/ki/pclass/StaticProperty.h @@ -458,14 +458,14 @@ namespace pclass StaticProperty &operator=(const StaticProperty &that) = delete; StaticProperty(PropertyClass &object, - const std::string &name, const Type &type) - : IStaticProperty(object, name, type) + const std::string &name, const Type &type, IProperty::flags flags) + : IStaticProperty(object, name, type, flags) , m_value(detail::static_object_helper::construct(type)) {} StaticProperty(PropertyClass &object, - const std::string &name, const Type &type, ValueT value) - : IStaticProperty(object, name, type) + const std::string &name, const Type &type, IProperty::flags flags, ValueT value) + : IStaticProperty(object, name, type, flags) { m_value = value; } @@ -563,8 +563,8 @@ namespace pclass StaticProperty &operator=(const StaticProperty &that) = delete; StaticProperty(PropertyClass &object, - const std::string &name, const Type &type) - : IStaticProperty(object, name, type) + const std::string &name, const Type &type, IProperty::flags flags) + : IStaticProperty(object, name, type, flags) { for (auto i = 0; i < N; ++i) m_value[i] = detail::static_object_helper::construct(type); diff --git a/include/ki/pclass/VectorProperty.h b/include/ki/pclass/VectorProperty.h index ea0021b..54c8977 100644 --- a/include/ki/pclass/VectorProperty.h +++ b/include/ki/pclass/VectorProperty.h @@ -251,8 +251,8 @@ namespace pclass VectorProperty &operator=(const VectorProperty &that) = delete; VectorProperty(PropertyClass &object, - const std::string &name, const Type &type) - : IProperty(object, name, type) + const std::string &name, const Type &type, IProperty::flags flags) + : IProperty(object, name, type, flags) {} VectorProperty(PropertyClass &object, diff --git a/include/ki/serialization/BinarySerializer.h b/include/ki/serialization/BinarySerializer.h index 2177483..f0cc4c0 100644 --- a/include/ki/serialization/BinarySerializer.h +++ b/include/ki/serialization/BinarySerializer.h @@ -30,6 +30,12 @@ namespace serialization */ 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 * potentially compressed. This is based on an added compression header. diff --git a/include/ki/util/FlagsEnum.h b/include/ki/util/FlagsEnum.h index 5b5907b..7a10809 100644 --- a/include/ki/util/FlagsEnum.h +++ b/include/ki/util/FlagsEnum.h @@ -8,7 +8,7 @@ #define SET_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 { diff --git a/src/pclass/Property.cpp b/src/pclass/Property.cpp index 26ad2b8..c0137d2 100644 --- a/src/pclass/Property.cpp +++ b/src/pclass/Property.cpp @@ -8,7 +8,7 @@ namespace ki namespace pclass { 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_name = name; @@ -18,6 +18,7 @@ namespace pclass .calculate_property_hash(name); m_full_hash = m_name_hash + type.get_hash(); m_type = &type; + m_flags = flags; // Add this property to the object's property list object.add_property(*this); @@ -31,6 +32,7 @@ namespace pclass m_name_hash = that.m_name_hash; m_full_hash = that.m_full_hash; m_type = that.m_type; + m_flags = that.m_flags; // Add this property to the object's property list object.add_property(*this); @@ -61,6 +63,11 @@ namespace pclass return *m_type; } + IProperty::flags IProperty::get_flags() const + { + return m_flags; + } + bool IProperty::is_pointer() const { return false; diff --git a/src/serialization/BinarySerializer.cpp b/src/serialization/BinarySerializer.cpp index dad2bc7..d16c5ac 100644 --- a/src/serialization/BinarySerializer.cpp +++ b/src/serialization/BinarySerializer.cpp @@ -163,6 +163,11 @@ namespace serialization 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 if (prop.is_dynamic() || m_is_file) stream.realign(); @@ -373,6 +378,11 @@ namespace serialization 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 if (prop.is_dynamic()) stream.realign(); diff --git a/test/samples/serialization/file.bin b/test/samples/serialization/file.bin index 348843f3b86ec6a00873a403ed5134267c3edae5..9ffa2380f9e45212c5db0983efae379240e80a98 100644 GIT binary patch delta 128 zcmeC=`p>E4je?|=#h;jQymjLTT#S*m_K+ZC`TcsKy z8JWcjK$NIZl3HA%P?nfen%V)>zw5)}wHg!mUg12!!@!{Z>y*lg&2t$iFoL-WA^dz$ S?hByOyKZx1Steg)F#!NLZYtye delta 138 zcmey**~z8oje@2ZL3j@Q3-nATo6O~FdJ^%%m$=xay zVF<~{ELH%bM1_*n;u3|j#GKO92|)e3K0ID4!Z2~q6`lt?3=G=8PN}2-^=zKWIDru? ak`ThrhY(?4Vqm!IHa8YXF-$(qVgdk~Eh&Tm diff --git a/test/samples/serialization/file_compressed.bin b/test/samples/serialization/file_compressed.bin index 57817788d2cd2f55411cc3f41688c839f83a8379..ae3a110f29d3e6e1d22b478732889834dcd09ee3 100644 GIT binary patch literal 574 zcmV-E0>S-4Nls)500001_XGd{c%1FiOHUI~7>DuGp#@r6riG%Y3=E1|#o`@NytGiN z^)6Ifg({^IHM-Ei$il`L6Ah8X7}>DVU;-vyqZ<}o5n~K7u3Q<35lUikrEA^z96Q9A z@Bv(y^w)V$&%AS{^FI?WZM!nGQizZc;?3uwv_lq?A8xsAdnld^j;Ae$DIEQtvOFbD z^>yTtns2jqQeJ)fSasM73$9V;+uo@q9=BTTau&(X4&{3N@6MT^5zKY!jfQS^-n6*= zbDiHFc<;`2&N6;j`O)x2&z|ei`6Tt;?w(%#a`J-F-ER>h^L^%-FQ&avF6miC7rF0d zO&2jOqGgpBRlC-#O)GK6a-}a9-#1LEk$_xjI&o*D+#ibmthNV+86R?W-4J3tC`50Q z_xYKCJpZ7Gnu2prH~~G9}1=wiL@ygXLHO_KEOe6;`7bYv4y6)?yvjV*@rqKFrOi#}+hT zE4HB#+pz;Xu?qo^h-gBy$ZgCPgs~fPb49Qh`>-Dea8L#cx#y0c6>W&(D2^cpxf74$ z1lrMo1Ww|V8A=jeNSVQOM%Ci~!Te*v%o4_@@V$gJV@-vp#GhA7G3&aD;j|1R^E&m{ Mt0%+z1;2!kJd08n*#H0l literal 577 zcmV-H0>1r1Nls)5000010R;d6c%1Fi%}*0S7{~FaOMwC z_zF~8g({^GHG0s{%E87M6O9Sc5WRTOU;-w-VDQ4BCt{2T3O-X-TnOQx)8(>97PCf zJ08PvbfX6moWMylmnixWGqdRp>P7#v`S-F>L3{|@i>N$O)>t4dzuqy;tm`XAlPZtY P%h+%4pvvzD`gM)u!Ra1P diff --git a/test/samples/serialization/regular_compressed.bin b/test/samples/serialization/regular_compressed.bin index 3efc38d9e47d20703abc062b6724154e43b30b7b..8b93632c4a7dd225da53d864d4111f81c714c08e 100644 GIT binary patch delta 8 PcmX@Zbed@+qc> delta 9 QcmX@jbcTtMaf3G_01u1;ng9R* diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index bc83e5e..7f1aa05 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -202,7 +202,7 @@ PCLASS(NestedTestObject) { public: PCLASS_CONSTRUCTOR(NestedTestObject) - INIT_PROPERTY(m_kind, "enum NestedObjectKind") + INIT_PROPERTY(m_kind, "enum NestedObjectKind", pclass::IProperty::flags::PUBLIC) { m_kind = NestedObjectKind::OBJECT; } @@ -231,7 +231,7 @@ DERIVED_PCLASS(NestedTestObjectA, NestedTestObject) { public: DERIVED_PCLASS_CONSTRUCTOR(NestedTestObjectA, NestedTestObject) - INIT_PROPERTY(extra_value, "int") + INIT_PROPERTY(extra_value, "int", pclass::IProperty::flags::PUBLIC) { m_kind = NestedObjectKind::OBJECT_A; extra_value = 10; @@ -271,32 +271,32 @@ PCLASS(TestObject) { public: PCLASS_CONSTRUCTOR(TestObject) - INIT_PROPERTY(int4, "bi4") - INIT_PROPERTY(uint4, "bui4") - INIT_PROPERTY(int8, "char") - INIT_PROPERTY(int16, "short") - INIT_PROPERTY(int24, "s24") - INIT_PROPERTY(int32, "int") - INIT_PROPERTY(int64, "long") - INIT_PROPERTY(uint8, "unsigned char") - INIT_PROPERTY(uint16, "unsigned short") - INIT_PROPERTY(uint24, "u24") - INIT_PROPERTY(uint32, "unsigned int") - INIT_PROPERTY(uint64, "unsigned long") - INIT_PROPERTY(string, "std::string") - INIT_PROPERTY(wstring, "std::wstring") - INIT_PROPERTY(float32, "float") - INIT_PROPERTY(float64, "double") - INIT_PROPERTY(vector3d, "struct Vector3D") - INIT_PROPERTY(int_ptr, "int") - INIT_PROPERTY(int_array, "int") - INIT_PROPERTY(int_ptr_array, "int") - INIT_PROPERTY(object, "class NestedTestObjectA") - INIT_PROPERTY(object_ptr, "class NestedTestObject") - INIT_PROPERTY(null_object_ptr, "class NestedTestObject") - INIT_PROPERTY(int_vector, "int") - INIT_PROPERTY(int_ptr_vector, "int") - INIT_PROPERTY(object_ptr_vector, "class NestedTestObject") + INIT_PROPERTY(int4, "bi4", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(uint4, "bui4", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int8, "char", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int16, "short", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int24, "s24", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int32, "int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int64, "long", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(uint8, "unsigned char", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(uint16, "unsigned short", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(uint24, "u24", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(uint32, "unsigned int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(uint64, "unsigned long", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(string, "std::string", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(wstring, "std::wstring", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(float32, "float", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(float64, "double", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(vector3d, "struct Vector3D", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int_ptr, "int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int_array, "int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int_ptr_array, "int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(object, "class NestedTestObjectA", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(object_ptr, "class NestedTestObject", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(null_object_ptr, "class NestedTestObject", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int_vector, "int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(int_ptr_vector, "int", pclass::IProperty::flags::PUBLIC) + INIT_PROPERTY(object_ptr_vector, "class NestedTestObject", pclass::IProperty::flags::PUBLIC) {} // Test signed and unsigned integers with a bit length less than 8