Files
pip/libs/main/core/pivariantsimple.h
2022-02-14 14:01:54 +03:00

149 lines
4.1 KiB
C++

/*! @file pivariantsimple.h
* @brief Variant simple type
*
* This file declares PIVariantSimple
*/
/*
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);}
};
class PIVariantSimple {
public:
PIVariantSimple() {ptr = 0; f = 0;}
PIVariantSimple(const PIVariantSimple & v) {
ptr = 0;
f = v.f;
if (f && v.ptr)
f->newT(ptr, v.ptr);
}
~PIVariantSimple() {destroy();}
PIVariantSimple & operator=(const PIVariantSimple & v) {
destroy();
f = v.f;
if (f && v.ptr)
f->newT(ptr, v.ptr);
return *this;
}
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);
}
template <typename T>
T value() const {
if (!f) return T();
if (!isMyType<T>())
return T();
return *(T*)(ptr);
}
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