Files
pip/main.cpp
Ivan Pelipenko 70a7363f76 some features
in main.cpp fastest Variant implementation
2020-08-05 00:53:27 +03:00

260 lines
6.5 KiB
C++

#include "pip.h"
PIMap<PIString, ullong> results;
template<typename T>
struct __VariantTypeInfo__ {
typedef T PureType;
typedef const T ConstPureType;
typedef T * PointerType;
typedef const T * ConstPointerType;
typedef T & ReferenceType;
typedef const T & ConstReferenceType;
};
#define __TYPEINFO_SINGLE(PT, T) \
template<> struct __PIVariantTypeInfo__<T> { \
typedef PT PureType; \
typedef const PT ConstPureType; \
typedef PT * PointerType; \
typedef const PT * ConstPointerType; \
typedef PT & ReferenceType; \
typedef const PT & ConstReferenceType; \
};
#define REGISTER_VARIANT_TYPEINFO(T) \
__TYPEINFO_SINGLE(T, T &) \
__TYPEINFO_SINGLE(T, const T) \
__TYPEINFO_SINGLE(T, const T &)
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 equalT(void *& ptr, const void * value) {;}
virtual void deleteT(void *& ptr) {;}
virtual PIByteArray toData(const void * ptr) const {return PIByteArray();}
virtual void fromData(void *& ptr, PIByteArray ba) {;}
//template<typename C> static PIByteArray castHelper(PIByteArray ba) {return PIByteArray();}
//template<typename C> static C castVariant(const T & v) {return C();}
static PIMap<uint, __VariantFunctionsBase__*> & registered() {static PIMap<uint, __VariantFunctionsBase__*> ret; return ret;}
};
template<typename T>
class __VariantFunctions__: public __VariantFunctionsBase__ {
public:
__VariantFunctionsBase__ * instance() override {static __VariantFunctions__<T> ret; return &ret;}
PIString typeName() const override {return PIString();}
uint hash() const override {static uint ret = typeName().hash(); return ret;}
void newT(void *& ptr, const void * value) override {ptr = (void*)(new T(*(const T*)value)); printf(" * new\n");}
void newNullT(void *& ptr) override {ptr = (void*)(new T()); printf(" * new null\n");}
void equalT(void *& ptr, const void * value) override {*(T*)ptr = *(const T*)value; printf(" * =\n");}
void deleteT(void *& ptr) override {delete (T*)(ptr); printf(" * del\n");}
PIByteArray toData(const void * ptr) const override {PIByteArray ret; ret << (*(const T* &)ptr); return ret;}
void fromData(void *& ptr, PIByteArray ba) override {ba >> *(T*)ptr;}
template<typename C> static PIByteArray castHelper(PIByteArray ba) {return PIByteArray();}
template<typename C> static C castVariant(const T & v) {return C();}
};
class Variant {
public:
Variant() {ptr = 0; f = 0;}
Variant(const Variant & v) {
ptr = 0;
f = v.f;
if (f && v.ptr)
f->newT(ptr, v.ptr);
}
~Variant() {destroy();}
Variant & operator=(const Variant & 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->equalT(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);
}
PIByteArray save() const {
if (!ptr || !f) return PIByteArray();
PIByteArray ret;
ret << f->hash();
ret.append(f->toData(ptr));
return ret;
}
bool load(PIByteArray ba) {
if (ba.size_s() < 4) return false;
uint h(0); ba >> h;
destroy();
f = __VariantFunctionsBase__::registered().value(h, 0);
if (!f) return false;
f->newNullT(ptr);
f->fromData(ptr, ba);
return true;
}
//private:
template <typename T>
bool isMyType() const {return f->hash() == __VariantFunctions__<T>().instance()->hash();}
void destroy() {
if (ptr && f)
f->deleteT(ptr);
ptr = 0;
f = 0;
}
void * ptr;
__VariantFunctionsBase__ * f;
};
int Acnt = 0;
class A {
public:
A() {i = "constructor"; /*piCout << "A()";*/ ++Acnt;}
A(const A & a): i(a.i) {/*piCout << "copy A()";*/ ++Acnt;}
~A() {/*piCout << "~A()";*/ --Acnt;}
A & operator =(const A & a) {i = a.i; /*piCout << "= A()";*/ return *this;}
PIString i;
};
PIByteArray & operator <<(PIByteArray & ba, const A & v) {ba << v.i; return ba;}
PIByteArray & operator >>(PIByteArray & ba, A & v) {ba >> v.i; return ba;}
template <>
PIString __VariantFunctions__<int>::typeName() const {static PIString ret("int"); return ret;}
class _VariantRegistrator_int__ {
public:
_VariantRegistrator_int__() {
__VariantFunctionsBase__ * f = __VariantFunctions__<int>().instance();
__VariantFunctionsBase__::registered()[f->hash()] = f;
}
};
_VariantRegistrator_int__ __reg_int__;
template <>
PIString __VariantFunctions__<A>::typeName() const {static PIString ret("A"); return ret;}
class _VariantRegistrator_A__ {
public:
_VariantRegistrator_A__() {
__VariantFunctionsBase__ * f = __VariantFunctions__<A>().instance();
__VariantFunctionsBase__::registered()[f->hash()] = f;
}
};
_VariantRegistrator_A__ __reg_A__;
int main() {
{
Variant v, v2;
/*{
A a, ra;
a.i = "main";
v.setValue(a);
ra = v.value<A>();
piCout << " 1 A.i =" << ra.i;
a.i = "main second";
v.setValue(a);
ra = v.value<A>();
piCout << " 2 A.i =" << ra.i;
piCout << "Acnt" << Acnt;
}
piCout << "Acnt" << Acnt;
v2 = v;
PIString ra = v2.value<PIString>();
piCout << " 3 A.i =" << ra;*/
A a, ra;
a.i = "main";
v.setValue(a);
PIByteArray ba = v.save();
piCout << v2.load(ba);
piCout << v2.value<A>().i;
}
piCout << "Acnt" << Acnt;
//__VariantFunctionsBase__ * f = __VariantFunctions__<void*>().instance();
//piCout << f->typeName();
//f = __VariantFunctions__<int>().instance();
//piCout << f->typeName();
}
/*
template <typename T>
void test_var(const char * Tname) {
piCout << Tname << "...";
ullong cnt = 0;
PIVariant _v;
PITimeMeasurer tm1s;
while (tm1s.elapsed_m() < 500.) {
++cnt;
for (int j = 0; j < 1000; ++j) {
PIVariant v;
v = T();
v.setValue(T(j));
_v = v;
}
}
PIVariant v;
results[Tname] = cnt;
}
#define TEST_VAR(T) test_var<T>(#T)
int main() {
TEST_VAR(int);
TEST_VAR(float);
TEST_VAR(ullong);
TEST_VAR(PIString);
int sz = 0;
auto i = results.makeIterator();
while (i.next()) sz = piMaxi(sz, i.key().length());
i.reset();
while (i.next())
piCout << i.key().expandedLeftTo(sz, ' ') << ":" << i.value();
}
*/