You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
376 lines
11 KiB
C++
376 lines
11 KiB
C++
/***************************************************************************
|
|
* Copyright (C) gempa GmbH *
|
|
* All rights reserved. *
|
|
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
|
* *
|
|
* GNU Affero General Public License Usage *
|
|
* This file may be used under the terms of the GNU Affero *
|
|
* Public License version 3.0 as published by the Free Software Foundation *
|
|
* and appearing in the file LICENSE included in the packaging of this *
|
|
* file. Please review the following information to ensure the GNU Affero *
|
|
* Public License version 3.0 requirements will be met: *
|
|
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
|
* *
|
|
* Other Usage *
|
|
* Alternatively, this file may be used in accordance with the terms and *
|
|
* conditions contained in a signed written agreement between you and *
|
|
* gempa GmbH. *
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef SEISCOMP_CORE_METAPROPERTY_H
|
|
#define SEISCOMP_CORE_METAPROPERTY_H
|
|
|
|
#include <seiscomp/core/metaobject.h>
|
|
#include <seiscomp/core/strings.h>
|
|
|
|
|
|
namespace Seiscomp {
|
|
namespace Core {
|
|
|
|
namespace Generic {
|
|
|
|
|
|
class No { };
|
|
class Yes { No no[2]; };
|
|
|
|
|
|
template <typename T>
|
|
Yes isOptionalTester(boost::optional<T>*);
|
|
No isOptionalTester(void*);
|
|
|
|
|
|
template <typename T>
|
|
class is_optional {
|
|
static T* t;
|
|
|
|
public:
|
|
enum { value = sizeof(isOptionalTester(t)) == sizeof(Yes) };
|
|
};
|
|
|
|
|
|
template <typename T, int>
|
|
struct remove_optional_helper {};
|
|
|
|
template <typename T>
|
|
struct remove_optional_helper<T,0> {
|
|
typedef T type;
|
|
};
|
|
|
|
template <typename T>
|
|
struct remove_optional_helper<T,1> {
|
|
typedef typename T::value_type type;
|
|
};
|
|
|
|
|
|
template <typename T>
|
|
struct remove_optional {
|
|
typedef typename remove_optional_helper<T, is_optional<T>::value>::type type;
|
|
};
|
|
|
|
|
|
}
|
|
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <typename T>
|
|
class MetaEnumImpl : public MetaEnum {
|
|
public:
|
|
MetaEnumImpl() : MetaEnum() {}
|
|
|
|
public:
|
|
int keyCount() const { return T::Quantity; }
|
|
|
|
//! Returns the key name at a given index
|
|
const char *key(int index) const;
|
|
|
|
const char *valueToKey(int value) const;
|
|
int keyToValue(const char *key) const;
|
|
};
|
|
|
|
#define DECLARE_METAENUM(CLASS, var) Seiscomp::Core::MetaEnumImpl<CLASS> var
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <typename T>
|
|
inline const char *MetaEnumImpl<T>::key(int index) const {
|
|
return T::NameDispatcher::name(index);
|
|
}
|
|
|
|
template <typename T>
|
|
inline const char *MetaEnumImpl<T>::valueToKey(int value) const {
|
|
T tmp;
|
|
if ( !tmp.fromInt(value) )
|
|
throw ValueException("value out of bounds");
|
|
|
|
return tmp.toString();
|
|
}
|
|
|
|
template <typename T>
|
|
inline int MetaEnumImpl<T>::keyToValue(const char *key) const {
|
|
T tmp;
|
|
if ( !tmp.fromString(key) )
|
|
throw ValueException("invalid key");
|
|
|
|
return tmp.toInt();
|
|
}
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <typename T>
|
|
class MetaClassProperty : public MetaProperty {
|
|
// ------------------------------------------------------------------
|
|
// Xstruction
|
|
// ------------------------------------------------------------------
|
|
public:
|
|
MetaClassProperty() : MetaProperty() {}
|
|
|
|
MetaClassProperty(const std::string& name,
|
|
const std::string& type,
|
|
bool isArray,
|
|
bool isIndex,
|
|
bool isOptional)
|
|
: MetaProperty(name, type, isArray, true, isIndex,
|
|
isOptional, false, false, nullptr) {}
|
|
|
|
|
|
public:
|
|
BaseObject *createClass() const {
|
|
return new T();
|
|
}
|
|
};
|
|
|
|
|
|
template <template <typename T_1, typename T_2, typename T_3, typename T_4> class P,
|
|
class C, typename R1, typename T1, typename T2>
|
|
MetaPropertyHandle createProperty(R1 (C::*setter)(T1), T2 (C::*getter)()) {
|
|
typedef typename std::remove_const<
|
|
typename std::remove_cv<
|
|
typename std::remove_pointer<
|
|
typename std::remove_reference<T1>::type
|
|
>::type
|
|
>::type
|
|
>::type T;
|
|
|
|
return MetaPropertyHandle(new P<C, T, R1 (C::*)(T1), T2 (C::*)()>(setter, getter));
|
|
}
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <template <typename T_1, typename T_2, typename T_3, typename T_4> class P,
|
|
class C, typename R1, typename T1, typename T2>
|
|
MetaPropertyHandle createProperty(const std::string& name, const std::string& type,
|
|
bool isArray, bool isClass, bool isIndex,
|
|
bool isReference, bool isOptional, bool isEnum,
|
|
const MetaEnum *enumeration,
|
|
R1 (C::*setter)(T1), T2 (C::*getter)() const) {
|
|
typedef typename std::remove_const<
|
|
typename std::remove_cv<
|
|
typename std::remove_pointer<
|
|
typename std::remove_reference<T1>::type
|
|
>::type
|
|
>::type
|
|
>::type T;
|
|
|
|
MetaPropertyHandle h = MetaPropertyHandle(new P<C, T, R1 (C::*)(T1), T2 (C::*)() const>(setter, getter));
|
|
h->setInfo(name, type, isArray, isClass, isIndex, isReference, isOptional, isEnum, enumeration);
|
|
return h;
|
|
}
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <template <typename T_1, typename T_2, typename T_3, typename T_4> class P,
|
|
class C, typename R1, typename T1, typename T2>
|
|
MetaPropertyHandle createProperty(const std::string& name, const std::string& type,
|
|
bool isArray, bool isClass, bool isIndex,
|
|
bool isReference, bool isOptional, bool isEnum,
|
|
const MetaEnum *enumeration,
|
|
R1 (C::*setter)(T1), T2 (C::*getter)()) {
|
|
typedef typename std::remove_const<
|
|
typename std::remove_cv<
|
|
typename std::remove_pointer<
|
|
typename std::remove_reference<T1>::type
|
|
>::type
|
|
>::type
|
|
>::type T;
|
|
|
|
MetaPropertyHandle h = MetaPropertyHandle(new P<C, T, R1 (C::*)(T1), T2 (C::*)()>(setter, getter));
|
|
h->setInfo(name, type, isArray, isClass, isIndex, isReference, isOptional, isEnum, enumeration);
|
|
return h;
|
|
}
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <typename T, typename U, typename F1, typename F2, int>
|
|
class SimplePropertyHelper : public MetaProperty {};
|
|
|
|
template <typename T, typename U, typename F1, typename F2>
|
|
class SimplePropertyHelper<T,U,F1,F2,0> : public MetaProperty {
|
|
public:
|
|
SimplePropertyHelper(F1 setter, F2 getter)
|
|
: _setter(setter), _getter(getter) {}
|
|
|
|
bool write(BaseObject *object, MetaValue value) const {
|
|
T *target = T::Cast(object);
|
|
if ( !target ) return false;
|
|
(target->*_setter)(boost::any_cast<U>(value));
|
|
return true;
|
|
}
|
|
|
|
bool writeString(BaseObject *object, const std::string &value) const {
|
|
T *target = T::Cast(object);
|
|
if ( !target ) return false;
|
|
|
|
U tmp;
|
|
if ( !fromString(tmp, value) )
|
|
return false;
|
|
|
|
(target->*_setter)(tmp);
|
|
return true;
|
|
}
|
|
|
|
MetaValue read(const BaseObject *object) const {
|
|
const T *target = T::ConstCast(object);
|
|
if ( !target ) throw GeneralException("invalid object");
|
|
return (target->*_getter)();
|
|
}
|
|
|
|
std::string readString(const BaseObject *object) const {
|
|
const T *target = T::ConstCast(object);
|
|
if ( !target ) throw GeneralException("invalid object");
|
|
return toString((target->*_getter)());
|
|
}
|
|
|
|
private:
|
|
F1 _setter;
|
|
F2 _getter;
|
|
};
|
|
|
|
template <typename T, typename U, typename F1, typename F2>
|
|
class SimplePropertyHelper<T,U,F1,F2,1> : public MetaProperty {
|
|
public:
|
|
SimplePropertyHelper(F1 setter, F2 getter)
|
|
: _setter(setter), _getter(getter) {}
|
|
|
|
bool write(BaseObject *object, MetaValue value) const {
|
|
T *target = T::Cast(object);
|
|
if ( !target ) return false;
|
|
|
|
if ( value.empty() )
|
|
(target->*_setter)(Core::None);
|
|
else
|
|
(target->*_setter)(boost::any_cast<U>(value));
|
|
return true;
|
|
}
|
|
|
|
bool writeString(BaseObject *object, const std::string &value) const {
|
|
T *target = T::Cast(object);
|
|
if ( !target ) return false;
|
|
|
|
if ( value.empty() )
|
|
(target->*_setter)(Core::None);
|
|
else {
|
|
typename Core::Generic::remove_optional<U>::type tmp;
|
|
if ( !fromString(tmp, value) )
|
|
return false;
|
|
|
|
(target->*_setter)(tmp);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
MetaValue read(const BaseObject *object) const {
|
|
const T *target = T::ConstCast(object);
|
|
if ( !target ) throw GeneralException("invalid object");
|
|
return (target->*_getter)();
|
|
}
|
|
|
|
std::string readString(const BaseObject *object) const {
|
|
const T *target = T::ConstCast(object);
|
|
if ( !target ) throw GeneralException("invalid object");
|
|
return toString((target->*_getter)());
|
|
}
|
|
|
|
private:
|
|
F1 _setter;
|
|
F2 _getter;
|
|
};
|
|
|
|
|
|
template <typename T, typename U, typename F1, typename F2>
|
|
class SimpleProperty : public SimplePropertyHelper<T, U, F1, F2, Generic::is_optional<U>::value> {
|
|
public:
|
|
SimpleProperty(F1 setter, F2 getter)
|
|
: SimplePropertyHelper<T, U, F1, F2, Generic::is_optional<U>::value>(setter, getter) {}
|
|
};
|
|
|
|
|
|
|
|
//! Creates a simple property assuming simple get/set methods
|
|
//! \code
|
|
//! class MyClass {
|
|
//! public:
|
|
//! void setAttrib(type value);
|
|
//! type attrib() const;
|
|
//! };
|
|
//! \endcode
|
|
template <class C, typename R1, typename T1, typename T2>
|
|
MetaPropertyHandle simpleProperty(R1 (C::*setter)(T1), T2 (C::*getter)() const) {
|
|
return createProperty<SimpleProperty>(setter, getter);
|
|
}
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
template <class C, typename R1, typename T1, typename T2>
|
|
MetaPropertyHandle simpleProperty(const std::string& name, const std::string& type,
|
|
bool isArray, bool isClass, bool isIndex,
|
|
bool isReference, bool isOptional, bool isEnum,
|
|
const MetaEnum *enumeration,
|
|
R1 (C::*setter)(T1), T2 (C::*getter)() const) {
|
|
return createProperty<SimpleProperty>(name, type, isArray, isClass, isIndex,
|
|
isReference, isOptional, isEnum, enumeration,
|
|
setter, getter);
|
|
}
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endif
|