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 #ifdef CUSTOM_PIVARIANT
PIMap<PIString, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = 0; PIMap<uint, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = nullptr;
#endif #endif
PIVariant::PIVariant() { PIVariant::PIVariant() {
_type = PIVariant::pivInvalid;
_info = 0;
} }
PIVariant::PIVariant(const PIVariant & v) { PIVariant::PIVariant(const PIVariant & v) {
_type = v._type; _type = v._type;
_content = v._content; _content = v._content;
_typeID = v._typeID;
#ifdef CUSTOM_PIVARIANT #ifdef CUSTOM_PIVARIANT
_info = v._info; _info = v._info;
#endif #endif
@@ -122,6 +121,7 @@ void PIVariant::setValueFromString(const PIString & v) {
PIVariant & PIVariant::operator =(const PIVariant & v) { PIVariant & PIVariant::operator =(const PIVariant & v) {
_type = v._type; _type = v._type;
_content = v._content; _content = v._content;
_typeID = v._typeID;
#ifdef CUSTOM_PIVARIANT #ifdef CUSTOM_PIVARIANT
_info = v._info; _info = v._info;
#endif #endif
@@ -136,7 +136,7 @@ PIVariant & PIVariant::operator =(PIVariant && v) {
bool PIVariant::operator ==(const PIVariant & v) const { 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 { PIString PIVariant::typeName() const {
#ifdef CUSTOM_PIVARIANT #ifdef CUSTOM_PIVARIANT
if ((_type == pivCustom) && _info) if ((_type == pivCustom) && _info)
@@ -193,12 +274,57 @@ PIString PIVariant::typeName() const {
void PIVariant::swap(PIVariant & v) { void PIVariant::swap(PIVariant & v) {
piSwap(_type, v._type); piSwap(_type, v._type);
_content.swap(v._content); _content.swap(v._content);
piSwap(_typeID, v._typeID);
#ifdef CUSTOM_PIVARIANT #ifdef CUSTOM_PIVARIANT
piSwap(_info, v._info); piSwap(_info, v._info);
#endif #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) { PIString PIVariant::typeName(PIVariant::Type type) {
switch (type) { switch (type) {
case PIVariant::pivBool: return "Bool"; case PIVariant::pivBool: return "Bool";

View File

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