diff --git a/libs/main/types/pivariant.cpp b/libs/main/types/pivariant.cpp index 7aa19e17..8aaa81ee 100644 --- a/libs/main/types/pivariant.cpp +++ b/libs/main/types/pivariant.cpp @@ -65,19 +65,18 @@ #ifdef CUSTOM_PIVARIANT -PIMap * __PIVariantInfoStorage__::map = 0; +PIMap * __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()) return PIVariant::pivBool; + if (type_id == typeID()) return PIVariant::pivChar; + if (type_id == typeID()) return PIVariant::pivShort; + if (type_id == typeID()) return PIVariant::pivInt; + if (type_id == typeID()) return PIVariant::pivInt; + if (type_id == typeID()) return PIVariant::pivLLong; + if (type_id == typeID()) return PIVariant::pivUChar; + if (type_id == typeID()) return PIVariant::pivUShort; + if (type_id == typeID()) return PIVariant::pivUInt; + if (type_id == typeID()) return PIVariant::pivUInt; + if (type_id == typeID()) return PIVariant::pivULLong; + if (type_id == typeID()) return PIVariant::pivFloat; + if (type_id == typeID()) return PIVariant::pivDouble; + if (type_id == typeID()) return PIVariant::pivLDouble; + if (type_id == typeID()) return PIVariant::pivComplexd; + if (type_id == typeID()) return PIVariant::pivComplexld; + if (type_id == typeID()) return PIVariant::pivBitArray; + if (type_id == typeID()) return PIVariant::pivByteArray; + if (type_id == typeID()) return PIVariant::pivString; + if (type_id == typeID()) return PIVariant::pivStringList; + if (type_id == typeID()) return PIVariant::pivTime; + if (type_id == typeID()) return PIVariant::pivDate; + if (type_id == typeID()) return PIVariant::pivDateTime; + if (type_id == typeID()) return PIVariant::pivSystemTime; + if (type_id == typeID()) return PIVariant::pivEnum; + if (type_id == typeID()) return PIVariant::pivFile; + if (type_id == typeID()) return PIVariant::pivDir; + if (type_id == typeID()) return PIVariant::pivColor; + if (type_id == typeID()) return PIVariant::pivPoint; + if (type_id == typeID()) return PIVariant::pivRect; + if (type_id == typeID()) return PIVariant::pivMathVector; + if (type_id == typeID()) return PIVariant::pivMathMatrix; + if (type_id == typeID()) return PIVariant::pivLine; + if (type_id == typeID()) 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(); + case (PIVariant::pivChar ): return typeID(); + case (PIVariant::pivShort ): return typeID(); + case (PIVariant::pivInt ): return typeID(); + case (PIVariant::pivLLong ): return typeID(); + case (PIVariant::pivUChar ): return typeID(); + case (PIVariant::pivUShort ): return typeID(); + case (PIVariant::pivUInt ): return typeID(); + case (PIVariant::pivULLong ): return typeID(); + case (PIVariant::pivFloat ): return typeID(); + case (PIVariant::pivDouble ): return typeID(); + case (PIVariant::pivLDouble ): return typeID(); + case (PIVariant::pivComplexd ): return typeID(); + case (PIVariant::pivComplexld ): return typeID(); + case (PIVariant::pivBitArray ): return typeID(); + case (PIVariant::pivByteArray ): return typeID(); + case (PIVariant::pivString ): return typeID(); + case (PIVariant::pivStringList): return typeID(); + case (PIVariant::pivTime ): return typeID(); + case (PIVariant::pivDate ): return typeID(); + case (PIVariant::pivDateTime ): return typeID(); + case (PIVariant::pivSystemTime): return typeID(); + case (PIVariant::pivEnum ): return typeID(); + case (PIVariant::pivFile ): return typeID(); + case (PIVariant::pivDir ): return typeID(); + case (PIVariant::pivColor ): return typeID(); + case (PIVariant::pivPoint ): return typeID(); + case (PIVariant::pivRect ): return typeID(); + case (PIVariant::pivMathVector): return typeID(); + case (PIVariant::pivMathMatrix): return typeID(); + case (PIVariant::pivLine ): return typeID(); + case (PIVariant::pivIODevice ): return typeID(); + 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"; diff --git a/libs/main/types/pivariant.h b/libs/main/types/pivariant.h index f14295b4..3a0af353 100644 --- a/libs/main/types/pivariant.h +++ b/libs/main/types/pivariant.h @@ -61,6 +61,7 @@ template class __PIVariantFunctions__ { public: static PIString typeNameHelper() {return PIStringAscii("");} + static uint typeIDHelper() {return 0;} static bool isSimpleHelper() {return false;} template 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 cast; + PIMap cast; PIString typeName; - bool simple; + uint typeID = 0; + bool simple = false; }; template @@ -105,89 +105,46 @@ struct __PIVariantTypeInfo__ { class PIP_EXPORT __PIVariantInfoStorage__ { public: - __PIVariantInfoStorage__() {if (!map) map = new PIMap();} + __PIVariantInfoStorage__() {if (!map) map = new PIMap();} static __PIVariantInfoStorage__ * get() {static __PIVariantInfoStorage__ * r = new __PIVariantInfoStorage__(); return r;} - static PIMap * map; + static PIMap * 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 \ -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 \ -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__::castVariant(const classname_from & v); + template<> template<> inline \ + classname_to __PIVariantFunctions__::castVariant(const classname_from & v); #define REGISTER_VARIANT_CAST_CPP(classname_from, classname_to) \ -template<> template<> inline \ -PIByteArray __PIVariantFunctions__::castHelper(PIByteArray v) { \ - classname_from f; v >> f; \ - classname_to t = __PIVariantFunctions__::castVariant(f); \ - PIByteArray ret; ret << t; \ - return ret;} \ -template \ -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__::castHelper(PIByteArray v) { \ + classname_from f; v >> f; \ + classname_to t = __PIVariantFunctions__::castVariant(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__::castHelper; \ - } \ -}; \ -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__::castVariant(const classname_from & v) + vi->cast[cname.hash()] = __PIVariantFunctions__::castHelper; \ + STATIC_INITIALIZER_END \ + template<> template<> \ + classname_to __PIVariantFunctions__::castVariant(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 + static uint typeID() { + return __PIVariantFunctions__::typeIDHelper(); + } + private: void destroy() {_content.clear();} template inline static Type getType() {return pivCustom;} @@ -787,10 +748,13 @@ private: _content << v; _type = getType(); #ifdef CUSTOM_PIVARIANT + _typeID = typeID(); if (_type == pivCustom) { - _info = __PIVariantInfoStorage__::get()->map->value(__PIVariantFunctions__::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; }