File indexing completed on 2024-10-06 06:37:55
0001 /* 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /** \file object.h 0008 * \brief Object, MetaObject and MetaProperty classes 0009 */ 0010 0011 #ifndef STEPCORE_OBJECT_H 0012 #define STEPCORE_OBJECT_H 0013 0014 #include <QBitArray> 0015 #include <QString> 0016 #include <QVariant> 0017 0018 #include <Eigen/Core> // for EIGEN_MAKE_ALIGNED_OPERATOR_NEW 0019 0020 #include "util.h" 0021 0022 namespace StepCore { 0023 0024 class MetaObject; 0025 class MetaProperty; 0026 0027 #define STEPCORE_OBJECT_NA(_className) \ 0028 private: \ 0029 typedef _className _thisType; \ 0030 static const StepCore::MetaObject _metaObject; \ 0031 static const StepCore::MetaObject* _superClasses[]; \ 0032 static const StepCore::MetaProperty _classProperties[]; \ 0033 public: \ 0034 static const StepCore::MetaObject* staticMetaObject() { return &_metaObject; } \ 0035 virtual const StepCore::MetaObject* metaObject() const { return &_metaObject; } \ 0036 private: 0037 0038 #define STEPCORE_OBJECT(_className) \ 0039 public: \ 0040 EIGEN_MAKE_ALIGNED_OPERATOR_NEW \ 0041 STEPCORE_OBJECT_NA(_className) 0042 0043 /** \ingroup reflections 0044 * \brief Root of the StepCore classes hierarchy 0045 */ 0046 class Object 0047 { 0048 STEPCORE_OBJECT(Object) 0049 0050 public: 0051 explicit Object(const QString& name = QString()): _name(name) {} 0052 virtual ~Object() {} 0053 0054 /** Returns name of the object */ 0055 const QString& name() const { return _name; } 0056 /** Set name of the object */ 0057 void setName(const QString& name) { _name = name; } 0058 0059 protected: 0060 QString _name; 0061 }; 0062 0063 /** \ingroup reflections 0064 * \brief Meta-information about property 0065 */ 0066 class MetaProperty 0067 { 0068 public: 0069 enum { 0070 READABLE = 1, ///< Property is readable 0071 WRITABLE = 2, ///< Property is writable 0072 STORED = 4, ///< Property should be stored in file 0073 DYNAMIC = 32, ///< Variable changes during simulation or changes of other properties 0074 SIDEEFFECTS = 64 ///< Changing this property has side-effects 0075 /// (changes in other dynamic or non-dynamic properties) 0076 /// @note Do not set this together with STORED 0077 }; 0078 0079 public: 0080 MetaProperty(): 0081 _name(QLatin1String("")), _units(QString()), _description(QLatin1String("")), 0082 _flags(0), _userTypeId(0), _readVariant(nullptr), _writeVariant(nullptr), 0083 _readString(nullptr), _writeString(nullptr), _initialized(false) {} 0084 0085 /*MetaProperty(const MetaProperty& p): 0086 _name(p._name), _units(p._units), _flags(p.flags), _userTypeId(p._userTypeId), 0087 _readVariant(p._readVariant), _writeVariant(p._writeVariant), 0088 _readString(p._readString), _writeString(p._writeString) {}*/ 0089 0090 MetaProperty(const QString& name, const QString& units, 0091 const QString& description, int flags, int userType, 0092 QVariant (*const readVariant)(const Object*), 0093 bool (*const writeVariant)(Object* obj, const QVariant& v), 0094 QString (*const readString)(const Object* obj), 0095 bool (*const writeString)(Object* obj, const QString& v)) 0096 : _name(name), _units(units), _description(description), 0097 _flags(flags), _userTypeId(userType), 0098 _readVariant(readVariant), _writeVariant(writeVariant), 0099 _readString(readString), _writeString(writeString), _initialized(false) {} 0100 0101 /** Returns property name */ 0102 const QString& name() const { return _name; } 0103 /** Returns property units (if appropriate) */ 0104 const QString& units() const { return _units; } 0105 /** Returns property description */ 0106 const QString& description() const { return _description; } 0107 /** Returns property flags */ 0108 int flags() const { return _flags; } 0109 0110 /** Returns translated property name */ 0111 const QString& nameTr() const { tryInit(); return _nameTr; } 0112 /** Returns translated property units (if appropriate) */ 0113 const QString& unitsTr() const { tryInit(); return _unitsTr; } 0114 /** Returns translated property description */ 0115 const QString& descriptionTr() const { tryInit(); return _descriptionTr; } 0116 0117 /** Returns property userType (see QMetaProperty) */ 0118 int userTypeId() const { return _userTypeId; } 0119 /** Read property as QVariant */ 0120 QVariant readVariant(const Object* obj) const { return _readVariant(obj); } 0121 /** Write property as QVariant. \return true on success */ 0122 bool writeVariant(Object* obj, const QVariant& v) const { return _writeVariant(obj, v); } 0123 0124 /** Read property as string */ 0125 QString readString(const Object* obj) const { return _readString(obj); } 0126 /** Write property as string. \return true on success */ 0127 bool writeString(Object* obj, const QString& s) const { return _writeString(obj, s); } 0128 0129 /** Returns true if this property is readable */ 0130 bool isReadable() const { return _flags & READABLE; } 0131 /** Returns true if this property is writable */ 0132 bool isWritable() const { return _flags & WRITABLE; } 0133 /** Returns true if this property should be stored */ 0134 bool isStored() const { return _flags & STORED; } 0135 /** Returns true if this property is dynamic (changes during simulation) */ 0136 bool isDynamic() const { return _flags & DYNAMIC; } 0137 /** Returns true if this property has side-effects 0138 * (changes in other dynamic or non-dynamic properties) */ 0139 bool hasSideEffects() const { return _flags & SIDEEFFECTS; } 0140 0141 public: 0142 const QString _name; 0143 const QString _units; 0144 const QString _description; 0145 const int _flags; 0146 const int _userTypeId; 0147 QVariant (*const _readVariant)(const Object* obj); 0148 bool (*const _writeVariant)(Object* obj, const QVariant& v); 0149 QString (*const _readString)(const Object* obj); 0150 bool (*const _writeString)(Object* obj, const QString& v); 0151 0152 mutable bool _initialized; 0153 mutable QString _nameTr; 0154 mutable QString _unitsTr; 0155 mutable QString _descriptionTr; 0156 0157 public: 0158 void init() const; 0159 void tryInit() const { if(!_initialized) init(); } 0160 }; 0161 0162 /** \ingroup reflections 0163 * \brief Meta-information about class 0164 */ 0165 class MetaObject 0166 { 0167 public: 0168 enum { 0169 ABSTRACT = 1 ///< Class is abstract 0170 }; 0171 0172 public: 0173 /** Returns class name */ 0174 const QString& className() const { return _className; } 0175 /** Returns class description */ 0176 const QString& description() const { return _description; } 0177 0178 /** Returns translated class name */ 0179 const QString& classNameTr() const { tryInit(); return _classNameTr; } 0180 /** Returns translated class description */ 0181 const QString& descriptionTr() const { tryInit(); return _descriptionTr; } 0182 0183 /** Returns class id */ 0184 int classId() const { tryInit(); return _classId; } 0185 0186 /** Returns true if class is abstract */ 0187 bool isAbstract() const { return _flags & ABSTRACT; } 0188 /** Creates new object of this class */ 0189 Object* newObject() const { return _newObject(); } 0190 /** Creates a copy of given object */ 0191 Object* cloneObject(const Object& obj) const { return _cloneObject(obj); } 0192 0193 /** Returns number of direct bases */ 0194 int superClassCount() const { return _superClassCount; } 0195 /** Returns direct base */ 0196 const MetaObject* superClass(int n) const { return _superClasses[n]; } 0197 /** Returns true if this class inherits class described by obj */ 0198 bool inherits(const MetaObject* obj) const; 0199 /** Returns true if this class inherits class T */ 0200 template<class T> bool inherits() const { return inherits(T::staticMetaObject()); } 0201 /** Returns true if this class inherits class T */ 0202 template<class T> bool inherits(T*) const { return inherits(T::staticMetaObject()); } 0203 /** Returns true if this class inherits class named name 0204 * \note Due to technical reason this is much slower then 0205 * inherits(const MetaObject*) function */ 0206 bool inherits(const char* name) const; 0207 0208 /** Returns number of non-inherited properties */ 0209 int classPropertyCount() const { return _classPropertyCount; } 0210 /** Returns non-inherited property */ 0211 const MetaProperty* classProperty(int n) const { return &_classProperties[n]; } 0212 0213 /** Returns property count */ 0214 int propertyCount() const { tryInit(); return _allPropertyCount; } 0215 /** Returns property by index */ 0216 const MetaProperty* property(int n) const { tryInit(); return _allProperties[n]; } 0217 /** Returns property by name */ 0218 const MetaProperty* property(const QString& name) const; 0219 0220 public: 0221 void init() const; 0222 void tryInit() const { if(!_initialized) init(); } 0223 void copyProperties(const MetaProperty** dest) const; 0224 0225 const QString _className; 0226 const QString _description; 0227 const int _flags; 0228 Object* (*const _newObject)(); 0229 Object* (*const _cloneObject)(const Object&); 0230 0231 const MetaObject** const _superClasses; 0232 const int _superClassCount; 0233 const MetaProperty* const _classProperties; 0234 const int _classPropertyCount; 0235 0236 mutable bool _initialized; 0237 mutable const MetaProperty** _allProperties; 0238 mutable int _allPropertyCount; 0239 0240 mutable int _classId; 0241 mutable QBitArray _allSuperClassIds; 0242 0243 mutable QString _classNameTr; 0244 mutable QString _descriptionTr; 0245 0246 static int s_classIdCount; 0247 }; 0248 0249 /** Casts between pointers to Object */ 0250 template<class _Dst, class _Src> // XXX: implement it better 0251 _Dst stepcore_cast(_Src src) { 0252 if(!src || !src->metaObject()->template inherits(_Dst())) return NULL; 0253 return static_cast<_Dst>(src); 0254 } 0255 0256 /* Helper functions TODO: namespace of class ? */ 0257 0258 template<typename T> inline QString typeToString(const T& v) { 0259 return QVariant::fromValue(v).toString(); 0260 } 0261 0262 template<typename T> inline T stringToType(const QString& s, bool* ok) { 0263 QVariant v(s); *ok = v.convert((QVariant::Type) qMetaTypeId<T>()); 0264 return v.value<T>(); 0265 } 0266 0267 template<typename T> inline QVariant typeToVariant(const T& v) { 0268 return QVariant::fromValue(v); 0269 } 0270 0271 template<typename T> inline T variantToType(const QVariant& v, bool* ok) { 0272 if(v.userType() == qMetaTypeId<T>()) { *ok = true; return v.value<T>(); } 0273 QVariant vc(v); *ok = vc.convert((QVariant::Type)qMetaTypeId<T>()); 0274 return vc.value<T>(); 0275 } 0276 0277 template<class C, typename T> 0278 struct MetaPropertyHelper { 0279 0280 /* read */ 0281 template<T (C::*_read)() const> static QVariant read(const Object* obj) { 0282 return typeToVariant<T>((dynamic_cast<const C*>(obj)->*_read)()); 0283 } 0284 template<const T& (C::*_read)() const> static QVariant read(const Object* obj) { 0285 return typeToVariant<T>((dynamic_cast<const C*>(obj)->*_read)()); 0286 } 0287 0288 /* write */ 0289 template<void (C::*_write)(T)> static bool write(Object* obj, const QVariant& v) { 0290 bool ok; T tv = variantToType<T>(v, &ok); if(!ok) return false; 0291 (dynamic_cast<C*>(obj)->*_write)(tv); return true; 0292 } 0293 template<void (C::*_write)(const T&)> static bool write(Object* obj, const QVariant& v) { 0294 bool ok; T tv = variantToType<T>(v, &ok); if(!ok) return false; 0295 (dynamic_cast<C*>(obj)->*_write)(tv); return true; 0296 } 0297 template<bool (C::*_write)(T)> static bool write(Object* obj, const QVariant& v) { 0298 bool ok; T tv = variantToType<T>(v, &ok); if(!ok) return false; 0299 return (dynamic_cast<C*>(obj)->*_write)(tv); 0300 } 0301 template<bool (C::*_write)(const T&)> static bool write(Object* obj, const QVariant& v) { 0302 bool ok; T tv = variantToType<T>(v, &ok); if(!ok) return false; 0303 return (dynamic_cast<C*>(obj)->*_write)(tv); 0304 } 0305 0306 /* readString */ 0307 template<T (C::*_read)() const> static QString readString(const Object* obj) { 0308 return typeToString<T>((dynamic_cast<const C*>(obj)->*_read)()); 0309 } 0310 template<const T& (C::*_read)() const> static QString readString(const Object* obj) { 0311 return typeToString<T>((dynamic_cast<const C*>(obj)->*_read)()); 0312 } 0313 0314 /* writeString */ 0315 template<void (C::*_write)(T)> static bool writeString(Object* obj, const QString& s) { 0316 bool ok; T tv = stringToType<T>(s, &ok); if(!ok) return false; 0317 (dynamic_cast<C*>(obj)->*_write)(tv); return true; 0318 } 0319 template<void (C::*_write)(const T&)> static bool writeString(Object* obj, const QString& s) { 0320 bool ok; T tv = stringToType<T>(s, &ok); if(!ok) return false; 0321 (dynamic_cast<C*>(obj)->*_write)(tv); return true; 0322 } 0323 template<bool (C::*_write)(T)> static bool writeString(Object* obj, const QString& s) { 0324 bool ok; T tv = stringToType<T>(s, &ok); if(!ok) return false; 0325 return (dynamic_cast<C*>(obj)->*_write)(tv); 0326 } 0327 template<bool (C::*_write)(const T&)> static bool writeString(Object* obj, const QString& s) { 0328 bool ok; T tv = stringToType<T>(s, &ok); if(!ok) return false; 0329 return (dynamic_cast<C*>(obj)->*_write)(tv); 0330 } 0331 0332 static QVariant readNull(const Object* obj) { Q_UNUSED(obj) return QVariant(); } 0333 static QString readStringNull(const Object* obj) { Q_UNUSED(obj) return QString(); } 0334 static bool writeNull(Object* obj, const QVariant& v) { Q_UNUSED(obj) Q_UNUSED(v) return false; } 0335 static bool writeStringNull(Object* obj, const QString& s) { Q_UNUSED(obj) Q_UNUSED(s) return false; } 0336 }; 0337 0338 template<typename Class, int N> 0339 struct MetaObjectHelper { 0340 static Object* newObjectHelper() { return new Class(); } 0341 static Object* cloneObjectHelper(const Object& obj) { 0342 return new Class(static_cast<const Class&>(obj)); 0343 } 0344 }; 0345 0346 template<class Class> 0347 struct MetaObjectHelper<Class, MetaObject::ABSTRACT> { 0348 static Object* newObjectHelper() { return nullptr; } 0349 static Object* cloneObjectHelper(const Object& obj) { Q_UNUSED(obj) return nullptr; } 0350 }; 0351 0352 #define STEPCORE_FROM_UTF8(str) QString::fromUtf8(str) 0353 0354 #define STEPCORE_UNITS_NULL QString() 0355 #define STEPCORE_UNITS_1 QString("") 0356 0357 #define _STEPCORE_PROPERTY_NULL StepCore::MetaProperty() 0358 0359 #define STEPCORE_META_OBJECT(_className, _classNameNoop, _description, _flags, __superClasses, __properties) \ 0360 const StepCore::MetaProperty _className::_classProperties[] = { _STEPCORE_PROPERTY_NULL, __properties }; \ 0361 const StepCore::MetaObject* _className::_superClasses[] = { nullptr, __superClasses }; \ 0362 const StepCore::MetaObject _className::_metaObject = { \ 0363 QString(STEPCORE_STRINGIFY(_className)), QString(_description), _flags, \ 0364 StepCore::MetaObjectHelper<_className, _flags & StepCore::MetaObject::ABSTRACT>::newObjectHelper, \ 0365 StepCore::MetaObjectHelper<_className, _flags & StepCore::MetaObject::ABSTRACT>::cloneObjectHelper, \ 0366 _superClasses+1, sizeof(_superClasses)/sizeof(*_superClasses)-1, \ 0367 _classProperties+1, sizeof(_classProperties)/sizeof(*_classProperties)-1, false, nullptr, 0, 0, QBitArray(), "", "" }; 0368 0369 #define STEPCORE_SUPER_CLASS(_className) _className::staticMetaObject(), 0370 0371 #define STEPCORE_PROPERTY_RF(_type, _name, _nameNoop, _units, _description, _flags, _read) \ 0372 StepCore::MetaProperty( STEPCORE_STRINGIFY(_name), _units, _description, \ 0373 StepCore::MetaProperty::READABLE | _flags, qMetaTypeId<_type>(), \ 0374 StepCore::MetaPropertyHelper<_thisType, _type>::read<&_thisType::_read>, \ 0375 StepCore::MetaPropertyHelper<_thisType, _type>::writeNull, \ 0376 StepCore::MetaPropertyHelper<_thisType, _type>::readString<&_thisType::_read>, \ 0377 StepCore::MetaPropertyHelper<_thisType, _type>::writeStringNull ), 0378 0379 #define STEPCORE_PROPERTY_RWF(_type, _name, _nameNoop, _units, _description, _flags, _read, _write) \ 0380 StepCore::MetaProperty( STEPCORE_STRINGIFY(_name), _units, _description, \ 0381 StepCore::MetaProperty::READABLE | StepCore::MetaProperty::WRITABLE | _flags, \ 0382 qMetaTypeId<_type>(), \ 0383 StepCore::MetaPropertyHelper<_thisType, _type>::read<&_thisType::_read>, \ 0384 StepCore::MetaPropertyHelper<_thisType, _type>::write<&_thisType::_write>, \ 0385 StepCore::MetaPropertyHelper<_thisType, _type>::readString<&_thisType::_read>, \ 0386 StepCore::MetaPropertyHelper<_thisType, _type>::writeString<&_thisType::_write> ), 0387 0388 #define STEPCORE_PROPERTY_R(_type, _name, _nameNoop, _units, _description, _read) \ 0389 STEPCORE_PROPERTY_RF(_type, _name, _nameNoop, _units, _description, 0, _read) 0390 0391 #define STEPCORE_PROPERTY_RW(_type, _name, _nameNoop, _units, _description, _read, _write) \ 0392 STEPCORE_PROPERTY_RWF(_type, _name, _nameNoop, _units, _description, \ 0393 StepCore::MetaProperty::STORED, _read, _write) 0394 0395 #define STEPCORE_PROPERTY_R_D(_type, _name, _nameNoop, _units, _description, _read) \ 0396 STEPCORE_PROPERTY_RF(_type, _name, _nameNoop, _units, _description, StepCore::MetaProperty::DYNAMIC, _read) 0397 0398 #define STEPCORE_PROPERTY_RW_D(_type, _name, _nameNoop, _units, _description, _read, _write) \ 0399 STEPCORE_PROPERTY_RWF(_type, _name, _nameNoop, _units, _description, \ 0400 StepCore::MetaProperty::STORED | StepCore::MetaProperty::DYNAMIC, _read, _write) 0401 0402 } // namespace StepCore 0403 0404 #endif 0405