Files
uLib/src/Core/Object.cpp
2026-04-01 11:13:28 +00:00

284 lines
8.6 KiB
C++

/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#include "config.h"
#include "Object.h"
#include "Vector.h"
#include "boost/archive/polymorphic_binary_iarchive.hpp"
#include "boost/archive/polymorphic_binary_oarchive.hpp"
#include "boost/archive/polymorphic_text_iarchive.hpp"
#include "boost/archive/polymorphic_text_oarchive.hpp"
#include "boost/archive/polymorphic_xml_iarchive.hpp"
#include "boost/archive/polymorphic_xml_oarchive.hpp"
#include <vector>
#include "Property.h"
namespace uLib {
const char *Version::PackageName = PACKAGE_NAME;
const char *Version::VersionNumber = PACKAGE_VERSION;
const char *Version::Release = "x"; // SVN_REVISION;
////////////////////////////////////////////////////////////////////////////////
// Object Private //
class ObjectPrivate {
public:
struct Signal {
GenericMFPtr sigptr;
std::string sigstr;
SignalBase *signal;
};
struct Slot {
GenericMFPtr sloptr;
std::string slostr;
};
std::string m_InstanceName;
std::vector<Signal> sigv;
std::vector<Slot> slov;
std::vector<PropertyBase*> m_Properties;
std::vector<PropertyBase*> m_DynamicProperties;
bool m_SignalsBlocked;
};
// Implementations of Property methods
void Object::RegisterProperty(PropertyBase* prop) {
if (prop) {
d->m_Properties.push_back(prop);
}
}
void Object::RegisterDynamicProperty(PropertyBase* prop) {
if (prop) {
for (auto* existing : d->m_DynamicProperties) {
if (existing == prop) return;
}
d->m_DynamicProperties.push_back(prop);
}
}
const std::vector<PropertyBase*>& Object::GetProperties() const {
return d->m_Properties;
}
PropertyBase* Object::GetProperty(const std::string& name) const {
for (auto* p : d->m_Properties) {
if (p->GetName() == name || p->GetQualifiedName() == name) return p;
}
for (auto* p : d->m_DynamicProperties) {
if (p->GetName() == name || p->GetQualifiedName() == name) return p;
}
return nullptr;
}
void Object::NotifyPropertiesUpdated() {
for (auto* p : d->m_Properties) p->Updated();
for (auto* p : d->m_DynamicProperties) p->Updated();
}
// In Object.h, the template serialize needs to be updated to call property serialization.
// However, since Object::serialize is a template in the header, we might need a helper here.
template <class ArchiveT>
void Object::serialize(ArchiveT &ar, const unsigned int version) {
ar & boost::serialization::make_nvp("InstanceName", d->m_InstanceName);
for (auto* prop : d->m_Properties) {
prop->serialize(ar, version);
}
}
void Object::Updated() { ULIB_SIGNAL_EMIT(Object::Updated); }
void Object::PropertyUpdated() { ULIB_SIGNAL_EMIT(Object::PropertyUpdated); }
template <class ArchiveT>
void Object::save_override(ArchiveT &ar, const unsigned int version) {}
// Explicitly instantiate for all uLib archives
template void Object::serialize(Archive::xml_oarchive &, const unsigned int);
template void Object::serialize(Archive::xml_iarchive &, const unsigned int);
template void Object::serialize(Archive::text_oarchive &, const unsigned int);
template void Object::serialize(Archive::text_iarchive &, const unsigned int);
template void Object::serialize(Archive::hrt_oarchive &, const unsigned int);
template void Object::serialize(Archive::hrt_iarchive &, const unsigned int);
template void Object::serialize(Archive::log_archive &, const unsigned int);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// OBJECT IMPLEMENTATION
Object::Object() : d(new ObjectPrivate) {
d->m_SignalsBlocked = false;
}
Object::Object(const Object &copy) : d(new ObjectPrivate) {
if (copy.d) {
d->m_InstanceName = copy.d->m_InstanceName;
d->m_SignalsBlocked = copy.d->m_SignalsBlocked;
}
}
Object& Object::operator=(const Object &other) {
// Intentionally does NOT share 'd'. Each Object owns its own ObjectPrivate.
// Without this, the compiler-generated operator= would copy the 'd' pointer,
// causing two objects to share the same ObjectPrivate. When both are
// destroyed, 'd' would be deleted twice, corrupting the heap.
if (this != &other && other.d) {
d->m_InstanceName = other.d->m_InstanceName;
d->m_SignalsBlocked = other.d->m_SignalsBlocked;
}
return *this;
}
Object::~Object() {
for (auto* p : d->m_DynamicProperties) {
delete p;
}
delete d;
}
void Object::DeepCopy(const Object &copy) {
if (this == &copy) return;
if (copy.d) d->m_InstanceName = copy.d->m_InstanceName;
std::cout << "Object DeepCopy: from d=" << copy.d << " to d=" << d << std::endl;
// Note: signals, slots and properties are intentionally not copied
// to maintain instance uniquely and avoid duplicate registrations.
this->Updated();
}
void Object::SaveXml(std::ostream &os, Object &ob) {
Archive::xml_oarchive ar(os);
ar << boost::serialization::make_nvp("Object", ob);
}
void Object::LoadXml(std::istream &is, Object &ob) {
Archive::xml_iarchive ar(is);
ar >> boost::serialization::make_nvp("Object", ob);
}
// FINIRE
void Object::SaveConfig(std::ostream &os, int version) {
Archive::xml_oarchive ar(os);
}
void Object::LoadConfig(std::istream &is, int version) {
Archive::xml_iarchive ar(is);
}
void Object::PrintSelf(std::ostream &o) const {
o << "OBJECT signals: ------------------\n";
for (const auto& sig : d->sigv) {
o << " signal:[ " << sig.sigstr << " ]\n";
}
o << "--------------------------------------\n\n";
}
bool Object::addSignalImpl(SignalBase *sig, GenericMFPtr fptr,
const char *name) {
ObjectPrivate::Signal s = {fptr, std::string(name), sig};
d->sigv.push_back(s);
return true;
}
bool Object::addSlotImpl(GenericMFPtr fptr, const char *name) {
ObjectPrivate::Slot s = {fptr, std::string(name)};
d->slov.push_back(s);
return true;
}
SignalBase *Object::findSignalImpl(const GenericMFPtr &fptr) const {
for (int i = 0; i < d->sigv.size(); ++i) {
if (d->sigv[i].sigptr == fptr)
return d->sigv[i].signal;
}
return NULL;
}
SignalBase *Object::findSignalImpl(const char *name) const {
std::string in(name);
for (int i = 0; i < d->sigv.size(); ++i) {
if (d->sigv[i].sigstr == in)
return d->sigv[i].signal;
}
return NULL;
}
GenericMFPtr *Object::findSlotImpl(const char *name) const {
std::string in(name);
for (int i = 0; i < d->slov.size(); ++i) {
if (d->slov[i].slostr == in)
return &d->slov[i].sloptr;
}
return NULL;
}
const std::string& Object::GetInstanceName() const {
return d->m_InstanceName;
}
void Object::SetInstanceName(const std::string& name) {
d->m_InstanceName = name;
this->Updated();
}
bool Object::blockSignals(bool block) {
bool old = d->m_SignalsBlocked;
d->m_SignalsBlocked = block;
return old;
}
bool Object::signalsBlocked() const {
return d->m_SignalsBlocked;
}
// std::ostream &
// operator << (std::ostream &os, uLib::Object &ob)
// {
// uLib::Object *op = &ob;
// uLib::Archive::hrt_oarchive (os) << op;
// return os;
// }
// std::ostream &
// operator << (std::ostream &os, uLib::Object *ob)
// {
// uLib::Archive::hrt_oarchive(os) << ob;
// return os;
// }
// std::istream &
// operator >> (std::istream &is, uLib::Object &ob)
// {
// // uLib::Object *op = &ob;
// uLib::Archive::hrt_iarchive(is) >> ob;
// return is;
// }
} // namespace uLib