/*
	PIP - Platform Independent Primitives
	Variant type
	Copyright (C) 2016  Ivan Pelipenko peri4ko@gmail.com

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "pivariant.h"


/** \class PIVariant
 * \brief Variant type
 * \details
 * \section PIVariant_sec0 Synopsis
 * 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.
 *
 * \section PIVariant_sec1 Usage
 * %PIVariant useful if you want pass many variables with different types in
 * single array, e.g.:
 * \code{cpp}
 * PIVector<PIVariant> array;
 * array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF");
 * piCout << array;
 * piForeachC (PIVariant & i, array)
 * 	piCout << i.toInt();
 * \endcode
 * Result:
 * \code{cpp}
 * {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)}
 * 10
 * 1
 * 1
 * 255
 * \endcode
 * */

#ifdef CUSTOM_PIVARIANT
PIMap<PIString, __PIVariantInfo__ * > * __PIVariantInfoStorage__::map = 0;
#endif


PIVariant::PIVariant() {
	_type = PIVariant::Invalid;
}


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


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


PIVariant::Type PIVariant::typeFromName(const PIString & tname) {
	PIString s = tname.trimmed().toLowerCase().replaceAll(" ", "");
	if (s == "bool" || s == "boolean") return PIVariant::Bool;
	if (s == "char" || s == "sbyte") return PIVariant::Char;
	if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword") return PIVariant::Short;
	if (s == "int" || s == "signed" || s == "signedint") return PIVariant::Int;
	if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::Int;
	if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword") return PIVariant::LLong;
	if (s == "uchar" || s == "byte") return PIVariant::UChar;
	if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word") return PIVariant::UShort;
	if (s == "uint" || s == "unsigned" || s == "unsignedint") return PIVariant::UInt;
	if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::UInt;
	if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword") return PIVariant::ULLong;
	if (s == "float") return PIVariant::Float;
	if (s == "double" || s == "real") return PIVariant::Double;
	if (s == "ldouble" || s == "longdouble") return PIVariant::LDouble;
	if (s == "complexd" || s == "complex<double>") return PIVariant::Complexd;
	if (s == "complexld" || s == "complex<ldouble>" || s == "complex<longdouble>") return PIVariant::Complexld;
	if (s == "pibitarray" || s == "bitarray") return PIVariant::BitArray;
	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::ByteArray;
	if (s == "pistring" || s == "string") return PIVariant::String;
	if (s == "pistringlist" || s == "stringlist" || s == "vector<string>" || s == "vector<pistring>" || s == "pivector<string>" || s == "pivector<pistring>") return PIVariant::StringList;
	if (s == "pitime" || s == "time") return PIVariant::Time;
	if (s == "pidate" || s == "date") return PIVariant::Date;
	if (s == "pidatetime" || s == "datetime") return PIVariant::DateTime;
	if (s == "pisystemtime" || s == "systemtime") return PIVariant::SystemTime;
	return PIVariant::Invalid;
}


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


PIString PIVariant::typeName(PIVariant::Type type) {
	switch (type) {
	case PIVariant::Bool: return "Bool";
	case PIVariant::Char: return "Char";
	case PIVariant::UChar: return "UChar";
	case PIVariant::Short: return "Short";
	case PIVariant::UShort: return "UShort";
	case PIVariant::Int: return "Int";
	case PIVariant::UInt: return "UInt";
	case PIVariant::LLong: return "LLong";
	case PIVariant::ULLong: return "ULLong";
	case PIVariant::Float: return "Float";
	case PIVariant::Double: return "Double";
	case PIVariant::LDouble: return "LDouble";
	case PIVariant::Complexd: return "Complexd";
	case PIVariant::Complexld: return "Complexld";
	case PIVariant::BitArray: return "BitArray";
	case PIVariant::ByteArray: return "ByteArray";
	case PIVariant::String: return "String";
	case PIVariant::StringList: return "StringList";
	case PIVariant::Time: return "Time";
	case PIVariant::Date: return "Date";
	case PIVariant::DateTime: return "DateTime";
	case PIVariant::SystemTime: return "SystemTime";
	case PIVariant::Custom: return "Custom";
	default: break;
	}
	return "Invalid";
}


/** \brief Returns variant content as boolean
 * \details 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. */
bool PIVariant::toBool() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r != 0;}
	case PIVariant::UChar: {uchar r; ba >> r; return r != 0;}
	case PIVariant::Short: {short r; ba >> r; return r != 0;}
	case PIVariant::UShort: {ushort r; ba >> r; return r != 0;}
	case PIVariant::Int: {int r; ba >> r; return r != 0;}
	case PIVariant::UInt: {uint r; ba >> r; return r != 0;}
	case PIVariant::LLong: {llong r; ba >> r; return r != 0;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r != 0;}
	case PIVariant::Float: {float r; ba >> r; return r > 0.f;}
	case PIVariant::Double: {double r; ba >> r; return r > 0.;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r > 0.;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real() != 0;}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real() != 0;}
	case PIVariant::String: {PIString r; ba >> r; return r.toBool();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return false; return r.front().toBool();}
	case PIVariant::Custom:
		return getAsValue<bool>(*this);
	default: break;
	}
	return false;
}



/** \brief Returns variant content as int
 * \details 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. */
int PIVariant::toInt() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toInt();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0; return r.front().toInt();}
	case PIVariant::Custom:
		return getAsValue<int>(*this);
	default: break;
	}
	return 0;
}


/** \brief Returns variant content as long long
 * \details 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. */
llong PIVariant::toLLong() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toLLong();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0L; return r.front().toLLong();}
	case PIVariant::Custom:
		return getAsValue<llong>(*this);
	}
	return 0L;
}


/** \brief Returns variant content as float
 * \details 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. */
float PIVariant::toFloat() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toFloat();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0.f; return r.front().toFloat();}
	case PIVariant::Custom:
		return getAsValue<float>(*this);
	}
	return 0.f;
}


/** \brief Returns variant content as double
 * \details 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.. */
double PIVariant::toDouble() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toDouble();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0.; return r.front().toDouble();}
	case PIVariant::Custom:
		return getAsValue<double>(*this);
	}
	return 0.;
}


/** \brief Returns variant content as long double
 * \details 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.. */
ldouble PIVariant::toLDouble() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toLDouble();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return 0.; return r.front().toLDouble();}
	case PIVariant::Custom:
		return getAsValue<float>(*this);
	}
	return 0.;
}


/** \brief Returns variant content as complex
 * \details In case of numeric types returns complex 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.. */
complexd PIVariant::toComplexd() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toDouble();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return complexd_0; return r.front().toDouble();}
	case PIVariant::Custom:
		return getAsValue<complexd>(*this);
	}
	return complexd_0;
}


/** \brief Returns variant content as long complex
 * \details In case of numeric types returns long complex 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.. */
complexld PIVariant::toComplexld() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return r;}
	case PIVariant::Char: {char r; ba >> r; return r;}
	case PIVariant::UChar: {uchar r; ba >> r; return r;}
	case PIVariant::Short: {short r; ba >> r; return r;}
	case PIVariant::UShort: {ushort r; ba >> r; return r;}
	case PIVariant::Int: {int r; ba >> r; return r;}
	case PIVariant::UInt: {uint r; ba >> r; return r;}
	case PIVariant::LLong: {llong r; ba >> r; return r;}
	case PIVariant::ULLong: {ullong r; ba >> r; return r;}
	case PIVariant::Float: {float r; ba >> r; return r;}
	case PIVariant::Double: {double r; ba >> r; return r;}
	case PIVariant::LDouble: {ldouble r; ba >> r; return r;}
	case PIVariant::Complexd: {complexd r; ba >> r; return r.real();}
	case PIVariant::Complexld: {complexld r; ba >> r; return r.real();}
	case PIVariant::String: {PIString r; ba >> r; return r.toLDouble();}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return complexld_0; return r.front().toLDouble();}
	case PIVariant::Custom:
		return getAsValue<complexld>(*this);
	}
	return complexld_0;
}


/** \brief Returns variant content as time
 * \details 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(). */
PITime PIVariant::toTime() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::Time) {PITime r; ba >> r; return r;}
	if (_type == PIVariant::DateTime) {PIDateTime r; ba >> r; return r.time();}
	if (_type == PIVariant::Custom) {return getAsValue<PITime>(*this);}
	return PITime();
}


/** \brief Returns variant content as date
 * \details 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(). */
PIDate PIVariant::toDate() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::Date) {PIDate r; ba >> r; return r;}
	if (_type == PIVariant::DateTime) {PIDateTime r; ba >> r; return r.date();}
	if (_type == PIVariant::Custom) {return getAsValue<PIDate>(*this);}
	return PIDate();
}


/** \brief Returns variant content as date and time
 * \details 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(). */
PIDateTime PIVariant::toDateTime() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::Time) {PITime r; ba >> r; return PIDateTime(r);}
	if (_type == PIVariant::Date) {PIDate r; ba >> r; return PIDateTime(r);}
	if (_type == PIVariant::DateTime) {PIDateTime r; ba >> r; return r;}
	if (_type == PIVariant::Custom) {return getAsValue<PIDateTime>(*this);}
	return PIDateTime();
}


/** \brief Returns variant content as system time
 * \details In case of SystemTime type returns system time. \n
 * In case of other types returns \a PISystemTime::fromSeconds() from
 * double value of variant content. */
PISystemTime PIVariant::toSystemTime() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::SystemTime) {PISystemTime r; ba >> r; return r;}
	if (_type == PIVariant::Custom) {return getAsValue<PISystemTime>(*this);}
	return PISystemTime::fromSeconds(toDouble());
}


/** \brief Returns variant content as string
 * \details 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 second and nanoseconds of time
 * ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n
 * In case of other types returns \b "". */
PIString PIVariant::toString() const {
	PIByteArray ba(_content);
	switch (_type) {
	case PIVariant::Bool: {bool r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::Char: {char r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::UChar: {uchar r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::Short: {short r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::UShort: {ushort r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::Int: {int r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::UInt: {uint r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::LLong: {llong r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::ULLong: {ullong r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::Float: {float r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::Double: {double r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::LDouble: {ldouble r; ba >> r; return PIString::fromNumber(r);}
	case PIVariant::Complexd: {complexd r; ba >> r; return PIString::fromNumber(r.real());}
	case PIVariant::Complexld: {complexld r; ba >> r; return PIString::fromNumber(r.real());}
	case PIVariant::String: {PIString r; ba >> r; return r;}
	case PIVariant::StringList: {PIStringList r; ba >> r; if (r.isEmpty()) return PIString(); return r.front();}
	case PIVariant::Custom:
		return getAsValue<PIString>(*this);
	}
	return PIString();
}


/** \brief Returns variant content as strings list
 * \details In case of StringList type returns strings list value. \n
 * In case of other types returns \a PIStringList with one string value of variant content. */
PIStringList PIVariant::toStringList() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::StringList) {PIStringList r; ba >> r; return r;}
	if (_type == PIVariant::Custom) {return getAsValue<PIStringList>(*this);}
	return PIStringList(toString());
}


/** \brief Returns variant content as bit array
 * \details In case of BitArray type returns bit array value. \n
 * In case of other types returns \a PIBitArray from \a toLLong() value. */
PIBitArray PIVariant::toBitArray() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::BitArray) {PIBitArray r; ba >> r; return r;}
	if (_type == PIVariant::Custom) {return getAsValue<PIBitArray>(*this);}
	return PIBitArray(ullong(toLLong()));
}


/** \brief Returns variant content as byte array
 * \details In case of ByteArray type returns byte array value. \n
 * In case of other types returns empty \a PIByteArray. */
PIByteArray PIVariant::toByteArray() const {
	PIByteArray ba(_content);
	if (_type == PIVariant::ByteArray) {PIByteArray r; ba >> r; return r;}
	if (_type == PIVariant::Custom) {return getAsValue<PIByteArray>(*this);}
	return PIByteArray();
}
