PIVariant add typeID, optimization, macros simplify and change custom logic to ID

This commit is contained in:
2022-11-27 11:03:32 +03:00
parent dc6fbbf7ec
commit f52fc5332c
2 changed files with 200 additions and 107 deletions

View File

@@ -65,19 +65,18 @@
#ifdef CUSTOM_PIVARIANT
PIMap<PIString, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = 0;
PIMap<uint, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = nullptr;
#endif
PIVariant::PIVariant() {
_type = PIVariant::pivInvalid;
_info = 0;
}
PIVariant::PIVariant(const PIVariant & v) {
_type = v._type;
_content = v._content;
_typeID = v._typeID;
#ifdef CUSTOM_PIVARIANT
_info = v._info;
#endif
@@ -122,6 +121,7 @@ void PIVariant::setValueFromString(const PIString & v) {
PIVariant & PIVariant::operator =(const PIVariant & v) {
_type = v._type;
_content = v._content;
_typeID = v._typeID;
#ifdef CUSTOM_PIVARIANT
_info = v._info;
#endif
@@ -136,7 +136,7 @@ PIVariant & PIVariant::operator =(PIVariant && v) {
bool PIVariant::operator ==(const PIVariant & v) const {
return (_type == v._type) && (_content == v._content);
return (_typeID == v._typeID) && (_content == v._content);
}
@@ -181,6 +181,87 @@ PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
}
PIVariant::Type PIVariant::typeFromID(uint type_id) {
if (type_id == typeID<bool>()) return PIVariant::pivBool;
if (type_id == typeID<char>()) return PIVariant::pivChar;
if (type_id == typeID<short>()) return PIVariant::pivShort;
if (type_id == typeID<int>()) return PIVariant::pivInt;
if (type_id == typeID<long>()) return PIVariant::pivInt;
if (type_id == typeID<llong>()) return PIVariant::pivLLong;
if (type_id == typeID<uchar>()) return PIVariant::pivUChar;
if (type_id == typeID<ushort>()) return PIVariant::pivUShort;
if (type_id == typeID<uint>()) return PIVariant::pivUInt;
if (type_id == typeID<ulong>()) return PIVariant::pivUInt;
if (type_id == typeID<ullong>()) return PIVariant::pivULLong;
if (type_id == typeID<float>()) return PIVariant::pivFloat;
if (type_id == typeID<double>()) return PIVariant::pivDouble;
if (type_id == typeID<ldouble>()) return PIVariant::pivLDouble;
if (type_id == typeID<complexd>()) return PIVariant::pivComplexd;
if (type_id == typeID<complexld>()) return PIVariant::pivComplexld;
if (type_id == typeID<PIBitArray>()) return PIVariant::pivBitArray;
if (type_id == typeID<PIByteArray>()) return PIVariant::pivByteArray;
if (type_id == typeID<PIString>()) return PIVariant::pivString;
if (type_id == typeID<PIStringList>()) return PIVariant::pivStringList;
if (type_id == typeID<PITime>()) return PIVariant::pivTime;
if (type_id == typeID<PIDate>()) return PIVariant::pivDate;
if (type_id == typeID<PIDateTime>()) return PIVariant::pivDateTime;
if (type_id == typeID<PISystemTime>()) return PIVariant::pivSystemTime;
if (type_id == typeID<PIVariantTypes::Enum>()) return PIVariant::pivEnum;
if (type_id == typeID<PIVariantTypes::File>()) return PIVariant::pivFile;
if (type_id == typeID<PIVariantTypes::Dir>()) return PIVariant::pivDir;
if (type_id == typeID<PIVariantTypes::Color>()) return PIVariant::pivColor;
if (type_id == typeID<PIPointd>()) return PIVariant::pivPoint;
if (type_id == typeID<PIRectd>()) return PIVariant::pivRect;
if (type_id == typeID<PIMathVectord>()) return PIVariant::pivMathVector;
if (type_id == typeID<PIMathMatrixd>()) return PIVariant::pivMathMatrix;
if (type_id == typeID<PILined>()) return PIVariant::pivLine;
if (type_id == typeID<PIVariantTypes::IODevice>()) return PIVariant::pivIODevice;
if (__PIVariantInfoStorage__::get()->map->contains(type_id))
return PIVariant::pivCustom;
return PIVariant::pivInvalid;
}
uint PIVariant::typeIDFromType(Type type) {
switch (type) {
case (PIVariant::pivBool ): return typeID<bool >();
case (PIVariant::pivChar ): return typeID<char >();
case (PIVariant::pivShort ): return typeID<short >();
case (PIVariant::pivInt ): return typeID<int >();
case (PIVariant::pivLLong ): return typeID<llong >();
case (PIVariant::pivUChar ): return typeID<uchar >();
case (PIVariant::pivUShort ): return typeID<ushort >();
case (PIVariant::pivUInt ): return typeID<uint >();
case (PIVariant::pivULLong ): return typeID<ullong >();
case (PIVariant::pivFloat ): return typeID<float >();
case (PIVariant::pivDouble ): return typeID<double >();
case (PIVariant::pivLDouble ): return typeID<ldouble >();
case (PIVariant::pivComplexd ): return typeID<complexd >();
case (PIVariant::pivComplexld ): return typeID<complexld >();
case (PIVariant::pivBitArray ): return typeID<PIBitArray >();
case (PIVariant::pivByteArray ): return typeID<PIByteArray >();
case (PIVariant::pivString ): return typeID<PIString >();
case (PIVariant::pivStringList): return typeID<PIStringList >();
case (PIVariant::pivTime ): return typeID<PITime >();
case (PIVariant::pivDate ): return typeID<PIDate >();
case (PIVariant::pivDateTime ): return typeID<PIDateTime >();
case (PIVariant::pivSystemTime): return typeID<PISystemTime >();
case (PIVariant::pivEnum ): return typeID<PIVariantTypes::Enum >();
case (PIVariant::pivFile ): return typeID<PIVariantTypes::File >();
case (PIVariant::pivDir ): return typeID<PIVariantTypes::Dir >();
case (PIVariant::pivColor ): return typeID<PIVariantTypes::Color >();
case (PIVariant::pivPoint ): return typeID<PIPointd >();
case (PIVariant::pivRect ): return typeID<PIRectd >();
case (PIVariant::pivMathVector): return typeID<PIMathVectord >();
case (PIVariant::pivMathMatrix): return typeID<PIMathMatrixd >();
case (PIVariant::pivLine ): return typeID<PILined >();
case (PIVariant::pivIODevice ): return typeID<PIVariantTypes::IODevice >();
default: break;
}
return 0;
}
PIString PIVariant::typeName() const {
#ifdef CUSTOM_PIVARIANT
if ((_type == pivCustom) && _info)
@@ -193,12 +274,57 @@ PIString PIVariant::typeName() const {
void PIVariant::swap(PIVariant & v) {
piSwap(_type, v._type);
_content.swap(v._content);
piSwap(_typeID, v._typeID);
#ifdef CUSTOM_PIVARIANT
piSwap(_info, v._info);
#endif
}
PIVariant PIVariant::fromValue(const PIByteArray & c, uint type_id) {
PIVariant ret;
PIVariant::Type t = typeFromID(type_id);
if (t == pivInvalid || t == pivCustom) {
#ifdef CUSTOM_PIVARIANT
ret._info = __PIVariantInfoStorage__::get()->map->value(type_id, 0);
if (ret._info) {
t = pivCustom;
} else
#endif
{
piCout << "Can`t initialize PIVariant from unregistered typeID \"" << type_id << "\"!";
return ret;
}
}
ret._type = t;
ret._typeID = type_id;
ret._content = c;
return ret;
}
PIVariant PIVariant::fromValue(const PIByteArray & c, const PIString & type) {
PIVariant ret;
PIVariant::Type t = typeFromName(type);
if (t == pivInvalid) {
#ifdef CUSTOM_PIVARIANT
ret._info = __PIVariantInfoStorage__::get()->map->value(type.hash(), 0);
if (ret._info) {
t = pivCustom;
} else
#endif
{
piCout << "Can`t initialize PIVariant from unregistered type \"" << type << "\"!";
return ret;
}
}
ret._type = t;
ret._typeID = type.hash();
ret._content = c;
return ret;
}
PIString PIVariant::typeName(PIVariant::Type type) {
switch (type) {
case PIVariant::pivBool: return "Bool";

View File

@@ -61,6 +61,7 @@ template<typename T>
class __PIVariantFunctions__ {
public:
static PIString typeNameHelper() {return PIStringAscii("");}
static uint typeIDHelper() {return 0;}
static bool isSimpleHelper() {return false;}
template<typename C> static PIByteArray castHelper(PIByteArray ba) {return PIByteArray();}
@@ -68,13 +69,12 @@ public:
};
struct PIP_EXPORT __PIVariantInfo__ {
__PIVariantInfo__() {
simple = false;
}
__PIVariantInfo__(const PIString & n) {typeName = n; typeID = n.hash();}
typedef PIByteArray(*castHelperFunc)(PIByteArray);
PIMap<PIString, castHelperFunc> cast;
PIMap<uint, castHelperFunc> cast;
PIString typeName;
bool simple;
uint typeID = 0;
bool simple = false;
};
template<typename T>
@@ -105,89 +105,46 @@ struct __PIVariantTypeInfo__ {
class PIP_EXPORT __PIVariantInfoStorage__ {
public:
__PIVariantInfoStorage__() {if (!map) map = new PIMap<PIString, __PIVariantInfo__ * >();}
__PIVariantInfoStorage__() {if (!map) map = new PIMap<uint, __PIVariantInfo__ * >();}
static __PIVariantInfoStorage__ * get() {static __PIVariantInfoStorage__ * r = new __PIVariantInfoStorage__(); return r;}
static PIMap<PIString, __PIVariantInfo__ * > * map;
static PIMap<uint, __PIVariantInfo__ * > * map;
};
#define REGISTER_VARIANT_H(classname) \
template<> inline PIString __PIVariantFunctions__< classname >::typeNameHelper() {static PIString tn = PIStringAscii(#classname); return tn;} \
REGISTER_VARIANT_TYPEINFO(classname)
#define REGISTER_NS_VARIANT_H(ns, classname) \
template<> inline PIString __PIVariantFunctions__< ns::classname >::typeNameHelper() {static PIString tn = PIStringAscii(#ns"::"#classname); return tn;} \
REGISTER_VARIANT_TYPEINFO(ns::classname)
#define REGISTER_VARIANT_CPP(classname) \
template <typename T> \
class __##classname##_PIVariantInitializer__ { \
public: \
__##classname##_PIVariantInitializer__(const PIString & name) { \
if (__PIVariantInfoStorage__::get()->map->contains(name)) \
return; \
__PIVariantInfo__ * vi = new __PIVariantInfo__(); \
vi->typeName = name; \
(*(__PIVariantInfoStorage__::get()->map))[name] = vi; \
} \
};
#define REGISTER_NS_VARIANT_CPP(ns, classname) \
template <typename T> \
class __##ns##classname##_PIVariantInitializer__ { \
public: \
__##ns##classname##_PIVariantInitializer__(const PIString & name) { \
if (__PIVariantInfoStorage__::get()->map->contains(name)) \
return; \
__PIVariantInfo__ * vi = new __PIVariantInfo__(); \
vi->typeName = name; \
(*(__PIVariantInfoStorage__::get()->map))[name] = vi; \
} \
};
#define INIT_VARIANT(classname) \
__##classname##_PIVariantInitializer__< classname > __##classname##_pivariant_initializer__(#classname);
#define INIT_NS_VARIANT(ns, classname) \
__##ns##classname##_PIVariantInitializer__< ns::classname > __##ns##classname##_pivariant_initializer__(#ns"::"#classname);
#define REGISTER_VARIANT(classname) \
REGISTER_VARIANT_H(classname) \
REGISTER_VARIANT_CPP(classname) \
static INIT_VARIANT(classname)
#define REGISTER_NS_VARIANT(ns, classname) \
REGISTER_NS_VARIANT_H(ns, classname) \
REGISTER_NS_VARIANT_CPP(ns, classname) \
static INIT_NS_VARIANT(ns, classname)
template<> inline PIString __PIVariantFunctions__< classname >::typeNameHelper() {static PIString tn = PIStringAscii(#classname); return tn;} \
template<> inline uint __PIVariantFunctions__< classname >::typeIDHelper() {static uint ret = PIStringAscii(#classname).hash(); return ret;} \
REGISTER_VARIANT_TYPEINFO(classname) \
STATIC_INITIALIZER_BEGIN \
uint type_id = __PIVariantFunctions__< classname >::typeIDHelper(); \
PIString type_name = __PIVariantFunctions__< classname >::typeNameHelper(); \
if (__PIVariantInfoStorage__::get()->map->contains(type_id)) return; \
(*(__PIVariantInfoStorage__::get()->map))[type_id] = new __PIVariantInfo__(type_name); \
STATIC_INITIALIZER_END
#define REGISTER_VARIANT_CAST_H(classname_from, classname_to) \
template<> template<> inline \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v);
template<> template<> inline \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v);
#define REGISTER_VARIANT_CAST_CPP(classname_from, classname_to) \
template<> template<> inline \
PIByteArray __PIVariantFunctions__<classname_from>::castHelper<classname_to>(PIByteArray v) { \
classname_from f; v >> f; \
classname_to t = __PIVariantFunctions__<classname_from>::castVariant<classname_to>(f); \
PIByteArray ret; ret << t; \
return ret;} \
template <typename T, typename C> \
class __##classname_from##_##classname_to##_PIVariantCastInitializer__ { \
public: \
__##classname_from##_##classname_to##_PIVariantCastInitializer__(const PIString & name, const PIString & cname) { \
__PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(name, 0)); \
template<> template<> inline \
PIByteArray __PIVariantFunctions__<classname_from>::castHelper<classname_to>(PIByteArray v) { \
classname_from f; v >> f; \
classname_to t = __PIVariantFunctions__<classname_from>::castVariant<classname_to>(f); \
PIByteArray ret; ret << t; \
return ret; \
} \
STATIC_INITIALIZER_BEGIN \
__PIVariantInfo__ * vi(__PIVariantInfoStorage__::get()->map->value(name.hash(), nullptr)); \
if (!vi) { \
piCout << "Warning! Using REGISTER_VARIANT_CAST("#classname_from", "#classname_to") before REGISTER_VARIANT("#classname_from"), ignore."; \
return; \
} \
vi->cast[cname] = __PIVariantFunctions__<classname_from>::castHelper<classname_to>; \
} \
}; \
static __##classname_from##_##classname_to##_PIVariantCastInitializer__< classname_from, classname_to > __##classname_from##_##classname_to##_pivariant_cast_initializer__(#classname_from, #classname_to); \
template<> template<> \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v)
vi->cast[cname.hash()] = __PIVariantFunctions__<classname_from>::castHelper<classname_to>; \
STATIC_INITIALIZER_END \
template<> template<> \
classname_to __PIVariantFunctions__<classname_from>::castVariant<classname_to>(const classname_from & v)
#define REGISTER_VARIANT_CAST(classname_from, classname_to) \
REGISTER_VARIANT_CAST_H(classname_from, classname_to) \
@@ -719,6 +676,10 @@ public:
//! \~russian Возвращает тип значения.
PIVariant::Type type() const {return _type;}
//! \~english Returns type ID of variant content.
//! \~russian Возвращает ID типа значения.
uint typeID() const {return _typeID;}
//! \~english Returns type name of variant content.
//! \~russian Возвращает имя типа значения.
PIString typeName() const;
@@ -750,35 +711,35 @@ public:
return ret;
}
static PIVariant fromValue(const PIByteArray & c, const PIString & type) {
PIVariant ret;
PIVariant::Type t = typeFromName(type);
if (t == pivInvalid) {
#ifdef CUSTOM_PIVARIANT
ret._info = __PIVariantInfoStorage__::get()->map->value(type, 0);
if (ret._info) {
t = pivCustom;
} else
#endif
{
piCout << "Can`t initialize PIVariant from unregistered type \"" << type << "\"!";
return ret;
}
}
ret._type = t;
ret._content = c;
return ret;
}
static PIVariant fromValue(const PIByteArray & c, uint type_id);
static PIVariant fromValue(const PIByteArray & c, const PIString & type);
//! \~english Returns type from its name.
//! \~russian Возвращает тип из его названия.
static PIVariant::Type typeFromName(const PIString & tname);
//! \~english Returns type from its ID.
//! \~russian Возвращает тип из его ID.
static PIVariant::Type typeFromID(uint type_id);
//! \~english Returns type from its name.
//! \~russian Возвращает тип из его названия.
static uint typeIDFromName(const PIString & tname) {return tname.hash();}
//! \~english Returns type ID from standard type.
//! \~russian Возвращает ID типа от стандатного типа.
static uint typeIDFromType(PIVariant::Type type);
//! \~english Returns type name.
//! \~russian Возвращает имя типа.
static PIString typeName(PIVariant::Type type);
template <typename T>
static uint typeID() {
return __PIVariantFunctions__<T>::typeIDHelper();
}
private:
void destroy() {_content.clear();}
template <typename T> inline static Type getType() {return pivCustom;}
@@ -787,10 +748,13 @@ private:
_content << v;
_type = getType<T>();
#ifdef CUSTOM_PIVARIANT
_typeID = typeID<T>();
if (_type == pivCustom) {
_info = __PIVariantInfoStorage__::get()->map->value(__PIVariantFunctions__<T>::typeNameHelper(), 0);
if (!_info)
_info = __PIVariantInfoStorage__::get()->map->value(_typeID, 0);
if (!_info) {
_type = pivInvalid;
piCout << "Can`t initialize PIVariant from unregistered type!";
}
} else
_info = 0;
#endif
@@ -804,7 +768,7 @@ private:
if (cn == v._info->typeName) {
ba = v._content;
} else {
__PIVariantInfo__::castHelperFunc cf = v._info->cast.value(cn);
__PIVariantInfo__::castHelperFunc cf = v._info->cast.value(cn.hash());
//piCout << "gav cast" << cf;
if (!cf) return T();
ba = cf(v._content);
@@ -817,10 +781,11 @@ private:
}
PIByteArray _content;
PIVariant::Type _type;
PIVariant::Type _type = PIVariant::pivInvalid;
#ifdef CUSTOM_PIVARIANT
__PIVariantInfo__ * _info;
__PIVariantInfo__ * _info = nullptr;
#endif
uint _typeID = 0;
};
@@ -938,11 +903,11 @@ REGISTER_VARIANT(PITime)
REGISTER_VARIANT(PIDate)
REGISTER_VARIANT(PIDateTime)
REGISTER_VARIANT(PISystemTime)
REGISTER_NS_VARIANT(PIVariantTypes, Enum)
REGISTER_NS_VARIANT(PIVariantTypes, File)
REGISTER_NS_VARIANT(PIVariantTypes, Dir)
REGISTER_NS_VARIANT(PIVariantTypes, Color)
REGISTER_NS_VARIANT(PIVariantTypes, IODevice)
REGISTER_VARIANT(PIVariantTypes::Enum)
REGISTER_VARIANT(PIVariantTypes::File)
REGISTER_VARIANT(PIVariantTypes::Dir)
REGISTER_VARIANT(PIVariantTypes::Color)
REGISTER_VARIANT(PIVariantTypes::IODevice)
REGISTER_VARIANT(PIPointd)
REGISTER_VARIANT(PIRectd)
REGISTER_VARIANT(PILined)
@@ -981,6 +946,8 @@ BINARY_STREAM_READ(PIVariant) {
PIByteArray vc = v._content;
v = PIVariant::fromValue(vc, tn);
#endif
} else {
v._typeID = PIVariant::typeIDFromType(v._type);
}
return s;
}