187 lines
5.4 KiB
C++
187 lines
5.4 KiB
C++
/*! \file pivariantsimple.h
|
||
* \ingroup Core
|
||
* \brief
|
||
* \~english Simple variant type
|
||
* \~russian Простой вариативный тип
|
||
*/
|
||
/*
|
||
PIP - Platform Independent Primitives
|
||
Variant simple type
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program 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 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#ifndef PIVARIANTSIMPLE_H
|
||
#define PIVARIANTSIMPLE_H
|
||
|
||
#include "pistring.h"
|
||
#include <typeinfo>
|
||
#ifdef MICRO_PIP
|
||
#include "pivariant.h"
|
||
#endif
|
||
|
||
|
||
class __VariantFunctionsBase__ {
|
||
public:
|
||
virtual __VariantFunctionsBase__ * instance() {return 0;}
|
||
virtual PIString typeName() const {return PIString();}
|
||
virtual uint hash() const {return 0;}
|
||
virtual void newT(void *& ptr, const void * value) {;}
|
||
virtual void newNullT(void *& ptr) {;}
|
||
virtual void assignT(void *& ptr, const void * value) {;}
|
||
virtual void deleteT(void *& ptr) {;}
|
||
};
|
||
|
||
|
||
template<typename T>
|
||
class __VariantFunctions__: public __VariantFunctionsBase__ {
|
||
public:
|
||
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<T> ret; return &ret;}
|
||
#ifdef MICRO_PIP
|
||
PIString typeName() const final {static PIString ret(PIVariant(T()).typeName()); return ret;}
|
||
#else
|
||
PIString typeName() const final {static PIString ret(typeid(T).name()); return ret;}
|
||
#endif
|
||
uint hash() const final {static uint ret = typeName().hash(); return ret;}
|
||
void newT(void *& ptr, const void * value) final {ptr = (void*)(new T(*(const T*)value));}
|
||
void newNullT(void *& ptr) final {ptr = (void*)(new T());}
|
||
void assignT(void *& ptr, const void * value) final {*(T*)ptr = *(const T*)value;}
|
||
void deleteT(void *& ptr) final {delete (T*)(ptr);}
|
||
};
|
||
|
||
|
||
//! \addtogroup Core
|
||
//! \{
|
||
//! \~\class PIVariantSimple pivariantsimple.h
|
||
//! \~\brief
|
||
//! \~english Simple variant type.
|
||
//! \~russian Простой вариативный тип.
|
||
//!
|
||
//! \~\details
|
||
//! \~english
|
||
//!
|
||
//! \~russian
|
||
//!
|
||
//! \}
|
||
class PIVariantSimple {
|
||
public:
|
||
|
||
//! \~english Construct null %PIVariantSimple
|
||
//! \~russian Создает пустой %PIVariantSimple
|
||
PIVariantSimple() {ptr = 0; f = 0;}
|
||
|
||
//! \~english Contructs a copy of %PIVariantSimple.
|
||
//! \~russian Создает копию %PIVariantSimple.
|
||
PIVariantSimple(const PIVariantSimple & v) {
|
||
ptr = 0;
|
||
f = v.f;
|
||
if (f && v.ptr)
|
||
f->newT(ptr, v.ptr);
|
||
}
|
||
~PIVariantSimple() {destroy();}
|
||
|
||
//! \~english Assign operator.
|
||
//! \~russian Оператор присваивания.
|
||
PIVariantSimple & operator=(const PIVariantSimple & v) {
|
||
destroy();
|
||
f = v.f;
|
||
if (f && v.ptr)
|
||
f->newT(ptr, v.ptr);
|
||
return *this;
|
||
}
|
||
|
||
//! \~english Set value to "v".
|
||
//! \~russian Устанавливает значение в "v".
|
||
template <typename T>
|
||
void setValue(const T & v) {
|
||
if (f) {
|
||
if (isMyType<T>()) {
|
||
f->assignT(ptr, (const void *)&v);
|
||
return;
|
||
}
|
||
}
|
||
destroy();
|
||
f = __VariantFunctions__<T>().instance();
|
||
f->newT(ptr, (const void *)&v);
|
||
}
|
||
|
||
//! \~\brief
|
||
//! \~english Returns value as type "T".
|
||
//! \~russian Возвращает значение как тип "T".
|
||
//! \~\details
|
||
//! \~english
|
||
//! In contrast of PIVariant this class has strong check of type.
|
||
//! Returns value only if this type was set before.
|
||
//!
|
||
//! \~russian
|
||
//! В отличии от PIVariant этот класс строго проверяет типы.
|
||
//! Возвращает значение только если этот же тип был установлен ранее.
|
||
//!
|
||
template <typename T>
|
||
T value() const {
|
||
if (!f) return T();
|
||
if (!isMyType<T>())
|
||
return T();
|
||
return *(T*)(ptr);
|
||
}
|
||
|
||
//! \~english Returns %PIVariantSimple with value "v".
|
||
//! \~russian Возвращает %PIVariantSimple со значением "v".
|
||
template <typename T>
|
||
static PIVariantSimple fromValue(const T & v) {
|
||
PIVariantSimple ret;
|
||
ret.setValue(v);
|
||
return ret;
|
||
}
|
||
|
||
private:
|
||
template <typename T>
|
||
bool isMyType() const {
|
||
if (!f) return false;
|
||
uint mh = f->hash(), th = __VariantFunctions__<T>().instance()->hash();
|
||
if (mh == 0 || th == 0) return false;
|
||
return mh == th;
|
||
}
|
||
|
||
void destroy() {
|
||
if (ptr && f)
|
||
f->deleteT(ptr);
|
||
ptr = 0;
|
||
f = 0;
|
||
}
|
||
|
||
void * ptr;
|
||
__VariantFunctionsBase__ * f;
|
||
|
||
};
|
||
|
||
|
||
#define REGISTER_PIVARIANTSIMPLE(Type) \
|
||
template<> \
|
||
class __VariantFunctions__<Type>: public __VariantFunctionsBase__ { \
|
||
public: \
|
||
__VariantFunctionsBase__ * instance() final {static __VariantFunctions__<Type> ret; return &ret;} \
|
||
PIString typeName() const final {static PIString ret(#Type); return ret;} \
|
||
uint hash() const final {static uint ret = typeName().hash(); return ret;} \
|
||
void newT(void *& ptr, const void * value) final {ptr = (void*)(new Type(*(const Type *)value));} \
|
||
void newNullT(void *& ptr) final {ptr = (void*)(new Type());} \
|
||
void assignT(void *& ptr, const void * value) final {*(Type *)ptr = *(const Type *)value;} \
|
||
void deleteT(void *& ptr) final {delete (Type *)(ptr);} \
|
||
};
|
||
|
||
REGISTER_PIVARIANTSIMPLE(std::function<void(void*)>)
|
||
|
||
#endif // PIVARIANTSIMPLE_H
|