refactor: standardize object type identification using uLibTypeMacro and update serialization macros

This commit is contained in:
AndreaRigoni
2026-04-02 10:33:14 +00:00
parent a1c5fc2600
commit 4435776484
32 changed files with 229 additions and 99 deletions

View File

@@ -28,6 +28,8 @@
#include <boost/archive/detail/basic_pointer_iserializer.hpp>
#include <boost/archive/detail/basic_pointer_oserializer.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <cstring>
#include <iostream>
#include <boost/archive/text_iarchive.hpp>
@@ -309,18 +311,32 @@ namespace Archive {
////////////////////////////////////////////////////////////////////////////////
// XML //
// ULIB_SERIALIZATION_VERSION should be get from the build system
#ifndef ULIB_SERIALIZATION_VERSION
#define ULIB_SERIALIZATION_VERSION "0.0"
#endif
class xml_iarchive : public boost::archive::xml_iarchive_impl<xml_iarchive> {
typedef xml_iarchive Archive;
typedef boost::archive::xml_iarchive_impl<Archive> base;
unsigned int m_flags;
// give serialization implementation access to this class
friend class boost::archive::detail::interface_iarchive<Archive>;
friend class boost::archive::basic_xml_iarchive<Archive>;
friend class boost::archive::load_access;
public:
xml_iarchive(std::istream &is, unsigned int flags = 0)
: xml_iarchive_impl<xml_iarchive>(is, flags) {}
: boost::archive::xml_iarchive_impl<xml_iarchive>(
is, flags | boost::archive::no_header), m_flags(flags) {
if (0 == (flags & boost::archive::no_header)) {
std::string line;
std::getline(is, line); // <?xml ... ?>
std::getline(is, line); // <!DOCTYPE ...>
std::getline(is, line); // <ulib_serialization ...>
}
}
using basic_xml_iarchive::load_override;
@@ -368,14 +384,31 @@ class xml_oarchive : public boost::archive::xml_oarchive_impl<xml_oarchive> {
typedef xml_oarchive Archive;
typedef boost::archive::xml_oarchive_impl<Archive> base;
unsigned int m_flags;
// give serialization implementation access to this class
friend class boost::archive::detail::interface_oarchive<Archive>;
friend class boost::archive::basic_xml_oarchive<Archive>;
friend class boost::archive::save_access;
public:
xml_oarchive(std::ostream &os, unsigned int flags = 0)
: boost::archive::xml_oarchive_impl<xml_oarchive>(os, flags) {}
: boost::archive::xml_oarchive_impl<xml_oarchive>(
os, flags | boost::archive::no_header), m_flags(flags) {
if (0 == (flags & boost::archive::no_header)) {
this->This()->put(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n");
this->This()->put("<!DOCTYPE ulib_serialization>\n");
this->This()->put("<ulib_serialization signature=\"serialization::archive\" ");
this->write_attribute("version", (const char *)ULIB_SERIALIZATION_VERSION);
this->This()->put(">\n");
}
}
virtual ~xml_oarchive() {
if (0 == (m_flags & boost::archive::no_header)) {
this->This()->put("</ulib_serialization>\n");
}
}
using basic_xml_oarchive::save_override;
@@ -397,8 +430,6 @@ public:
// Do not save any human decoration string //
// basic_text_oprimitive::save(str);
}
virtual ~xml_oarchive() {}
};
// typedef boost::archive::detail::polymorphic_oarchive_route<

View File

@@ -58,6 +58,7 @@ if(USE_CUDA)
endif()
target_link_libraries(${libname} ${LIBRARIES})
target_compile_definitions(${libname} PUBLIC ULIB_SERIALIZATION_VERSION="${PROJECT_VERSION}")
install(TARGETS ${libname}
EXPORT "uLibTargets"

View File

@@ -79,6 +79,7 @@ void Object::RegisterDynamicProperty(PropertyBase* prop) {
if (prop) {
for (auto* existing : d->m_DynamicProperties) {
if (existing == prop) return;
if (existing->GetQualifiedName() == prop->GetQualifiedName()) return;
}
d->m_DynamicProperties.push_back(prop);
}

View File

@@ -78,7 +78,8 @@ public:
Object(const Object &copy);
virtual ~Object();
virtual const char * GetClassName() const { return "Object"; }
virtual const char * GetClassName() const { return type_name(); }
virtual const char * type_name() const { return "Object"; }
const std::string& GetInstanceName() const;
void SetInstanceName(const std::string& name);

View File

@@ -14,7 +14,7 @@ public:
ObjectsContext();
virtual ~ObjectsContext();
virtual const char * GetClassName() const { return "ObjectsContext"; }
uLibTypeMacro(ObjectsContext, Object)
virtual ObjectsContext* GetChildren() override { return this; }
/**

View File

@@ -54,13 +54,13 @@ public:
virtual void Updated() override { ULIB_SIGNAL_EMIT(PropertyBase::Updated); }
// Serialization support for different uLib archives
virtual void serialize(Archive::xml_oarchive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::xml_iarchive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::text_oarchive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::text_iarchive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::hrt_oarchive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::hrt_iarchive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::log_archive & ar, const unsigned int version) = 0;
virtual void serialize(Archive::xml_oarchive & ar, const unsigned int version) override = 0;
virtual void serialize(Archive::xml_iarchive & ar, const unsigned int version) override = 0;
virtual void serialize(Archive::text_oarchive & ar, const unsigned int version) override = 0;
virtual void serialize(Archive::text_iarchive & ar, const unsigned int version) override = 0;
virtual void serialize(Archive::hrt_oarchive & ar, const unsigned int version) override = 0;
virtual void serialize(Archive::hrt_iarchive & ar, const unsigned int version) override = 0;
virtual void serialize(Archive::log_archive & ar, const unsigned int version) override = 0;
};
@@ -407,12 +407,32 @@ private:
/**
* @brief Convenience macro to automatically activate and register all HRP members
* @brief Convenience macro to automatically activate and register all HRP members
* as uLib properties. Usage: ULIB_ACTIVATE_PROPERTIES(obj)
*/
#define ULIB_ACTIVATE_PROPERTIES(obj) \
{ uLib::Archive::property_register_archive _ar_tmp(&(obj)); _ar_tmp & (obj); }
/**
* @brief Declares a private member that automatically calls ULIB_ACTIVATE_PROPERTIES
* in every constructor of the class. Place this macro as the last declaration
* inside the class body (before the closing brace).
*
* Usage: ULIB_DECLARE_PROPERTIES(ClassName)
*
* This replaces per-constructor ULIB_ACTIVATE_PROPERTIES(*this) calls.
* RegisterDynamicProperty deduplicates by qualified name, so re-registration
* from inherited activators in a hierarchy is safe.
*/
#define ULIB_DECLARE_PROPERTIES(SelfType) \
private: \
struct _PropActivator { \
_PropActivator(SelfType* self) { \
uLib::Archive::property_register_archive _ar(self); \
_ar & *self; \
} \
} _prop_activator{this};
} // namespace Archive
} // namespace uLib

View File

@@ -309,6 +309,8 @@ namespace uLib {
#define HRP5(name, data, units, min, max) boost::serialization::make_hrp(name, data, units).range(min, max)
#define HRP6(name, data, units, default, min, max) boost::serialization::make_hrp(name, data, units).set_default(default).range(min, max)
#define HRPE(name, data, labels) boost::serialization::make_hrp_enum(name, data, labels)
// LEFT FOR BACKWARD COMPATIBILITY
#define HRPU(name, units) boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), name, units)
@@ -349,7 +351,7 @@ using boost::serialization::make_hrp_enum;
#define ULIB_SERIALIZE_OBJECT(_Ob, ...) \
_ULIB_DETAIL_UNINTRUSIVE_SERIALIZE_OBJECT(_Ob, __VA_ARGS__)
#define AR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name)
#define HR(_name) _ULIB_DETAIL_UNINTRUSIVE_AR_(_name)
#define HR(_name) _ULIB_DETAIL_UNINTRUSIVE_HR_(_name)
#endif
#define ULIB_SERIALIZE_ACCESS \
@@ -362,14 +364,14 @@ using boost::serialization::make_hrp_enum;
#define ULIB_CLASS_EXPORT_OBJECT_KEY(_FullNamespaceClass) \
BOOST_CLASS_EXPORT_KEY(_FullNamespaceClass)
#define _SERIALIZE_IMPL_SEQ \
(uLib::Archive::text_iarchive)(uLib::Archive::text_oarchive)( \
uLib::Archive:: \
hrt_iarchive)(uLib::Archive:: \
hrt_oarchive)(uLib::Archive:: \
xml_iarchive)(uLib::Archive:: \
xml_oarchive)(uLib::Archive:: \
log_archive)
#define _SERIALIZE_IMPL_SEQ \
(uLib::Archive::text_iarchive) \
(uLib::Archive::text_oarchive) \
(uLib::Archive::hrt_iarchive) \
(uLib::Archive::hrt_oarchive) \
(uLib::Archive::xml_iarchive) \
(uLib::Archive::xml_oarchive) \
(uLib::Archive::log_archive)
/** Solving virtual class check problem */
#define _ULIB_DETAIL_SPECIALIZE_IS_VIRTUAL_BASE(_Base, _Derived) \
@@ -549,7 +551,8 @@ using boost::serialization::make_hrp_enum;
void serialize_parents(ArchiveT &ar, _Ob &ob, const unsigned int v) { \
/* PP serialize */ BOOST_PP_SEQ_FOR_EACH( \
_UNAR_OP, ob, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))); \
/* MPL serialize */ /*uLib::mpl::for_each<_Ob::BaseList>(uLib::detail::Serializable::serialize_baseobject<_Ob,ArchiveT>(ob,ar) );*/ } \
/* MPL serialize */ /*uLib::mpl::for_each<_Ob::BaseList> \
(uLib::detail::Serializable::serialize_baseobject<_Ob,ArchiveT>(ob,ar) );*/ }\
template <class ArchiveT> \
inline void load_construct_data(ArchiveT &ar, _Ob *ob, \
const unsigned int file_version) { \
@@ -572,10 +575,18 @@ using boost::serialization::make_hrp_enum;
_SERIALIZE_IMPL_SEQ) \
template <class ArchiveT> \
void boost::serialization::access2<_Ob>::save_override( \
ArchiveT &ar, _Ob &ob, const unsigned int version)
ArchiveT &ar, _Ob &ob, const unsigned int version)
#define _ULIB_DETAIL_UNINTRUSIVE_AR_(name) \
boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), ob.name)
#define _ULIB_DETAIL_UNINTRUSIVE_HR_(name) \
boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), ob.name)
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

View File

@@ -76,8 +76,9 @@ public:
ULIB_SERIALIZABLE_OBJECT(TestObject2)
ULIB_SERIALIZE_OBJECT(TestObject2, TestObject) {
// std::cout << "Serializing TestObject2" << std::endl;
ar & boost::serialization::make_hrp("value2", ob.m_Value2, "mm").set_default(1.);
std::cout << "Serializing TestObject2" << std::endl;
// ar & boost::serialization::make_hrp("value2", ob.m_Value2, "mm").set_default(1.);
ar & HRP("value2", ob.m_Value2, "mm").set_default(1.);
}

View File

@@ -8,13 +8,12 @@ using namespace uLib;
class TestObject : public Object {
public:
uLibTypeMacro(TestObject, Object)
TestObject() : Object(),
IntProp(this, "IntProp", 10),
StringProp(this, "StringProp", "Initial")
{}
virtual const char* GetClassName() const override { return "TestObject"; }
Property<int> IntProp;
Property<std::string> StringProp;
};

View File

@@ -9,10 +9,9 @@ using namespace uLib;
class TestObject : public Object {
public:
uLibTypeMacro(TestObject, Object)
TestObject() : Object() {}
virtual const char* GetClassName() const override { return "TestObject"; }
// Use new typedefs
StringProperty StringProp = StringProperty(this, "StringProp", "Initial");
IntProperty IntProp = IntProperty(this, "IntProp", 42);