/*
    PIP - Platform Independent Primitives
    Variant type
    Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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/>.
*/

#include "pivariant.h"

#include "pitranslator.h"


//! \class PIVariant pivariant.h
//! \details
//! \~english \section PIVariant_sec0 Synopsis
//! \~russian \section PIVariant_sec0 Краткий обзор
//! \~english
//! This class provides general type that can contains all standard types, some
//! PIP types or custom type. In case of standard types this class also provides
//! convertions between them.
//!
//! \~russian
//! Этот класс предоставляет некий общий тип, который может содержать все стандартные тип,
//! некоторые типы PIP, а также любой свой тип. В случае стандартных типов предоставляется
//! автоматическое преобразование между ними.
//!
//! \~english \section PIVariant_sec1 Usage
//! \~russian \section PIVariant_sec1 Использование
//! \~english
//! %PIVariant useful if you want pass many variables with different types in
//! single array, or type may vary from case to case, e.g.:
//!
//! \~russian
//! %PIVariant полезен когда надо передать несколько разнотипных значений
//! одним массивом, или тип заранее неизвестен, например:
//!
//! \~\code{cpp}
//! PIVector<PIVariant> array;
//! array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
//! piCout << array;
//! for (auto i: array)
//! 	piCout << i.toInt();
//! \endcode
//!
//! \~english Result:
//! \~russian Результат:
//! \~\code{cpp}
//! {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
//! 10
//! 1
//! 1
//! 255
//! \endcode
//!


#ifdef CUSTOM_PIVARIANT
PIMap<uint, __PIVariantInfo__ *> & __PIVariantInfoStorage__::get() {
	static PIMap<uint, __PIVariantInfo__ *> ret;
	return ret;
}
#endif


PIVariant::PIVariant() {}


PIVariant::PIVariant(const PIVariant & v) {
	_type    = v._type;
	_content = v._content;
	_typeID  = v._typeID;
#ifdef CUSTOM_PIVARIANT
	_info = v._info;
#endif
}


PIVariant::PIVariant(PIVariant && v) {
	swap(v);
}


void PIVariant::setValueFromString(const PIString & v) {
	switch (_type) {
	case PIVariant::pivBool: {
		setValue(v.toBool());
	} break;
	case PIVariant::pivChar: {
		setValue(v.toChar());
	} break;
	case PIVariant::pivUChar: {
		setValue((uchar)v.toChar());
	} break;
	case PIVariant::pivShort: {
		setValue(v.toShort());
	} break;
	case PIVariant::pivUShort: {
		setValue(v.toUShort());
	} break;
	case PIVariant::pivInt: {
		setValue(v.toInt());
	} break;
	case PIVariant::pivUInt: {
		setValue(v.toUInt());
	} break;
	case PIVariant::pivLLong: {
		setValue(v.toLLong());
	} break;
	case PIVariant::pivULLong: {
		setValue(v.toULLong());
	} break;
	case PIVariant::pivFloat: {
		setValue(v.toFloat());
	} break;
	case PIVariant::pivDouble: {
		setValue(v.toDouble());
	} break;
	case PIVariant::pivLDouble: {
		setValue(v.toLDouble());
	} break;
	case PIVariant::pivComplexf: {
		PIStringList sl = v.mid(1, v.size_s() - 2).split(';');
		setValue(complexf(sl.size() > 0 ? sl[0].toFloat() : 0.f, sl.size() > 1 ? sl[1].toFloat() : 0.f));
	} break;
	case PIVariant::pivComplexd: {
		PIStringList sl = v.mid(1, v.size_s() - 2).split(';');
		setValue(complexd(sl.size() > 0 ? sl[0].toDouble() : 0., sl.size() > 1 ? sl[1].toDouble() : 0.));
	} break;
	case PIVariant::pivComplexld: {
		PIStringList sl = v.mid(1, v.size_s() - 2).split(';');
		setValue(complexld(sl.size() > 0 ? sl[0].toLDouble() : 0.L, sl.size() > 1 ? sl[1].toLDouble() : 0.L));
	} break;
	case PIVariant::pivTime: {
		setValue(PITime::fromString(v));
	} break;
	case PIVariant::pivDate: {
		setValue(PIDate::fromString(v));
	} break;
	case PIVariant::pivDateTime: {
		setValue(PIDateTime::fromString(v));
	} break;
	case PIVariant::pivSystemTime: {
		setValue(PISystemTime::fromString(v));
	} break;
	case PIVariant::pivString: {
		setValue(v);
	} break;
	case PIVariant::pivStringList: {
		setValue(v.split("%|%"));
	} break;
	case PIVariant::pivEnum: {
		setValue(PIVariantTypes::Enum::fromString(v));
	} break;
	case PIVariant::pivFile: {
		PIVariantTypes::File r = toFile();
		r.file                 = v;
		setValue(r);
	} break;
	case PIVariant::pivDir: {
		PIVariantTypes::Dir r = toDir();
		r.dir                 = v;
		setValue(r);
	} break;
	case PIVariant::pivColor: {
		setValue(PIVariantTypes::Color::fromString(v));
	} break;
	case PIVariant::pivIODevice: {
		setValue(PIVariantTypes::IODevice()); // TODO
	} break;
	case PIVariant::pivPoint: {
		PIStringList l = v.split(';');
		if (l.size() >= 2) setValue(PIPointd(l[0].toDouble(), l[1].toDouble()));
	} break;
	case PIVariant::pivRect: {
		PIStringList l = v.split(';');
		if (l.size() >= 4) setValue(PIRectd(l[0].toDouble(), l[1].toDouble(), l[2].toDouble(), l[3].toDouble()));
	} break;
	case PIVariant::pivLine: {
		PIStringList l = v.split(';');
		if (l.size() >= 4) setValue(PILined(l[0].toDouble(), l[1].toDouble(), l[2].toDouble(), l[3].toDouble()));
	} break;
	case PIVariant::pivNetworkAddress: {
		setValue(PINetworkAddress(v));
	} break;
	case PIVariant::pivCustom: {
#ifdef CUSTOM_PIVARIANT
		__PIVariantInfo__ * vi = __PIVariantInfoStorage__::get().value(__PIVariantFunctions__<PIString>::typeIDHelper());
		if (vi) {
			__PIVariantInfo__::castHelperFunc cf = vi->cast.value(_typeID);
			if (cf) {
				PIByteArray sba;
				sba << v;
				_content = cf(sba);
			}
		}
#endif
	} break;
	default: break;
	}
}


PIVariant & PIVariant::operator=(const PIVariant & v) {
	_type    = v._type;
	_content = v._content;
	_typeID  = v._typeID;
#ifdef CUSTOM_PIVARIANT
	_info = v._info;
#endif
	return *this;
}


PIVariant & PIVariant::operator=(PIVariant && v) {
	swap(v);
	return *this;
}


bool PIVariant::operator==(const PIVariant & v) const {
	return (_typeID == v._typeID) && (_content == v._content);
}


PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
	PIString s = tname.trimmed().toLowerCase().replaceAll(" ", "");
	if (s == "bool" || s == "boolean") return PIVariant::pivBool;
	if (s == "char" || s == "sbyte" || s == "int8_t") return PIVariant::pivChar;
	if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword" || s == "int16_t")
		return PIVariant::pivShort;
	if (s == "int" || s == "signed" || s == "signedint" || s == "int32_t") return PIVariant::pivInt;
	if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::pivInt;
	if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword" ||
	    s == "int64_t")
		return PIVariant::pivLLong;
	if (s == "uchar" || s == "byte" || s == "uint8_t") return PIVariant::pivUChar;
	if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word" || s == "uint16_t") return PIVariant::pivUShort;
	if (s == "uint" || s == "unsigned" || s == "unsignedint" || s == "uint32_t") return PIVariant::pivUInt;
	if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::pivUInt;
	if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword" || s == "uint64_t")
		return PIVariant::pivULLong;
	if (s == "float") return PIVariant::pivFloat;
	if (s == "double" || s == "real") return PIVariant::pivDouble;
	if (s == "ldouble" || s == "longdouble") return PIVariant::pivLDouble;
	if (s == "complexf" || s == "complex<float>") return PIVariant::pivComplexf;
	if (s == "complexd" || s == "complex<double>") return PIVariant::pivComplexd;
	if (s == "complexld" || s == "complex<ldouble>" || s == "complex<longdouble>") return PIVariant::pivComplexld;
	if (s == "pibitarray" || s == "bitarray") return PIVariant::pivBitArray;
	if (s == "pibytearray" || s == "bytearray" || s == "vector<uchar>" || s == "pivector<uchar>" || s == "vector<unsignedchar>" ||
	    s == "pivector<unsignedchar>" || s == "vector<char>" || s == "pivector<char>")
		return PIVariant::pivByteArray;
	if (s == "pistring" || s == "string" || s == "text") return PIVariant::pivString;
	if (s == "pistringlist" || s == "stringlist" || s == "vector<string>" || s == "vector<pistring>" || s == "pivector<string>" ||
	    s == "pivector<pistring>")
		return PIVariant::pivStringList;
	if (s == "pitime" || s == "time") return PIVariant::pivTime;
	if (s == "pidate" || s == "date") return PIVariant::pivDate;
	if (s == "pidatetime" || s == "datetime") return PIVariant::pivDateTime;
	if (s == "pisystemtime" || s == "systemtime") return PIVariant::pivSystemTime;
	if (s == "pivarianttypes::enum" || s == "enum") return PIVariant::pivEnum;
	if (s == "pivarianttypes::file" || s == "file" || s == "path") return PIVariant::pivFile;
	if (s == "pivarianttypes::dir" || s == "dir" || s == "directory") return PIVariant::pivDir;
	if (s == "pivarianttypes::color" || s == "color") return PIVariant::pivColor;
	if (s == "pivarianttypes::iodevice" || s == "device" || s == "iodevice") return PIVariant::pivIODevice;
	if (s == "pipointd" || s == "point") return PIVariant::pivPoint;
	if (s == "pirectd" || s == "rect") return PIVariant::pivRect;
	if (s == "pimathvectord" || s == "vector") return PIVariant::pivMathVector;
	if (s == "pimathmatrixd" || s == "matrix") return PIVariant::pivMathMatrix;
	if (s == "pilined" || s == "line") return PIVariant::pivLine;
	if (s == "pinetworkaddress" || s == "networkaddress" || s == "ip") return PIVariant::pivNetworkAddress;
	return PIVariant::pivInvalid;
}


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<complexf>()) return PIVariant::pivComplexf;
	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<PIVariantTypes::IODevice>()) return PIVariant::pivIODevice;
	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<PINetworkAddress>()) return PIVariant::pivNetworkAddress;
#ifdef CUSTOM_PIVARIANT
	if (__PIVariantInfoStorage__::get().contains(type_id)) return PIVariant::pivCustom;
#endif
	return PIVariant::pivInvalid;
}


uint PIVariant::typeIDFromName(const PIString & tname) {
	PIVariant::Type t = typeFromName(tname);
	if (t == pivCustom || t == pivInvalid) return tname.hash();
	return typeIDFromType(t);
}


// clang-format off
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::pivComplexf      ): return typeID<complexf                 >();
	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::pivIODevice      ): return typeID<PIVariantTypes::IODevice >();
	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::pivNetworkAddress): return typeID<PINetworkAddress         >();
	default: break;
	}
	return 0;
}
// clang-format on


PIString PIVariant::typeName() const {
#ifdef CUSTOM_PIVARIANT
	if ((_type == pivCustom) && _info) return _info->typeName;
#endif
	return typeName(_type);
}


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().value(type_id, 0);
		if (ret._info) {
			t = pivCustom;
		} else
#endif
		{
			piCout << "Can`t initialize PIVariant from unregistered typeID \"%1\"!"_tr("PIVariant").arg(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().value(type.hash(), 0);
		if (ret._info) {
			t = pivCustom;
		} else
#endif
		{
			piCout << "Can`t initialize PIVariant from unregistered type \"%1\"!"_tr("PIVariant").arg(type);
			return ret;
		}
	}
	ret._type    = t;
	ret._typeID  = type.hash();
	ret._content = c;
	return ret;
}


PIVariant PIVariant::fromType(uint type_id) {
#ifdef CUSTOM_PIVARIANT
	__PIVariantInfo__ * vi = __PIVariantInfoStorage__::get().value(type_id);
	if (!vi) return PIVariant();
	return PIVariant::fromValue(vi->empty, type_id);
#else
	return PIVariant();
#endif
}


PIString PIVariant::typeName(PIVariant::Type type) {
	switch (type) {
	case PIVariant::pivBool: return "Bool";
	case PIVariant::pivChar: return "Char";
	case PIVariant::pivUChar: return "UChar";
	case PIVariant::pivShort: return "Short";
	case PIVariant::pivUShort: return "UShort";
	case PIVariant::pivInt: return "Int";
	case PIVariant::pivUInt: return "UInt";
	case PIVariant::pivLLong: return "LLong";
	case PIVariant::pivULLong: return "ULLong";
	case PIVariant::pivFloat: return "Float";
	case PIVariant::pivDouble: return "Double";
	case PIVariant::pivLDouble: return "LDouble";
	case PIVariant::pivComplexf: return "Complexf";
	case PIVariant::pivComplexd: return "Complexd";
	case PIVariant::pivComplexld: return "Complexld";
	case PIVariant::pivBitArray: return "BitArray";
	case PIVariant::pivByteArray: return "ByteArray";
	case PIVariant::pivString: return "String";
	case PIVariant::pivStringList: return "StringList";
	case PIVariant::pivTime: return "Time";
	case PIVariant::pivDate: return "Date";
	case PIVariant::pivDateTime: return "DateTime";
	case PIVariant::pivSystemTime: return "SystemTime";
	case PIVariant::pivEnum: return "Enum";
	case PIVariant::pivFile: return "File";
	case PIVariant::pivDir: return "Dir";
	case PIVariant::pivColor: return "Color";
	case PIVariant::pivIODevice: return "IODevice";
	case PIVariant::pivPoint: return "Point";
	case PIVariant::pivRect: return "Rect";
	case PIVariant::pivLine: return "Line";
	case PIVariant::pivNetworkAddress: return "NetworkAddress";
	case PIVariant::pivMathVector: return "Vector";
	case PIVariant::pivMathMatrix: return "Matrix";
	case PIVariant::pivCustom: return "Custom";
	default: break;
	}
	return "Invalid";
}


PIString PIVariant::typeNameFromID(uint type_id) {
#ifdef CUSTOM_PIVARIANT
	__PIVariantInfo__ * vi = __PIVariantInfoStorage__::get().value(type_id);
	if (!vi) return PIString();
	return vi->typeName;
#else
	return PIString();
#endif
}


PIVector<uint> PIVariant::knownTypeIDs() {
	PIVector<uint> ret;
#ifdef CUSTOM_PIVARIANT
	auto it = __PIVariantInfoStorage__::get().makeIterator();
	while (it.next())
		ret << it.key();
#endif
	return ret;
}


int PIVariant::knownTypeIDsCount() {
#ifdef CUSTOM_PIVARIANT
	return __PIVariantInfoStorage__::get().size_s();
#endif
	return 0;
}


//! \~\brief
//! \~english Returns variant content as boolean
//! \~russian Возвращает содержимое как boolean
//!
//! \~\details
//! \~english
//! In case of numeric types returns \b true if value != 0. \n
//! In case of String type returns \a PIString::toBool(). \n
//! In case of StringList type returns \b false if string list is empty,
//! otherwise returns \a PIString::toBool() of first string. \n
//! In case of other types returns \b false.
//!
//! \~russian
//! Для численных типов возвращает \b true если значение != 0. \n
//! Для типа String возвращает \a PIString::toBool(). \n
//! Для типа StringList возвращает \b false если массив пустой, \n
//! иначе возвращает \a PIString::toBool() первой строки. \n
//! Для остальных типов возвращает \b false.
//!
bool PIVariant::toBool() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return r;
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return r != 0;
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return r > 0.f;
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return r > 0.;
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return r > 0.;
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r.toBool();
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return false;
		return r.front().toBool();
	}
	case PIVariant::pivCustom: return getAsValue<bool>(*this);
	default: break;
	}
	return false;
}


//! \~\brief
//! \~english Returns variant content as int
//! \~russian Возвращает содержимое как int
//!
//! \~\details
//! \~english
//! In case of numeric types returns integer value. \n
//! In case of String type returns \a PIString::toInt(). \n
//! In case of StringList type returns \b 0 if string list is empty,
//! otherwise returns \a PIString::toInt() of first string. \n
//! In case of other types returns \b 0.
//!
//! \~russian
//! Для численных типов возвращает целочисленное значение. \n
//! Для типа String возвращает \a PIString::toInt(). \n
//! Для типа StringList возвращает \b 0 если массив пустой, \n
//! иначе возвращает \a PIString::toInt() первой строки. \n
//! Для остальных типов возвращает \b 0.
//!
int PIVariant::toInt() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return r;
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return r;
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return r;
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return r;
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r.toInt();
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return 0;
		return r.front().toInt();
	}
	case PIVariant::pivEnum: {
		PIVariantTypes::Enum r;
		ba >> r;
		return r.selectedValue();
	}
	case PIVariant::pivColor: {
		PIVariantTypes::Color r;
		ba >> r;
		return (int)r.rgba;
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return r.size() > 0 ? r[0] : 0;
	}
	case PIVariant::pivCustom: return getAsValue<int>(*this);
	default: break;
	}
	return 0;
}


//! \~\brief
//! \~english Returns variant content as long long
//! \~russian Возвращает содержимое как long long
//!
//! \~\details
//! \~english
//! In case of numeric types returns integer value. \n
//! In case of String type returns \a PIString::toLLong(). \n
//! In case of StringList type returns \b 0L if string list is empty,
//! otherwise returns \a PIString::toLLong() of first string. \n
//! In case of other types returns \b 0L.
//!
//! \~russian
//! Для численных типов возвращает целочисленное значение. \n
//! Для типа String возвращает \a PIString::toLLong(). \n
//! Для типа StringList возвращает \b 0L если массив пустой, \n
//! иначе возвращает \a PIString::toLLong() первой строки. \n
//! Для остальных типов возвращает \b 0L.
//!
llong PIVariant::toLLong() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return r;
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return r;
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return r;
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return r;
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r.toLLong();
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return 0L;
		return r.front().toLLong();
	}
	case PIVariant::pivEnum: {
		PIVariantTypes::Enum r;
		ba >> r;
		return llong(r.selectedValue());
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return r.size() > 0 ? r[0] : 0L;
	}
	case PIVariant::pivCustom: return getAsValue<llong>(*this);
	default: break;
	}
	return 0L;
}


//! \~\brief
//! \~english Returns variant content as float
//! \~russian Возвращает содержимое как float
//!
//! \~\details
//! \~english
//! In case of numeric types returns float value. \n
//! In case of String type returns \a PIString::toFloat(). \n
//! In case of StringList type returns \b 0.f if string list is empty,
//! otherwise returns \a PIString::toFloat() of first string. \n
//! In case of other types returns \b 0.f .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toFloat(). \n
//! Для типа StringList возвращает \b 0.f если массив пустой, \n
//! иначе возвращает \a PIString::toFloat() первой строки. \n
//! Для остальных типов возвращает \b 0.f .
//!
float PIVariant::toFloat() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return r;
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return r;
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return r;
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return r;
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r.toFloat();
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return 0.f;
		return r.front().toFloat();
	}
	case PIVariant::pivEnum: {
		PIVariantTypes::Enum r;
		ba >> r;
		return float(r.selectedValue());
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return r.size() > 0 ? r[0] : 0.f;
	}
	case PIVariant::pivCustom: return getAsValue<float>(*this);
	default: break;
	}
	return 0.f;
}


//! \~\brief
//! \~english Returns variant content as double
//! \~russian Возвращает содержимое как double
//!
//! \~\details
//! \~english
//! In case of numeric types returns double value. \n
//! In case of String type returns \a PIString::toDouble(). \n
//! In case of StringList type returns \b 0. if string list is empty,
//! otherwise returns \a PIString::toDouble() of first string. \n
//! In case of other types returns \b 0. .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toDouble(). \n
//! Для типа StringList возвращает \b 0. если массив пустой, \n
//! иначе возвращает \a PIString::toDouble() первой строки. \n
//! Для остальных типов возвращает \b 0. .
//!
double PIVariant::toDouble() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return r;
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return r;
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return r;
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return r;
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r.toDouble();
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return 0.;
		return r.front().toDouble();
	}
	case PIVariant::pivEnum: {
		PIVariantTypes::Enum r;
		ba >> r;
		return double(r.selectedValue());
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return r.size() > 0 ? r[0] : 0.;
	}
	case PIVariant::pivCustom: return getAsValue<double>(*this);
	default: break;
	}
	return 0.;
}


//! \~\brief
//! \~english Returns variant content as long double
//! \~russian Возвращает содержимое как long double
//!
//! \~\details
//! \~english
//! In case of numeric types returns long double value. \n
//! In case of String type returns \a PIString::toLDouble(). \n
//! In case of StringList type returns \b 0. if string list is empty,
//! otherwise returns \a PIString::toLDouble() of first string. \n
//! In case of other types returns \b 0. .
//!
//! \~russian
//! Для численных типов возвращает вещественное значение. \n
//! Для типа String возвращает \a PIString::toLDouble(). \n
//! Для типа StringList возвращает \b 0. если массив пустой, \n
//! иначе возвращает \a PIString::toLDouble() первой строки. \n
//! Для остальных типов возвращает \b 0. .
//!
ldouble PIVariant::toLDouble() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return r;
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return r;
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return r;
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return r;
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return r;
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return r;
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return r;
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return r.real();
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r.toLDouble();
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return 0.;
		return r.front().toLDouble();
	}
	case PIVariant::pivEnum: {
		PIVariantTypes::Enum r;
		ba >> r;
		return ldouble(r.selectedValue());
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return r.size() > 0 ? r[0] : 0.;
	}
	case PIVariant::pivCustom: return getAsValue<float>(*this);
	default: break;
	}
	return 0.;
}


complexf PIVariant::toComplexF() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return complexf(r.real(), r.imag());
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return complexf(r.real(), r.imag());
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return complexf(r.size() > 0 ? r[0] : 0., r.size() > 1 ? r[1] : 0.);
	}
	case PIVariant::pivCustom: return getAsValue<complexf>(*this);
	default: return complexf(toFloat(), 0.f);
	}
	return complexf();
}


complexd PIVariant::toComplexD() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return complexd(r.real(), r.imag());
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return r;
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return complexd(r.real(), r.imag());
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return complexd(r.size() > 0 ? r[0] : 0., r.size() > 1 ? r[1] : 0.);
	}
	case PIVariant::pivCustom: return getAsValue<complexd>(*this);
	default: return complexd(toDouble(), 0.f);
	}
	return complexd();
}


complexld PIVariant::toComplexLD() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivComplexf: {
		complexf r;
		return complexld(r.real(), r.imag());
		ba >> r;
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return complexld(r.real(), r.imag());
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return r;
	}
	case PIVariant::pivMathVector: {
		PIMathVectord r;
		ba >> r;
		return complexld(r.size() > 0 ? r[0] : 0., r.size() > 1 ? r[1] : 0.);
	}
	case PIVariant::pivCustom: return getAsValue<complexld>(*this);
	default: return complexld(toLDouble(), 0.f);
	}
	return complexld();
}


//! \~\brief
//! \~english Returns variant content as time
//! \~russian Возвращает содержимое как время
//!
//! \~\details
//! \~english
//! In case of Time type returns time value. \n
//! In case of DateTime type returns time part of value. \n
//! In case of other types returns \a PITime().
//!
//! \~russian
//! Для типа Time возвращает время. \n
//! Для типа DateTime возвращает часть времени. \n
//! Для остальных типов возвращает \a PITime().
//!
PITime PIVariant::toTime() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		return PITime::fromString(r);
	}
	if (_type == PIVariant::pivTime) {
		PITime r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivDateTime) {
		PIDateTime r;
		ba >> r;
		return r.time();
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PITime>(*this);
	}
	return PITime();
}


//! \~\brief
//! \~english Returns variant content as date
//! \~russian Возвращает содержимое как дата
//!
//! \~\details
//! \~english
//! In case of Date type returns date value. \n
//! In case of DateTime type returns date part of value. \n
//! In case of other types returns \a PIDate().
//!
//! \~russian
//! Для типа Date возвращает дату. \n
//! Для типа DateTime возвращает часть даты. \n
//! Для остальных типов возвращает \a PIDate().
//!
PIDate PIVariant::toDate() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		return PIDate::fromString(r);
	}
	if (_type == PIVariant::pivDate) {
		PIDate r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivDateTime) {
		PIDateTime r;
		ba >> r;
		return r.date();
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIDate>(*this);
	}
	return PIDate();
}


//! \~\brief
//! \~english Returns variant content as date and time
//! \~russian Возвращает содержимое как дата и время
//!
//! \~\details
//! \~english
//! In case of Time type returns time value with null date. \n
//! In case of Date type returns date value with null time. \n
//! In case of DateTime type returns date and time. \n
//! In case of other types returns \a PIDateTime().
//!
//! \~russian
//! Для типа Time возвращает время без даты. \n
//! Для типа Date возвращает дату без времени. \n
//! Для типа DateTime возвращает время и дату. \n
//! Для остальных типов возвращает \a PIDateTime().
//!
PIDateTime PIVariant::toDateTime() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		return PIDateTime::fromString(r);
	}
	if (_type == PIVariant::pivTime) {
		PITime r;
		ba >> r;
		return PIDateTime(r);
	}
	if (_type == PIVariant::pivDate) {
		PIDate r;
		ba >> r;
		return PIDateTime(r);
	}
	if (_type == PIVariant::pivDateTime) {
		PIDateTime r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIDateTime>(*this);
	}
	return PIDateTime();
}


//! \~\brief
//! \~english Returns variant content as system time
//! \~russian Возвращает содержимое как системное время
//!
//! \~\details
//! \~english
//! In case of SystemTime type returns system time. \n
//! In case of String type returns \a PISystemTime::fromString(). \n
//! In case of DateTime type returns \a PIDateTime::toSystemTime(). \n
//! In case of other types returns \a PISystemTime::fromSeconds() from \a toDouble().
//!
//! \~russian
//! Для типа SystemTime возвращает системное время. \n
//! Для типа String возвращает \a PISystemTime::fromString(). \n
//! Для типа DateTime возвращает \a PIDateTime::toSystemTime(). \n
//! Для остальных типов возвращает \a PISystemTime::fromSeconds() от \a toDouble().
//!
PISystemTime PIVariant::toSystemTime() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivSystemTime) {
		PISystemTime r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		return PISystemTime::fromString(r);
	}
	if (_type == PIVariant::pivDateTime) {
		PIDateTime r;
		ba >> r;
		return r.toSystemTime();
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PISystemTime>(*this);
	}
	return PISystemTime::fromSeconds(toDouble());
}


//! \~\brief
//! \~english Returns variant content as string
//! \~russian Возвращает содержимое как строка
//!
//! \~\details
//! \~english
//! In case of numeric types returns \a PIString::fromNumber(). \n
//! In case of String type returns string value. \n
//! In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n
//! In case of BitArray or ByteArray types returns number of bits/bytes. \n
//! In case of Time, Date or DateTime types returns toString() of this values. \n
//! In case of SystemTime types returns \a PISystemTime::toString(). \n
//! In case of NetworkAddress types returns "i.i.i.i:p". \n
//! ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
//! In case of other types returns \b "".
//!
//! \~russian
//! Для численных типов возвращает \a PIString::fromNumber(). \n
//! Для типа String возвращает строку. \n
//! Для типа StringList возвращает объединенную строку ("(" + PIStringList::join("; ") + ")"). \n
//! Для типов BitArray или ByteArray возвращает количество бит/байт. \n
//! Для типов Time, Date или DateTime возвращает toString(). \n
//! Для типов SystemTime возвращает \a PISystemTime::toString(). \n
//! Для типов NetworkAddress возвращает "i.i.i.i:p". \n
//! Для остальных типов возвращает \b "".
//!
PIString PIVariant::toString() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::pivBool: {
		bool r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivChar: {
		char r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivUChar: {
		uchar r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivShort: {
		short r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivUShort: {
		ushort r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivInt: {
		int r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivUInt: {
		uint r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivLLong: {
		llong r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivULLong: {
		ullong r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivFloat: {
		float r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivDouble: {
		double r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivLDouble: {
		ldouble r;
		ba >> r;
		return PIString::fromNumber(r);
	}
	case PIVariant::pivComplexf: {
		complexf r;
		ba >> r;
		return "(" + PIString::fromNumber(r.real()) + ";" + PIString::fromNumber(r.imag()) + ")";
	}
	case PIVariant::pivComplexd: {
		complexd r;
		ba >> r;
		return "(" + PIString::fromNumber(r.real()) + ";" + PIString::fromNumber(r.imag()) + ")";
	}
	case PIVariant::pivComplexld: {
		complexld r;
		ba >> r;
		return "(" + PIString::fromNumber(r.real()) + ";" + PIString::fromNumber(r.imag()) + ")";
	}
	case PIVariant::pivTime: {
		PITime r;
		ba >> r;
		return r.toString();
	}
	case PIVariant::pivDate: {
		PIDate r;
		ba >> r;
		return r.toString();
	}
	case PIVariant::pivDateTime: {
		PIDateTime r;
		ba >> r;
		return r.toString();
	}
	case PIVariant::pivSystemTime: {
		PISystemTime r;
		ba >> r;
		return r.toString();
	}
	case PIVariant::pivString: {
		PIString r;
		ba >> r;
		return r;
	}
	case PIVariant::pivStringList: {
		PIStringList r;
		ba >> r;
		if (r.isEmpty()) return PIString();
		return r.join("%|%");
	}
	case PIVariant::pivEnum: {
		PIVariantTypes::Enum r;
		ba >> r;
		return r.toString();
	}
	case PIVariant::pivFile: {
		PIVariantTypes::File r;
		ba >> r;
		return r.file;
	}
	case PIVariant::pivDir: {
		PIVariantTypes::Dir r;
		ba >> r;
		return r.dir;
	}
	case PIVariant::pivColor: {
		PIVariantTypes::Color r;
		ba >> r;
		return r.toName();
	}
	case PIVariant::pivIODevice: {
		PIVariantTypes::IODevice r;
		ba >> r;
		return "IODevice";
	} // TODO
	case PIVariant::pivPoint: {
		PIPointd r;
		ba >> r;
		return PIString::fromNumber(r.x) + ";" + PIString::fromNumber(r.y);
	} break;
	case PIVariant::pivRect: {
		PIRectd r;
		ba >> r;
		return PIString::fromNumber(r.left()) + ";" + PIString::fromNumber(r.bottom()) + ";" + PIString::fromNumber(r.width()) + ";" +
		       PIString::fromNumber(r.height());
	} break;
	case PIVariant::pivLine: {
		PILined r;
		ba >> r;
		return PIString::fromNumber(r.p0.x) + ";" + PIString::fromNumber(r.p0.y) + ";" + PIString::fromNumber(r.p1.x) + ";" +
		       PIString::fromNumber(r.p1.y);
	} break;
	case PIVariant::pivNetworkAddress: {
		PINetworkAddress r;
		ba >> r;
		return r.toString();
	} break;
	case PIVariant::pivCustom: return getAsValue<PIString>(*this);
	default: break;
	}
	return PIString();
}


//! \~\brief
//! \~english Returns variant content as strings list
//! \~russian Возвращает содержимое как массив строк
//!
//! \~\details
//! \~english
//! In case of StringList type returns strings list value. \n
//! In case of other types returns \a PIStringList with one string \a toString().
//!
//! \~russian
//! Для типа StringList возвращает массив строк. \n
//! Для остальных типов возвращает \a PIStringList с одной строкой \a toString().
//!
PIStringList PIVariant::toStringList() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivStringList) {
		PIStringList r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivEnum) {
		PIVariantTypes::Enum r;
		ba >> r;
		return r.names();
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIStringList>(*this);
	}
	return PIStringList(toString());
}


//! \~\brief
//! \~english Returns variant content as bit array
//! \~russian Возвращает содержимое как массив битов
//!
//! \~\details
//! \~english
//! In case of BitArray type returns bit array value. \n
//! In case of other types returns \a PIBitArray from \a toLLong() value.
//!
//! \~russian
//! Для типа BitArray возвращает массив битов. \n
//! Для остальных типов возвращает \a PIBitArray от значения \a toLLong().
//!
PIBitArray PIVariant::toBitArray() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivBitArray) {
		PIBitArray r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIBitArray>(*this);
	}
	return PIBitArray(ullong(toLLong()));
}


//! \~\brief
//! \~english Returns variant content as byte array
//! \~russian Возвращает содержимое как массив байтов
//!
//! \~\details
//! \~english
//! In case of ByteArray type returns byte array value. \n
//! In case of other types returns empty \a PIByteArray.
//!
//! \~russian
//! Для типа ByteArray возвращает массив байтов. \n
//! Для остальных типов возвращает пустой \a PIByteArray.
//!
PIByteArray PIVariant::toByteArray() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivByteArray) {
		PIByteArray r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIByteArray>(*this);
	}
	return PIByteArray();
}


//! \~\brief
//! \~english Returns variant content as enum
//! \~russian Возвращает содержимое как перечисление
//!
//! \~\details
//! \~english
//! In case of Enum type returns enum value. \n
//! In case of String returns Enum with one member. \n
//! In case of StringList returns Enum with corresponding members. \n
//! In case of other types returns empty Enum.
//!
//! \~russian
//! Для типа Enum возвращает перечисление. \n
//! Для типа String возвращает Enum с одним членом. \n
//! Для типа StringList возвращает Enum с членами по строкам. \n
//! Для остальных типов возвращает пустой Enum.
//!
PIVariantTypes::Enum PIVariant::toEnum() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivEnum) {
		PIVariantTypes::Enum r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivString) {
		PIString v;
		ba >> v;
		return PIVariantTypes::Enum::fromString(v);
	}
	if (_type == PIVariant::pivStringList) {
		PIStringList v;
		ba >> v;
		PIVariantTypes::Enum r;
		r << v;
		return r;
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIVariantTypes::Enum>(*this);
	}
	return PIVariantTypes::Enum();
}


//! \~\brief
//! \~english Returns variant content as file
//! \~russian Возвращает содержимое как файл
//!
//! \~\details
//! \~english
//! In case of File type returns file value. \n
//! In case of String returns File with string value path. \n
//! In case of other types returns empty File.
//!
//! \~russian
//! Для типа File возвращает файл. \n
//! Для типа String возвращает File с путем значения строки. \n
//! Для остальных типов возвращает пустой File.
//!
PIVariantTypes::File PIVariant::toFile() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivFile) {
		PIVariantTypes::File r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivString) {
		PIString v;
		ba >> v;
		PIVariantTypes::File r;
		r.file = v;
		return r;
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIVariantTypes::File>(*this);
	}
	return PIVariantTypes::File();
}


//! \~\brief
//! \~english Returns variant content as dir
//! \~russian Возвращает содержимое как директория
//!
//! \~\details
//! \~english
//! In case of Dir type returns dir value. \n
//! In case of String returns Dir with string value path. \n
//! In case of other types returns empty Dir.
//!
//! \~russian
//! Для типа Dir возвращает директорию. \n
//! Для типа String возвращает Dir с путем значения строки. \n
//! Для остальных типов возвращает пустой Dir.
//!
PIVariantTypes::Dir PIVariant::toDir() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivDir) {
		PIVariantTypes::Dir r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivString) {
		PIString v;
		ba >> v;
		PIVariantTypes::Dir r;
		r.dir = v;
		return r;
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIVariantTypes::Dir>(*this);
	}
	return PIVariantTypes::Dir();
}


//! \~\brief
//! \~english Returns variant content as color
//! \~russian Возвращает содержимое как цвет
//!
//! \~\details
//! \~english
//! In case of Color type returns color value. \n
//! In case of Int returns color with int value. \n
//! In case of other types returns empty Color.
//!
//! \~russian
//! Для типа Color возвращает цвет. \n
//! Для типа Int возвращает цвет с целочисленным значением. \n
//! Для остальных типов возвращает пустой Color.
//!
PIVariantTypes::Color PIVariant::toColor() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		return PIVariantTypes::Color::fromString(r);
	}
	if (_type == PIVariant::pivColor) {
		PIVariantTypes::Color r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivInt) {
		int v;
		ba >> v;
		return PIVariantTypes::Color(v);
	}
	if (_type == PIVariant::pivCustom) {
		return getAsValue<PIVariantTypes::Color>(*this);
	}
	return PIVariantTypes::Color();
}


//! \~\brief
//! \~english Returns variant content as IODevice
//! \~russian Возвращает содержимое как IODevice
//!
//! \~\details
//! \~english
//! In case of IODevice type returns IODevice value. \n
//! In case of other types returns empty IODevice.
//!
//! \~russian
//! Для типа IODevice возвращает IODevice. \n
//! Для остальных типов возвращает пустой IODevice.
//!
PIVariantTypes::IODevice PIVariant::toIODevice() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivIODevice) {
		PIVariantTypes::IODevice r;
		ba >> r;
		return r;
	}
	return PIVariantTypes::IODevice();
}


//! \~\brief
//! \~english Returns variant content as point
//! \~russian Возвращает содержимое как точка
//!
//! \~\details
//! \~english
//! In case of Point type returns point value. \n
//! In case of other types returns empty PIPointd.
//!
//! \~russian
//! Для типа Point возвращает точку. \n
//! Для остальных типов возвращает пустую PIPointd.
//!
PIPointd PIVariant::toPoint() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivPoint) {
		PIPointd r;
		ba >> r;
		return r;
	}
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		PIStringList l = r.split(';');
		if (l.size() >= 2) return PIPointd(l[0].toDouble(), l[1].toDouble());
	}
	if (_type == PIVariant::pivMathVector) {
		PIMathVectord r;
		ba >> r;
		PIPointd ret;
		if (r.size() > 0) ret.x = r[0];
		if (r.size() > 1) ret.y = r[1];
		return ret;
	}
	return PIPointd();
}


//! \~\brief
//! \~english Returns variant content as rect
//! \~russian Возвращает содержимое как прямоугольник
//!
//! \~\details
//! \~english
//! In case of Rect type returns rect value. \n
//! In case of other types returns empty PIRectd.
//!
//! \~russian
//! Для типа Rect возвращает прямоугольник. \n
//! Для остальных типов возвращает пустой PIRectd.
//!
PIRectd PIVariant::toRect() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		PIStringList l = r.split(';');
		if (l.size() >= 4) return PIRectd(l[0].toDouble(), l[1].toDouble(), l[2].toDouble(), l[3].toDouble());
	}
	if (_type == PIVariant::pivRect) {
		PIRectd r;
		ba >> r;
		return r;
	}
	return PIRectd();
}


//! \~\brief
//! \~english Returns variant content as line
//! \~russian Возвращает содержимое как линия
//!
//! \~\details
//! \~english
//! In case of Line type returns line value. \n
//! In case of other types returns empty PILined.
//!
//! \~russian
//! Для типа Line возвращает линию. \n
//! Для остальных типов возвращает пустую PILined.
//!
PILined PIVariant::toLine() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		PIStringList l = r.split(';');
		if (l.size() >= 4) return PILined(l[0].toDouble(), l[1].toDouble(), l[2].toDouble(), l[3].toDouble());
	}
	if (_type == PIVariant::pivLine) {
		PILined r;
		ba >> r;
		return r;
	}
	return PILined();
}


//! \~\brief
//! \~english Returns variant content as PINetworkAddress
//! \~russian Возвращает содержимое как PINetworkAddress
//!
//! \~\details
//! \~english
//! In case of NetworkAddress type returns address. \n
//! In case of String type returns address from "i.i.i.i:p". \n
//! In case of other types returns empty PINetworkAddress.
//!
//! \~russian
//! Для типа NetworkAddress возвращает адрес. \n
//! Для типа String возвращает адрес из формата "i.i.i.i:p". \n
//! Для остальных типов возвращает пустой PINetworkAddress.
//!
PINetworkAddress PIVariant::toNetworkAddress() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivString) {
		PIString r;
		ba >> r;
		return PINetworkAddress(r);
	}
	if (_type == PIVariant::pivNetworkAddress) {
		PINetworkAddress r;
		ba >> r;
		return r;
	}
	return PINetworkAddress();
}


//! \~\brief
//! \~english Returns variant content as math vector
//! \~russian Возвращает содержимое как вектор
//!
//! \~\details
//! \~english
//! In case of MathVector type returns rect value. \n
//! In case of other types returns empty PIMathVectord.
//!
//! \~russian
//! Для типа MathVector возвращает вектор. \n
//! Для остальных типов возвращает пустой PIMathVectord.
//!
PIMathVectord PIVariant::toMathVector() const {
	PIMathVectord ret;
	PIByteArray ba(_content);
	if (_type == PIVariant::pivComplexf) {
		complexf r;
		ba >> r;
		ret.resize(2);
		ret[0] = r.real();
		ret[1] = r.imag();
		return ret;
	}
	if (_type == PIVariant::pivComplexd) {
		complexd r;
		ba >> r;
		ret.resize(2);
		ret[0] = r.real();
		ret[1] = r.imag();
		return ret;
	}
	if (_type == PIVariant::pivComplexld) {
		complexld r;
		ba >> r;
		ret.resize(2);
		ret[0] = r.real();
		ret[1] = r.imag();
		return ret;
	}
	if (_type == PIVariant::pivMathVector) {
		ba >> ret;
		return ret;
	}
	if (_type == PIVariant::pivPoint) {
		PIPointd r;
		ba >> r;
		ret.resize(2);
		ret[0] = r.x;
		ret[1] = r.y;
		return ret;
	}
	return ret;
}


//! \~\brief
//! \~english Returns variant content as math matrix
//! \~russian Возвращает содержимое как матрица
//!
//! \~\details
//! \~english
//! In case of MathMatrix type returns rect value. \n
//! In case of other types returns empty PIMathMatrixd.
//!
//! \~russian
//! Для типа MathMatrix возвращает матрицу. \n
//! Для остальных типов возвращает пустую PIMathMatrixd.
//!
PIMathMatrixd PIVariant::toMathMatrix() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::pivMathMatrix) {
		PIMathMatrixd r;
		ba >> r;
		return r;
	}
	return PIMathMatrixd();
}
