Files
pip/libs/main/core/pivariantsimple.h
2022-08-15 19:35:49 +03:00

187 lines
5.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \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