mirror of https://github.com/KLayout/klayout.git
2512 lines
65 KiB
C++
2512 lines
65 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
#include "tlVariant.h"
|
|
#include "tlInternational.h"
|
|
#include "tlString.h"
|
|
|
|
#include <string.h>
|
|
#include <limits>
|
|
#include <QVariant>
|
|
#include <QStringList>
|
|
|
|
// the Qt classes supported by QVariant:
|
|
#include <QBitArray>
|
|
#include <QBitmap>
|
|
#include <QBrush>
|
|
#include <QByteArray>
|
|
#include <QChar>
|
|
#include <QColor>
|
|
#include <QCursor>
|
|
#include <QDate>
|
|
#include <QDateTime>
|
|
#if QT_VERSION >= 0x040600
|
|
# include <QEasingCurve>
|
|
#endif
|
|
#include <QFont>
|
|
#include <QVariantHash>
|
|
#include <QIcon>
|
|
#include <QImage>
|
|
#include <QKeySequence>
|
|
#include <QLine>
|
|
#include <QLineF>
|
|
#include <QVariantList>
|
|
#include <QLocale>
|
|
#include <QTransform>
|
|
#include <QMatrix4x4>
|
|
#include <QPalette>
|
|
#include <QPen>
|
|
#include <QPixmap>
|
|
#include <QPoint>
|
|
#include <QPointF>
|
|
#include <QPolygon>
|
|
#include <QQuaternion>
|
|
#include <QRect>
|
|
#include <QRectF>
|
|
#include <QRegExp>
|
|
#include <QRegion>
|
|
#include <QSize>
|
|
#include <QSizeF>
|
|
#include <QSizePolicy>
|
|
#include <QString>
|
|
#include <QStringList>
|
|
#include <QTextFormat>
|
|
#include <QTextLength>
|
|
#include <QTime>
|
|
#include <QUrl>
|
|
#include <QVector2D>
|
|
#include <QVector3D>
|
|
#include <QVector4D>
|
|
|
|
namespace tl
|
|
{
|
|
|
|
// --------------------------------------------------------------------
|
|
// Helper for converting int128 from and to string
|
|
|
|
#if defined(HAVE_64BIT_COORD)
|
|
|
|
template <>
|
|
TL_PUBLIC bool test_extractor_impl (tl::Extractor &ex, __int128 &v)
|
|
{
|
|
__int128 x = 0;
|
|
bool neg = ex.test("-");
|
|
while (*ex <= '9' && *ex >= '0') {
|
|
x = x * 10 + __int128 (*ex - '0');
|
|
++ex;
|
|
}
|
|
v = neg ? -x : x;
|
|
return true;
|
|
}
|
|
|
|
template <>
|
|
TL_PUBLIC void extractor_impl (tl::Extractor &ex, __int128 &v)
|
|
{
|
|
if (! test_extractor_impl (ex, v)) {
|
|
ex.error (tl::to_string (QObject::tr ("Expected a value specification")));
|
|
}
|
|
}
|
|
|
|
TL_PUBLIC std::string to_string (__int128 v)
|
|
{
|
|
if (v < 0) {
|
|
return std::string ("-") + to_string (-v);
|
|
}
|
|
|
|
std::string res;
|
|
do {
|
|
res += '0' + char (v % __int128 (10));
|
|
v /= __int128 (10);
|
|
} while (v > 0);
|
|
std::reverse (res.begin (), res.end ());
|
|
return res;
|
|
}
|
|
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------
|
|
// Implementation of tl::VariantUserClassBase
|
|
|
|
struct VariantUserClassTableKey
|
|
{
|
|
VariantUserClassTableKey (const std::type_info &t, bool c)
|
|
: type (&t), is_const (c)
|
|
{
|
|
}
|
|
|
|
bool operator< (const VariantUserClassTableKey &k) const
|
|
{
|
|
if (is_const != k.is_const) {
|
|
return is_const < k.is_const;
|
|
}
|
|
if (*type != *k.type) {
|
|
return type->before (*k.type);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool operator== (const VariantUserClassTableKey &k) const
|
|
{
|
|
return is_const == k.is_const && *type == *k.type;
|
|
}
|
|
|
|
const std::type_info *type;
|
|
bool is_const;
|
|
};
|
|
|
|
static std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *> *sp_class_table = 0;
|
|
static std::map <std::string, const VariantUserClassBase *> s_user_type_by_name;
|
|
|
|
void
|
|
VariantUserClassBase::clear_class_table ()
|
|
{
|
|
s_user_type_by_name.clear ();
|
|
}
|
|
|
|
std::string
|
|
VariantUserClassBase::translate_class_name (const std::string &lc_clsname)
|
|
{
|
|
// Note: for pre-0.23 versions to be able to read PCell's generated by 0.23 and further
|
|
// (see #601), we need to use the old "complex type" names, specifically "layer" instead of "layerinfo".
|
|
if (lc_clsname == "layerinfo") {
|
|
return "layer";
|
|
} else {
|
|
return lc_clsname;
|
|
}
|
|
}
|
|
|
|
void
|
|
VariantUserClassBase::register_user_class (const std::string &name, const VariantUserClassBase *cls)
|
|
{
|
|
s_user_type_by_name.insert (std::make_pair (name, cls));
|
|
}
|
|
|
|
const VariantUserClassBase *
|
|
VariantUserClassBase::find_cls_by_name (const std::string &name)
|
|
{
|
|
tl_assert (! s_user_type_by_name.empty ());
|
|
|
|
std::map <std::string, const VariantUserClassBase *>::const_iterator s = s_user_type_by_name.find (tl::to_lower_case (name));
|
|
if (s == s_user_type_by_name.end ()) {
|
|
return 0;
|
|
}
|
|
|
|
return s->second;
|
|
}
|
|
|
|
const tl::VariantUserClassBase *VariantUserClassBase::instance (const std::type_info &type, bool is_const)
|
|
{
|
|
tl_assert (sp_class_table != 0);
|
|
std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *>::const_iterator c = sp_class_table->find (VariantUserClassTableKey (type, is_const));
|
|
tl_assert (c != sp_class_table->end ());
|
|
return c->second;
|
|
}
|
|
|
|
void VariantUserClassBase::register_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const)
|
|
{
|
|
if (! sp_class_table) {
|
|
sp_class_table = new std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *> ();
|
|
}
|
|
(*sp_class_table)[VariantUserClassTableKey (type, is_const)] = inst;
|
|
}
|
|
|
|
void VariantUserClassBase::unregister_instance (const tl::VariantUserClassBase *inst, const std::type_info &type, bool is_const)
|
|
{
|
|
if (sp_class_table) {
|
|
std::map<VariantUserClassTableKey, const tl::VariantUserClassBase *>::iterator c = sp_class_table->find (VariantUserClassTableKey (type, is_const));
|
|
if (c != sp_class_table->end () && c->second == inst) {
|
|
sp_class_table->erase (c);
|
|
}
|
|
if (sp_class_table->empty ()) {
|
|
delete sp_class_table;
|
|
sp_class_table = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// Implementation of tl::Variant
|
|
|
|
Variant::Variant ()
|
|
: m_type (t_nil), m_string (0)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
Variant::Variant (const QByteArray &qba)
|
|
: m_type (t_qbytearray), m_string (0)
|
|
{
|
|
m_var.m_qbytearray = new QByteArray (qba);
|
|
}
|
|
|
|
Variant::Variant (const QString &qs)
|
|
: m_type (t_qstring), m_string (0)
|
|
{
|
|
m_var.m_qstring = new QString (qs);
|
|
}
|
|
|
|
Variant::Variant (const std::string &s)
|
|
: m_type (t_stdstring), m_string (0)
|
|
{
|
|
m_var.m_stdstring = new std::string (s);
|
|
}
|
|
|
|
Variant::Variant (const char *s)
|
|
: m_type (t_string)
|
|
{
|
|
m_string = new char [strlen (s) + 1];
|
|
strcpy (m_string, s);
|
|
}
|
|
|
|
Variant::Variant (double d)
|
|
: m_type (t_double), m_string (0)
|
|
{
|
|
m_var.m_double = d;
|
|
}
|
|
|
|
Variant::Variant (float d)
|
|
: m_type (t_float), m_string (0)
|
|
{
|
|
m_var.m_float = d;
|
|
}
|
|
|
|
Variant::Variant (bool b)
|
|
: m_type (t_bool), m_string (0)
|
|
{
|
|
m_var.m_bool = b;
|
|
}
|
|
|
|
Variant::Variant (char c)
|
|
: m_type (t_char), m_string (0)
|
|
{
|
|
m_var.m_char = c;
|
|
}
|
|
|
|
Variant::Variant (signed char c)
|
|
: m_type (t_schar), m_string (0)
|
|
{
|
|
m_var.m_schar = c;
|
|
}
|
|
|
|
Variant::Variant (unsigned char c)
|
|
: m_type (t_uchar), m_string (0)
|
|
{
|
|
m_var.m_uchar = c;
|
|
}
|
|
|
|
Variant::Variant (short s)
|
|
: m_type (t_short), m_string (0)
|
|
{
|
|
m_var.m_short = s;
|
|
}
|
|
|
|
Variant::Variant (unsigned short s)
|
|
: m_type (t_ushort), m_string (0)
|
|
{
|
|
m_var.m_ushort = s;
|
|
}
|
|
|
|
Variant::Variant (int l)
|
|
: m_type (t_int), m_string (0)
|
|
{
|
|
m_var.m_int = l;
|
|
}
|
|
|
|
Variant::Variant (unsigned int l)
|
|
: m_type (t_uint), m_string (0)
|
|
{
|
|
m_var.m_uint = l;
|
|
}
|
|
|
|
Variant::Variant (long long l)
|
|
: m_type (t_longlong), m_string (0)
|
|
{
|
|
m_var.m_longlong = l;
|
|
}
|
|
|
|
Variant::Variant (unsigned long long l)
|
|
: m_type (t_ulonglong), m_string (0)
|
|
{
|
|
m_var.m_ulonglong = l;
|
|
}
|
|
|
|
#if defined(HAVE_64BIT_COORD)
|
|
Variant::Variant (__int128 l)
|
|
: m_type (t_int128), m_string (0)
|
|
{
|
|
m_var.m_int128 = l;
|
|
}
|
|
#endif
|
|
|
|
Variant::Variant (long l)
|
|
: m_type (t_long), m_string (0)
|
|
{
|
|
m_var.m_long = l;
|
|
}
|
|
|
|
Variant::Variant (unsigned long l)
|
|
: m_type (t_ulong), m_string (0)
|
|
{
|
|
m_var.m_ulong = l;
|
|
}
|
|
|
|
Variant::Variant (size_t l, bool /*dummy*/)
|
|
: m_type (t_id), m_string (0)
|
|
{
|
|
m_var.m_id = l;
|
|
}
|
|
|
|
Variant::Variant (const Variant &v)
|
|
: m_type (t_nil), m_string (0)
|
|
{
|
|
operator= (v);
|
|
}
|
|
|
|
Variant::Variant (const QVariant &v)
|
|
: m_type (t_nil), m_string (0)
|
|
{
|
|
switch (v.type ()) {
|
|
case QVariant::Invalid:
|
|
break;
|
|
case QVariant::Bool:
|
|
operator= (v.toBool ());
|
|
break;
|
|
case QVariant::ByteArray:
|
|
operator= (v.toByteArray ());
|
|
break;
|
|
case QVariant::Double:
|
|
operator= (v.toDouble ());
|
|
break;
|
|
case QVariant::Hash:
|
|
{
|
|
QHash<QString, QVariant> m = v.toHash ();
|
|
set_array ();
|
|
for (QHash<QString, QVariant>::const_iterator i = m.begin (); i != m.end (); ++i) {
|
|
insert (tl::Variant (i.key ()), tl::Variant (i.value ()));
|
|
}
|
|
}
|
|
break;
|
|
case QVariant::Int:
|
|
operator= (v.toInt ());
|
|
break;
|
|
case QVariant::List:
|
|
{
|
|
QList<QVariant> vl = v.toList ();
|
|
set_list ();
|
|
for (QList<QVariant>::const_iterator i = vl.begin (); i != vl.end (); ++i) {
|
|
push (tl::Variant (*i));
|
|
}
|
|
}
|
|
break;
|
|
case QVariant::LongLong:
|
|
operator= (v.toLongLong ());
|
|
break;
|
|
case QVariant::Map:
|
|
{
|
|
QMap<QString, QVariant> m = v.toMap ();
|
|
set_array ();
|
|
for (QMap<QString, QVariant>::const_iterator i = m.begin (); i != m.end (); ++i) {
|
|
insert (tl::Variant (i.key ()), tl::Variant (i.value ()));
|
|
}
|
|
}
|
|
break;
|
|
case QVariant::StringList:
|
|
{
|
|
QStringList sl = v.toStringList ();
|
|
set_list ();
|
|
for (QStringList::const_iterator s = sl.begin (); s != sl.end (); ++s) {
|
|
push (tl::Variant (*s));
|
|
}
|
|
}
|
|
break;
|
|
case QVariant::UInt:
|
|
operator= (v.toUInt ());
|
|
break;
|
|
case QVariant::ULongLong:
|
|
operator= (v.toULongLong ());
|
|
break;
|
|
// special types supported by QVariant too:
|
|
case QVariant::BitArray:
|
|
operator= (tl::Variant (v.value<QBitArray> ()));
|
|
break;
|
|
case QVariant::Bitmap:
|
|
operator= (tl::Variant (v.value<QBitmap> ()));
|
|
break;
|
|
case QVariant::Brush:
|
|
operator= (tl::Variant (v.value<QBrush> ()));
|
|
break;
|
|
case QVariant::Color:
|
|
operator= (tl::Variant (v.value<QColor> ()));
|
|
break;
|
|
case QVariant::Cursor:
|
|
operator= (tl::Variant (v.value<QCursor> ()));
|
|
break;
|
|
case QVariant::Date:
|
|
operator= (tl::Variant (v.value<QDate> ()));
|
|
break;
|
|
case QVariant::DateTime:
|
|
operator= (tl::Variant (v.value<QDateTime> ()));
|
|
break;
|
|
#if QT_VERSION >= 0x040700
|
|
case QVariant::EasingCurve:
|
|
operator= (tl::Variant (v.value<QEasingCurve> ()));
|
|
break;
|
|
#endif
|
|
case QVariant::Font:
|
|
operator= (tl::Variant (v.value<QFont> ()));
|
|
break;
|
|
case QVariant::Icon:
|
|
operator= (tl::Variant (v.value<QIcon> ()));
|
|
break;
|
|
case QVariant::Image:
|
|
operator= (tl::Variant (v.value<QImage> ()));
|
|
break;
|
|
case QVariant::KeySequence:
|
|
operator= (tl::Variant (v.value<QKeySequence> ()));
|
|
break;
|
|
case QVariant::Line:
|
|
operator= (tl::Variant (v.value<QLine> ()));
|
|
break;
|
|
case QVariant::LineF:
|
|
operator= (tl::Variant (v.value<QLineF> ()));
|
|
break;
|
|
case QVariant::Locale:
|
|
operator= (tl::Variant (v.value<QLocale> ()));
|
|
break;
|
|
case QVariant::Transform:
|
|
operator= (tl::Variant (v.value<QTransform> ()));
|
|
break;
|
|
case QVariant::Matrix4x4:
|
|
operator= (tl::Variant (v.value<QMatrix4x4> ()));
|
|
break;
|
|
case QVariant::Palette:
|
|
operator= (tl::Variant (v.value<QPalette> ()));
|
|
break;
|
|
case QVariant::Pen:
|
|
operator= (tl::Variant (v.value<QPen> ()));
|
|
break;
|
|
case QVariant::Pixmap:
|
|
operator= (tl::Variant (v.value<QPixmap> ()));
|
|
break;
|
|
case QVariant::Point:
|
|
operator= (tl::Variant (v.value<QPoint> ()));
|
|
break;
|
|
case QVariant::PointF:
|
|
operator= (tl::Variant (v.value<QPointF> ()));
|
|
break;
|
|
case QVariant::Polygon:
|
|
operator= (tl::Variant (v.value<QPolygon> ()));
|
|
break;
|
|
case QVariant::Quaternion:
|
|
operator= (tl::Variant (v.value<QQuaternion> ()));
|
|
break;
|
|
case QVariant::Rect:
|
|
operator= (tl::Variant (v.value<QRect> ()));
|
|
break;
|
|
case QVariant::RectF:
|
|
operator= (tl::Variant (v.value<QRectF> ()));
|
|
break;
|
|
case QVariant::RegExp:
|
|
operator= (tl::Variant (v.value<QRegExp> ()));
|
|
break;
|
|
case QVariant::Region:
|
|
operator= (tl::Variant (v.value<QRegion> ()));
|
|
break;
|
|
case QVariant::Size:
|
|
operator= (tl::Variant (v.value<QSize> ()));
|
|
break;
|
|
case QVariant::SizeF:
|
|
operator= (tl::Variant (v.value<QSizeF> ()));
|
|
break;
|
|
case QVariant::SizePolicy:
|
|
operator= (tl::Variant (v.value<QSizePolicy> ()));
|
|
break;
|
|
case QVariant::TextFormat:
|
|
operator= (tl::Variant (v.value<QTextFormat> ()));
|
|
break;
|
|
case QVariant::TextLength:
|
|
operator= (tl::Variant (v.value<QTextLength> ()));
|
|
break;
|
|
case QVariant::Time:
|
|
operator= (tl::Variant (v.value<QTime> ()));
|
|
break;
|
|
case QVariant::Url:
|
|
operator= (tl::Variant (v.value<QUrl> ()));
|
|
break;
|
|
case QVariant::Vector2D:
|
|
operator= (tl::Variant (v.value<QVector2D> ()));
|
|
break;
|
|
case QVariant::Vector3D:
|
|
operator= (tl::Variant (v.value<QVector3D> ()));
|
|
break;
|
|
case QVariant::Vector4D:
|
|
operator= (tl::Variant (v.value<QVector4D> ()));
|
|
break;
|
|
default:
|
|
case QVariant::String:
|
|
operator= (v.toString ());
|
|
break;
|
|
}
|
|
}
|
|
|
|
Variant::~Variant ()
|
|
{
|
|
reset ();
|
|
}
|
|
|
|
void
|
|
Variant::reset ()
|
|
{
|
|
if (m_string) {
|
|
delete [] m_string;
|
|
}
|
|
m_string = 0;
|
|
if (m_type == t_list) {
|
|
delete m_var.m_list;
|
|
} else if (m_type == t_array) {
|
|
delete m_var.m_array;
|
|
} else if (m_type == t_qstring) {
|
|
delete m_var.m_qstring;
|
|
} else if (m_type == t_qbytearray) {
|
|
delete m_var.m_qbytearray;
|
|
} else if (m_type == t_stdstring) {
|
|
delete m_var.m_stdstring;
|
|
} else if (m_type == t_user_ref) {
|
|
WeakOrSharedPtr *ptr = reinterpret_cast<WeakOrSharedPtr *> (m_var.mp_user_ref.ptr);
|
|
ptr->~WeakOrSharedPtr();
|
|
} else if (m_type == t_user) {
|
|
if (m_var.mp_user.object && m_var.mp_user.shared) {
|
|
m_var.mp_user.cls->destroy (m_var.mp_user.object);
|
|
}
|
|
}
|
|
m_type = t_nil;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (const char *s)
|
|
{
|
|
if (m_type == t_string && s == m_string) {
|
|
// we are assigning to ourselves
|
|
} else {
|
|
char *snew = new char [strlen (s) + 1];
|
|
strcpy (snew, s);
|
|
reset ();
|
|
m_type = t_string;
|
|
m_string = snew;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (const std::string &s)
|
|
{
|
|
if (m_type == t_stdstring && &s == m_var.m_stdstring) {
|
|
// we are assigning to ourselves
|
|
} else {
|
|
std::string *snew = new std::string (s);
|
|
reset ();
|
|
m_type = t_stdstring;
|
|
m_var.m_stdstring = snew;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (const QByteArray &qs)
|
|
{
|
|
if (m_type == t_qbytearray && &qs == m_var.m_qbytearray) {
|
|
// we are assigning to ourselves
|
|
} else {
|
|
QByteArray *snew = new QByteArray (qs);
|
|
reset ();
|
|
m_type = t_qbytearray;
|
|
m_var.m_qbytearray = snew;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (const QString &qs)
|
|
{
|
|
if (m_type == t_qstring && &qs == m_var.m_qstring) {
|
|
// we are assigning to ourselves
|
|
} else {
|
|
QString *snew = new QString (qs);
|
|
reset ();
|
|
m_type = t_qstring;
|
|
m_var.m_qstring = snew;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (double d)
|
|
{
|
|
reset ();
|
|
m_type = t_double;
|
|
m_var.m_double = d;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (float d)
|
|
{
|
|
reset ();
|
|
m_type = t_float;
|
|
m_var.m_float = d;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (bool b)
|
|
{
|
|
reset ();
|
|
m_type = t_bool;
|
|
m_var.m_bool = b;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (signed char c)
|
|
{
|
|
reset ();
|
|
m_type = t_schar;
|
|
m_var.m_schar = c;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (unsigned char c)
|
|
{
|
|
reset ();
|
|
m_type = t_uchar;
|
|
m_var.m_uchar = c;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (char c)
|
|
{
|
|
reset ();
|
|
m_type = t_char;
|
|
m_var.m_char = c;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (unsigned short s)
|
|
{
|
|
reset ();
|
|
m_type = t_ushort;
|
|
m_var.m_ushort = s;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (short s)
|
|
{
|
|
reset ();
|
|
m_type = t_short;
|
|
m_var.m_short = s;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (unsigned int l)
|
|
{
|
|
reset ();
|
|
m_type = t_uint;
|
|
m_var.m_uint = l;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (int l)
|
|
{
|
|
reset ();
|
|
m_type = t_int;
|
|
m_var.m_int = l;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (unsigned long l)
|
|
{
|
|
reset ();
|
|
m_type = t_ulong;
|
|
m_var.m_ulong = l;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (long l)
|
|
{
|
|
reset ();
|
|
m_type = t_long;
|
|
m_var.m_long = l;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (unsigned long long l)
|
|
{
|
|
reset ();
|
|
m_type = t_ulonglong;
|
|
m_var.m_ulonglong = l;
|
|
return *this;
|
|
}
|
|
|
|
Variant &
|
|
Variant::operator= (long long l)
|
|
{
|
|
reset ();
|
|
m_type = t_longlong;
|
|
m_var.m_longlong = l;
|
|
return *this;
|
|
}
|
|
|
|
#if defined(HAVE_64BIT_COORD)
|
|
Variant &
|
|
Variant::operator= (__int128 l)
|
|
{
|
|
reset ();
|
|
m_type = t_int128;
|
|
m_var.m_int128 = l;
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
Variant &
|
|
Variant::operator= (const Variant &v)
|
|
{
|
|
if (this != &v) {
|
|
|
|
// Clearing *this through swap delays the destruction of
|
|
// this's content. This is important if we assign a list member
|
|
// of this to this itself (this happens in tl::Expression).
|
|
tl::Variant vv;
|
|
vv.swap (*this);
|
|
|
|
m_type = v.m_type;
|
|
if (m_type == t_double) {
|
|
m_var.m_double = v.m_var.m_double;
|
|
} else if (m_type == t_float) {
|
|
m_var.m_float = v.m_var.m_float;
|
|
} else if (m_type == t_bool) {
|
|
m_var.m_bool = v.m_var.m_bool;
|
|
} else if (m_type == t_uchar) {
|
|
m_var.m_uchar = v.m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
m_var.m_schar = v.m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
m_var.m_char = v.m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
m_var.m_ushort = v.m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
m_var.m_short = v.m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
m_var.m_uint = v.m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
m_var.m_int = v.m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
m_var.m_ulong = v.m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
m_var.m_long = v.m_var.m_long;
|
|
} else if (m_type == t_longlong) {
|
|
m_var.m_longlong = v.m_var.m_longlong;
|
|
} else if (m_type == t_ulonglong) {
|
|
m_var.m_ulonglong = v.m_var.m_ulonglong;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
m_var.m_int128 = v.m_var.m_int128;
|
|
#endif
|
|
} else if (m_type == t_id) {
|
|
m_var.m_id = v.m_var.m_id;
|
|
} else if (m_type == t_qstring) {
|
|
m_var.m_qstring = new QString (*v.m_var.m_qstring);
|
|
} else if (m_type == t_qbytearray) {
|
|
m_var.m_qbytearray = new QByteArray (*v.m_var.m_qbytearray);
|
|
} else if (m_type == t_stdstring) {
|
|
m_var.m_stdstring = new std::string (*v.m_var.m_stdstring);
|
|
} else if (m_type == t_string) {
|
|
m_string = new char [strlen (v.m_string) + 1];
|
|
strcpy (m_string, v.m_string);
|
|
} else if (m_type == t_list) {
|
|
m_var.m_list = new std::vector<tl::Variant> (*v.m_var.m_list);
|
|
} else if (m_type == t_array) {
|
|
m_var.m_array = new std::map<tl::Variant, tl::Variant> (*v.m_var.m_array);
|
|
} else if (m_type == t_user) {
|
|
m_var.mp_user.cls = v.m_var.mp_user.cls;
|
|
if (v.m_var.mp_user.object) {
|
|
if (v.m_var.mp_user.shared) {
|
|
m_var.mp_user.object = v.m_var.mp_user.cls->clone (v.m_var.mp_user.object);
|
|
m_var.mp_user.shared = true;
|
|
} else {
|
|
m_var.mp_user.object = v.m_var.mp_user.object;
|
|
m_var.mp_user.shared = false;
|
|
}
|
|
} else {
|
|
m_var.mp_user.object = 0;
|
|
}
|
|
} else if (m_type == t_user_ref) {
|
|
m_var.mp_user_ref.cls = v.m_var.mp_user_ref.cls;
|
|
const WeakOrSharedPtr *ptr = reinterpret_cast<const WeakOrSharedPtr *> (v.m_var.mp_user_ref.ptr);
|
|
new (m_var.mp_user_ref.ptr) WeakOrSharedPtr (*ptr);
|
|
}
|
|
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
inline bool
|
|
is_integer_type (Variant::type type)
|
|
{
|
|
switch (type) {
|
|
case Variant::t_char:
|
|
case Variant::t_schar:
|
|
case Variant::t_short:
|
|
case Variant::t_int:
|
|
case Variant::t_long:
|
|
case Variant::t_uchar:
|
|
case Variant::t_ushort:
|
|
case Variant::t_uint:
|
|
case Variant::t_ulong:
|
|
case Variant::t_longlong:
|
|
case Variant::t_ulonglong:
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case Variant::t_int128:
|
|
#endif
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
inline Variant::type
|
|
normalized_type (Variant::type type)
|
|
{
|
|
switch (type) {
|
|
case Variant::t_float:
|
|
case Variant::t_double:
|
|
return Variant::t_double;
|
|
case Variant::t_char:
|
|
case Variant::t_schar:
|
|
case Variant::t_short:
|
|
case Variant::t_int:
|
|
case Variant::t_long:
|
|
return Variant::t_long;
|
|
case Variant::t_uchar:
|
|
case Variant::t_ushort:
|
|
case Variant::t_uint:
|
|
case Variant::t_ulong:
|
|
return Variant::t_ulong;
|
|
case Variant::t_stdstring:
|
|
case Variant::t_string:
|
|
return Variant::t_string;
|
|
default:
|
|
case Variant::t_longlong:
|
|
case Variant::t_ulonglong:
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case Variant::t_int128:
|
|
#endif
|
|
case Variant::t_bool:
|
|
case Variant::t_nil:
|
|
case Variant::t_qstring:
|
|
case Variant::t_qbytearray:
|
|
return type;
|
|
}
|
|
}
|
|
|
|
inline std::pair<bool, Variant::type>
|
|
normalized_type (Variant::type type1, Variant::type type2)
|
|
{
|
|
type1 = normalized_type (type1);
|
|
type2 = normalized_type (type2);
|
|
|
|
if (type1 == type2) {
|
|
return std::make_pair (true, type1);
|
|
}
|
|
|
|
if (type1 == Variant::t_double && is_integer_type (type2)) {
|
|
// use double as common representation
|
|
return std::make_pair (true, Variant::t_double);
|
|
} else if (type2 == Variant::t_double && is_integer_type (type1)) {
|
|
// use double as common representation
|
|
return std::make_pair (true, Variant::t_double);
|
|
} else {
|
|
return std::make_pair (type1 == type2, type1);
|
|
}
|
|
}
|
|
|
|
|
|
bool
|
|
Variant::operator== (const tl::Variant &d) const
|
|
{
|
|
std::pair<bool, type> tt = normalized_type (m_type, d.m_type);
|
|
if (! tt.first) {
|
|
return false;
|
|
}
|
|
type t = tt.second;
|
|
|
|
if (t == t_nil) {
|
|
return true;
|
|
} else if (t == t_bool) {
|
|
return m_var.m_bool == d.m_var.m_bool;
|
|
} else if (t == t_ulong) {
|
|
return to_ulong () == d.to_ulong ();
|
|
} else if (t == t_long) {
|
|
return to_long () == d.to_long ();
|
|
} else if (t == t_ulonglong) {
|
|
return to_ulonglong () == d.to_ulonglong ();
|
|
} else if (t == t_longlong) {
|
|
return to_longlong () == d.to_longlong ();
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (t == t_int128) {
|
|
return to_int128 () == d.to_int128 ();
|
|
#endif
|
|
} else if (t == t_id) {
|
|
return m_var.m_id == d.m_var.m_id;
|
|
} else if (t == t_double) {
|
|
return to_double () == d.to_double ();
|
|
} else if (t == t_string) {
|
|
return strcmp (to_string (), d.to_string ()) == 0;
|
|
} else if (t == t_qstring) {
|
|
return *m_var.m_qstring == *d.m_var.m_qstring;
|
|
} else if (t == t_qbytearray) {
|
|
return *m_var.m_qbytearray == *d.m_var.m_qbytearray;
|
|
} else if (t == t_list) {
|
|
return *m_var.m_list == *d.m_var.m_list;
|
|
} else if (t == t_array) {
|
|
return *m_var.m_array == *d.m_var.m_array;
|
|
} else if (t == t_user) {
|
|
return m_var.mp_user.cls == d.m_var.mp_user.cls && m_var.mp_user.cls->equal (m_var.mp_user.object, d.m_var.mp_user.object);
|
|
} else if (t == t_user_ref) {
|
|
const tl::Object *self = reinterpret_cast<const WeakOrSharedPtr *> (m_var.mp_user_ref.ptr)->get ();
|
|
const tl::Object *other = reinterpret_cast<const WeakOrSharedPtr *> (d.m_var.mp_user_ref.ptr)->get ();
|
|
return m_var.mp_user_ref.cls == d.m_var.mp_user_ref.cls && m_var.mp_user_ref.cls->equal (m_var.mp_user_ref.cls->deref_proxy_const (self), m_var.mp_user_ref.cls->deref_proxy_const (other));
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::operator< (const tl::Variant &d) const
|
|
{
|
|
std::pair<bool, type> tt = normalized_type (m_type, d.m_type);
|
|
if (! tt.first) {
|
|
return normalized_type (m_type) < normalized_type (d.m_type);
|
|
}
|
|
|
|
type t = tt.second;
|
|
|
|
if (t == t_nil) {
|
|
return false;
|
|
} else if (t == t_bool) {
|
|
return m_var.m_bool < d.m_var.m_bool;
|
|
} else if (t == t_ulong) {
|
|
return to_ulong () < d.to_ulong ();
|
|
} else if (t == t_long) {
|
|
return to_long () < d.to_long ();
|
|
} else if (t == t_ulonglong) {
|
|
return to_ulonglong () < d.to_ulonglong ();
|
|
} else if (t == t_longlong) {
|
|
return to_longlong () < d.to_longlong ();
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (t == t_int128) {
|
|
return to_int128 () < d.to_int128 ();
|
|
#endif
|
|
} else if (t == t_id) {
|
|
return m_var.m_id < d.m_var.m_id;
|
|
} else if (t == t_double) {
|
|
return to_double () < d.to_double ();
|
|
} else if (t == t_string) {
|
|
return strcmp (to_string (), d.to_string ()) < 0;
|
|
} else if (t == t_qstring) {
|
|
return *m_var.m_qstring < *d.m_var.m_qstring;
|
|
} else if (t == t_qbytearray) {
|
|
return *m_var.m_qbytearray < *d.m_var.m_qbytearray;
|
|
} else if (t == t_list) {
|
|
return *m_var.m_list < *d.m_var.m_list;
|
|
} else if (t == t_array) {
|
|
return *m_var.m_array < *d.m_var.m_array;
|
|
} else if (t == t_user) {
|
|
if (m_var.mp_user.cls != d.m_var.mp_user.cls) {
|
|
// TODO: there should be some class Id that can be used for comparison (that is more predictable)
|
|
return m_var.mp_user.cls < d.m_var.mp_user.cls;
|
|
}
|
|
return m_var.mp_user.cls->less (m_var.mp_user.object, d.m_var.mp_user.object);
|
|
} else if (t == t_user_ref) {
|
|
if (m_var.mp_user_ref.cls != d.m_var.mp_user_ref.cls) {
|
|
// TODO: there should be some class Id that can be used for comparison (that is more predictable)
|
|
return m_var.mp_user_ref.cls < d.m_var.mp_user_ref.cls;
|
|
}
|
|
const tl::Object *self = reinterpret_cast<const WeakOrSharedPtr *> (m_var.mp_user_ref.ptr)->get ();
|
|
const tl::Object *other = reinterpret_cast<const WeakOrSharedPtr *> (d.m_var.mp_user_ref.ptr)->get ();
|
|
return m_var.mp_user_ref.cls->less (m_var.mp_user_ref.cls->deref_proxy_const (self), m_var.mp_user_ref.cls->deref_proxy_const (other));
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_float () const
|
|
{
|
|
switch (m_type) {
|
|
case t_float:
|
|
case t_char:
|
|
case t_uchar:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_ushort:
|
|
case t_int:
|
|
case t_uint:
|
|
case t_long:
|
|
case t_ulong:
|
|
case t_longlong:
|
|
case t_ulonglong:
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
#endif
|
|
case t_bool:
|
|
case t_nil:
|
|
return true;
|
|
case t_double:
|
|
return m_var.m_double < std::numeric_limits<float>::max () && m_var.m_double > std::numeric_limits<float>::min ();
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
case t_string:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
double d;
|
|
return ex.try_read (d) && ex.at_end ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_double () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
case t_float:
|
|
case t_char:
|
|
case t_uchar:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_ushort:
|
|
case t_int:
|
|
case t_uint:
|
|
case t_long:
|
|
case t_ulong:
|
|
case t_longlong:
|
|
case t_ulonglong:
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
#endif
|
|
case t_bool:
|
|
case t_nil:
|
|
return true;
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
case t_string:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
double d;
|
|
return ex.try_read (d) && ex.at_end ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#if defined(HAVE_64BIT_COORD)
|
|
bool
|
|
Variant::can_convert_to_int128 () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<__int128>::max () && m_var.m_double >= std::numeric_limits<__int128>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= float (std::numeric_limits<__int128>::max ()) && m_var.m_float >= float (std::numeric_limits<__int128>::min ());
|
|
case t_longlong:
|
|
case t_long:
|
|
case t_int128:
|
|
case t_char:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_int:
|
|
case t_bool:
|
|
case t_uchar:
|
|
case t_ushort:
|
|
case t_uint:
|
|
case t_nil:
|
|
return true;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
// TODO: there is no range checking currently
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool
|
|
Variant::can_convert_to_ulonglong () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<unsigned long long>::max () && m_var.m_double >= std::numeric_limits<unsigned long long>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= float (std::numeric_limits<unsigned long long>::max ()) && m_var.m_float >= float (std::numeric_limits<unsigned long long>::min ());
|
|
case t_longlong:
|
|
return m_var.m_longlong >= 0;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return m_var.m_int128 <= __int128 (std::numeric_limits<unsigned long long>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<unsigned long long>::min ());
|
|
#endif
|
|
case t_ulonglong:
|
|
case t_ulong:
|
|
case t_bool:
|
|
case t_uchar:
|
|
case t_ushort:
|
|
case t_uint:
|
|
case t_nil:
|
|
return true;
|
|
case t_long:
|
|
return m_var.m_long >= 0;
|
|
case t_char:
|
|
return m_var.m_char >= 0;
|
|
case t_schar:
|
|
return m_var.m_schar >= 0;
|
|
case t_short:
|
|
return m_var.m_short >= 0;
|
|
case t_int:
|
|
return m_var.m_int >= 0;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
unsigned long long ll;
|
|
return ex.try_read (ll) && ex.at_end ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_longlong () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<long long>::max () && m_var.m_double >= std::numeric_limits<long long>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= float (std::numeric_limits<long long>::max ()) && m_var.m_float >= float (std::numeric_limits<long long>::min ());
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return m_var.m_int128 <= __int128 (std::numeric_limits<long long>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<long long>::min ());
|
|
#endif
|
|
case t_ulonglong:
|
|
return m_var.m_ulonglong <= (unsigned long long) std::numeric_limits<long long>::max ();
|
|
case t_longlong:
|
|
case t_ulong:
|
|
case t_long:
|
|
case t_bool:
|
|
case t_char:
|
|
case t_uchar:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_ushort:
|
|
case t_int:
|
|
case t_uint:
|
|
case t_nil:
|
|
return true;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
long long ll;
|
|
return ex.try_read (ll) && ex.at_end ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_ulong () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<unsigned long>::max () && m_var.m_double >= std::numeric_limits<unsigned long>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= std::numeric_limits<unsigned long>::max () && m_var.m_float >= std::numeric_limits<unsigned long>::min ();
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return m_var.m_int128 <= __int128 (std::numeric_limits<unsigned long long>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<unsigned long long>::min ());
|
|
#endif
|
|
case t_longlong:
|
|
return m_var.m_longlong >= 0 && m_var.m_longlong < (long long) std::numeric_limits<unsigned long>::max ();
|
|
case t_ulonglong:
|
|
return m_var.m_ulonglong < (unsigned long long) std::numeric_limits<unsigned long>::max ();
|
|
case t_ulong:
|
|
case t_bool:
|
|
case t_uchar:
|
|
case t_ushort:
|
|
case t_uint:
|
|
case t_nil:
|
|
return true;
|
|
case t_long:
|
|
return m_var.m_long >= 0;
|
|
case t_char:
|
|
return m_var.m_char >= 0;
|
|
case t_schar:
|
|
return m_var.m_schar >= 0;
|
|
case t_short:
|
|
return m_var.m_short >= 0;
|
|
case t_int:
|
|
return m_var.m_int >= 0;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
unsigned long l;
|
|
return ex.try_read (l) && ex.at_end ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_long () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<long>::max () && m_var.m_double >= std::numeric_limits<long>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= std::numeric_limits<long>::max () && m_var.m_float >= std::numeric_limits<long>::min ();
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return m_var.m_int128 <= __int128 (std::numeric_limits<long>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<long>::min ());
|
|
#endif
|
|
case t_ulonglong:
|
|
return m_var.m_ulonglong <= (unsigned long long) std::numeric_limits<long>::max ();
|
|
case t_longlong:
|
|
return m_var.m_longlong >= (long long) std::numeric_limits<long>::min () && m_var.m_longlong <= (long long) std::numeric_limits<long>::max ();
|
|
case t_ulong:
|
|
return m_var.m_ulong <= (unsigned long) std::numeric_limits<long>::max ();
|
|
case t_long:
|
|
case t_bool:
|
|
case t_char:
|
|
case t_uchar:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_ushort:
|
|
case t_int:
|
|
case t_uint:
|
|
case t_nil:
|
|
return true;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
long l;
|
|
return ex.try_read (l) && ex.at_end ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_int () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<int>::max () && m_var.m_double >= std::numeric_limits<int>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= std::numeric_limits<int>::max () && m_var.m_float >= std::numeric_limits<int>::min ();
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return m_var.m_int128 <= __int128 (std::numeric_limits<int>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<int>::min ());
|
|
#endif
|
|
case t_ulonglong:
|
|
return m_var.m_ulonglong <= (unsigned long long) std::numeric_limits<int>::max ();
|
|
case t_longlong:
|
|
return m_var.m_longlong >= (long long) std::numeric_limits<int>::min () && m_var.m_longlong <= (long long) std::numeric_limits<int>::max ();
|
|
case t_ulong:
|
|
return m_var.m_ulong <= (unsigned long) std::numeric_limits<int>::max ();
|
|
case t_uint:
|
|
return m_var.m_uint <= (unsigned int) std::numeric_limits<int>::max ();
|
|
case t_long:
|
|
return m_var.m_long >= (long) std::numeric_limits<int>::min () && m_var.m_long <= (long) std::numeric_limits<int>::max ();
|
|
case t_bool:
|
|
case t_char:
|
|
case t_uchar:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_ushort:
|
|
case t_int:
|
|
case t_nil:
|
|
return true;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
long l;
|
|
return ex.try_read (l) && ex.at_end () && l >= (long) std::numeric_limits<int>::min () && l <= (long) std::numeric_limits<int>::max ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_uint () const
|
|
{
|
|
switch (m_type) {
|
|
case t_double:
|
|
return m_var.m_double <= std::numeric_limits<unsigned int>::max () && m_var.m_double >= std::numeric_limits<unsigned int>::min ();
|
|
case t_float:
|
|
return m_var.m_float <= std::numeric_limits<unsigned int>::max () && m_var.m_float >= std::numeric_limits<unsigned int>::min ();
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return m_var.m_int128 <= __int128 (std::numeric_limits<unsigned int>::max ()) && m_var.m_int128 >= __int128 (std::numeric_limits<unsigned int>::min ());
|
|
#endif
|
|
case t_ulonglong:
|
|
return m_var.m_ulonglong <= (unsigned long long) std::numeric_limits<unsigned int>::max ();
|
|
case t_longlong:
|
|
return m_var.m_longlong >= (long long) std::numeric_limits<unsigned int>::min () && m_var.m_longlong <= (long long) std::numeric_limits<unsigned int>::max ();
|
|
case t_ulong:
|
|
return m_var.m_ulong <= (unsigned long) std::numeric_limits<unsigned int>::max ();
|
|
case t_int:
|
|
return m_var.m_int >= (long) std::numeric_limits<unsigned int>::min ();
|
|
case t_long:
|
|
return m_var.m_long >= (long) std::numeric_limits<unsigned int>::min () && (sizeof (long) == sizeof (unsigned int) || m_var.m_long <= (long) std::numeric_limits<unsigned int>::max ());
|
|
case t_bool:
|
|
case t_char:
|
|
case t_uchar:
|
|
case t_schar:
|
|
case t_short:
|
|
case t_ushort:
|
|
case t_uint:
|
|
case t_nil:
|
|
return true;
|
|
case t_string:
|
|
case t_qstring:
|
|
case t_qbytearray:
|
|
case t_stdstring:
|
|
{
|
|
tl::Extractor ex (to_string ());
|
|
long l;
|
|
return ex.try_read (l) && ex.at_end () && l >= (long) std::numeric_limits<int>::min () && l <= (long) std::numeric_limits<int>::max ();
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_short () const
|
|
{
|
|
return can_convert_to_long () && (to_long () <= (long) std::numeric_limits<short>::max () && to_long () >= (long) std::numeric_limits<short>::min ());
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_ushort () const
|
|
{
|
|
return can_convert_to_long () && (to_long () <= (long) std::numeric_limits<unsigned short>::max () && to_long () >= (long) std::numeric_limits<unsigned short>::min ());
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_char () const
|
|
{
|
|
return can_convert_to_long () && (to_long () <= (long) std::numeric_limits<char>::max () && to_long () >= (long) std::numeric_limits<char>::min ());
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_schar () const
|
|
{
|
|
return can_convert_to_long () && (to_short () <= (long) std::numeric_limits<signed char>::max () && to_short () >= (long) std::numeric_limits<signed char>::min ());
|
|
}
|
|
|
|
bool
|
|
Variant::can_convert_to_uchar () const
|
|
{
|
|
return can_convert_to_long () && (to_short () <= (long) std::numeric_limits<unsigned char>::max () && to_short () >= (long) std::numeric_limits<unsigned char>::min ());
|
|
}
|
|
|
|
QByteArray
|
|
Variant::to_qbytearray () const
|
|
{
|
|
if (m_type == t_qbytearray) {
|
|
return *m_var.m_qbytearray;
|
|
} else if (m_type == t_qstring) {
|
|
return m_var.m_qstring->toUtf8 ();
|
|
} else if (m_type == t_stdstring) {
|
|
return QByteArray (m_var.m_stdstring->c_str (), int (m_var.m_stdstring->size ()));
|
|
} else {
|
|
// TODO: maybe some other conversion makes sense? I.e. byte representation of int?
|
|
std::string s = to_string ();
|
|
return QByteArray (s.c_str (), int (s.size ()));
|
|
}
|
|
}
|
|
|
|
QString
|
|
Variant::to_qstring () const
|
|
{
|
|
if (m_type == t_qstring) {
|
|
return *m_var.m_qstring;
|
|
} else if (m_type == t_qbytearray) {
|
|
return QString::fromUtf8 (*m_var.m_qbytearray);
|
|
} else {
|
|
return tl::to_qstring (to_string ());
|
|
}
|
|
}
|
|
|
|
std::string
|
|
Variant::to_stdstring () const
|
|
{
|
|
if (m_type == t_stdstring) {
|
|
return *m_var.m_stdstring;
|
|
} else if (m_type == t_qstring) {
|
|
return tl::to_string (*m_var.m_qstring);
|
|
} else if (m_type == t_qbytearray) {
|
|
return std::string (m_var.m_qbytearray->constData (), m_var.m_qbytearray->size ());
|
|
} else {
|
|
return std::string (to_string ());
|
|
}
|
|
}
|
|
|
|
const char *
|
|
Variant::to_string () const
|
|
{
|
|
if (m_type == t_stdstring) {
|
|
|
|
return m_var.m_stdstring->c_str ();
|
|
|
|
} else if (m_type == t_qbytearray) {
|
|
|
|
// TODO: content may be longer - const char * terminates at first 0 character
|
|
return m_var.m_qbytearray->constData ();
|
|
|
|
// conversion needed
|
|
} else if (! m_string) {
|
|
|
|
std::string r;
|
|
|
|
if (m_type == t_nil) {
|
|
r = "nil";
|
|
} else if (m_type == t_double) {
|
|
r = tl::to_string (m_var.m_double);
|
|
} else if (m_type == t_float) {
|
|
r = tl::to_string (m_var.m_float);
|
|
} else if (m_type == t_char) {
|
|
r = tl::to_string ((int) m_var.m_char);
|
|
} else if (m_type == t_schar) {
|
|
r = tl::to_string ((int) m_var.m_schar);
|
|
} else if (m_type == t_uchar) {
|
|
r = tl::to_string ((int) m_var.m_uchar);
|
|
} else if (m_type == t_short) {
|
|
r = tl::to_string ((int) m_var.m_short);
|
|
} else if (m_type == t_ushort) {
|
|
r = tl::to_string ((int) m_var.m_ushort);
|
|
} else if (m_type == t_int) {
|
|
r = tl::to_string (m_var.m_int);
|
|
} else if (m_type == t_uint) {
|
|
r = tl::to_string (m_var.m_uint);
|
|
} else if (m_type == t_long) {
|
|
r = tl::to_string (m_var.m_long);
|
|
} else if (m_type == t_ulong) {
|
|
r = tl::to_string (m_var.m_ulong);
|
|
} else if (m_type == t_longlong) {
|
|
r = tl::to_string (m_var.m_longlong);
|
|
} else if (m_type == t_ulonglong) {
|
|
r = tl::to_string (m_var.m_ulonglong);
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
r = tl::to_string (m_var.m_int128);
|
|
#endif
|
|
} else if (m_type == t_bool) {
|
|
r = tl::to_string (m_var.m_bool);
|
|
} else if (m_type == t_qstring) {
|
|
r = tl::to_string (*m_var.m_qstring);
|
|
} else if (m_type == t_qbytearray) {
|
|
r = std::string (m_var.m_qbytearray->constData (), m_var.m_qbytearray->size ());
|
|
} else if (m_type == t_list) {
|
|
for (std::vector<tl::Variant>::const_iterator v = m_var.m_list->begin (); v != m_var.m_list->end (); ++v) {
|
|
if (v != m_var.m_list->begin ()) {
|
|
r += ",";
|
|
}
|
|
r += v->to_string ();
|
|
}
|
|
} else if (m_type == t_array) {
|
|
for (const_array_iterator v = m_var.m_array->begin (); v != m_var.m_array->end (); ++v) {
|
|
if (v != m_var.m_array->begin ()) {
|
|
r += ",";
|
|
}
|
|
r += v->first.to_string ();
|
|
r += "=>";
|
|
r += v->second.to_string ();
|
|
}
|
|
} else if (m_type == t_id) {
|
|
r = "[id" + tl::to_string (m_var.m_id) + "]";
|
|
} else if (m_type == t_user) {
|
|
r = m_var.mp_user.cls->to_string (m_var.mp_user.object);
|
|
} else if (m_type == t_user_ref) {
|
|
r = m_var.mp_user_ref.cls->to_string (m_var.mp_user_ref.cls->deref_proxy_const (reinterpret_cast <const tl::WeakOrSharedPtr *> (m_var.mp_user_ref.ptr)->get ()));
|
|
} else {
|
|
r = "[unknown]";
|
|
}
|
|
|
|
m_string = new char [r.size () + 1];
|
|
strcpy (m_string, r.c_str ());
|
|
|
|
}
|
|
|
|
return m_string;
|
|
}
|
|
|
|
bool
|
|
Variant::to_bool () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return false;
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#if defined(HAVE_64BIT_COORD)
|
|
__int128
|
|
Variant::to_int128 () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return 0;
|
|
} else if (m_type == t_int128) {
|
|
return m_var.m_int128;
|
|
} else if (m_type == t_double) {
|
|
return (__int128) (m_var.m_double);
|
|
} else if (m_type == t_float) {
|
|
return (__int128) (m_var.m_float);
|
|
} else if (m_type == t_uchar) {
|
|
return m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
return m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
return m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
return m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
return m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
return m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
return m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
return m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
return m_var.m_long;
|
|
} else if (m_type == t_ulonglong) {
|
|
return m_var.m_ulonglong;
|
|
} else if (m_type == t_longlong) {
|
|
return m_var.m_longlong;
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else if (m_type == t_stdstring) {
|
|
tl::Extractor ex (m_var.m_stdstring->c_str ());
|
|
__int128 l = 0;
|
|
ex.read (l);
|
|
return l;
|
|
} else if (m_type == t_qbytearray) {
|
|
tl::Extractor ex (m_var.m_qbytearray->constData ());
|
|
__int128 l = 0;
|
|
ex.read (l);
|
|
return l;
|
|
} else if (m_type == t_string || m_type == t_qstring) {
|
|
std::string s (to_string ());
|
|
tl::Extractor ex (s.c_str ());
|
|
__int128 l = 0;
|
|
ex.read (l);
|
|
return l;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
unsigned long long
|
|
Variant::to_ulonglong () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return 0;
|
|
} else if (m_type == t_double) {
|
|
return (unsigned long long) (m_var.m_double);
|
|
} else if (m_type == t_float) {
|
|
return (unsigned long long) (m_var.m_float);
|
|
} else if (m_type == t_uchar) {
|
|
return m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
return m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
return m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
return m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
return m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
return m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
return m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
return m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
return m_var.m_long;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
return m_var.m_int128;
|
|
#endif
|
|
} else if (m_type == t_ulonglong) {
|
|
return m_var.m_ulonglong;
|
|
} else if (m_type == t_longlong) {
|
|
return m_var.m_longlong;
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else if (m_type == t_stdstring) {
|
|
unsigned long long l = 0;
|
|
tl::from_string (*m_var.m_stdstring, l);
|
|
return l;
|
|
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
|
|
unsigned long long l = 0;
|
|
tl::from_string (to_string (), l);
|
|
return l;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
long long
|
|
Variant::to_longlong () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return 0;
|
|
} else if (m_type == t_double) {
|
|
return (long long) (m_var.m_double);
|
|
} else if (m_type == t_float) {
|
|
return (long long) (m_var.m_float);
|
|
} else if (m_type == t_uchar) {
|
|
return m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
return m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
return m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
return m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
return m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
return m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
return m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
return m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
return m_var.m_long;
|
|
} else if (m_type == t_ulonglong) {
|
|
return m_var.m_ulonglong;
|
|
} else if (m_type == t_longlong) {
|
|
return m_var.m_longlong;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
return m_var.m_int128;
|
|
#endif
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else if (m_type == t_stdstring) {
|
|
long long l = 0;
|
|
tl::from_string (*m_var.m_stdstring, l);
|
|
return l;
|
|
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
|
|
long long l = 0;
|
|
tl::from_string (to_string (), l);
|
|
return l;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
unsigned long
|
|
Variant::to_ulong () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return 0;
|
|
} else if (m_type == t_double) {
|
|
return (unsigned long) (m_var.m_double);
|
|
} else if (m_type == t_float) {
|
|
return (unsigned long) (m_var.m_float);
|
|
} else if (m_type == t_uchar) {
|
|
return m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
return m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
return m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
return m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
return m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
return m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
return m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
return m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
return m_var.m_long;
|
|
} else if (m_type == t_ulonglong) {
|
|
return m_var.m_ulonglong;
|
|
} else if (m_type == t_longlong) {
|
|
return m_var.m_longlong;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
return m_var.m_int128;
|
|
#endif
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else if (m_type == t_stdstring) {
|
|
unsigned long l = 0;
|
|
tl::from_string (*m_var.m_stdstring, l);
|
|
return l;
|
|
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
|
|
unsigned long l = 0;
|
|
tl::from_string (to_string (), l);
|
|
return l;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
long
|
|
Variant::to_long () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return 0;
|
|
} else if (m_type == t_double) {
|
|
return (long) (m_var.m_double);
|
|
} else if (m_type == t_float) {
|
|
return (long) (m_var.m_float);
|
|
} else if (m_type == t_uchar) {
|
|
return m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
return m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
return m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
return m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
return m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
return m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
return m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
return m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
return m_var.m_long;
|
|
} else if (m_type == t_ulonglong) {
|
|
return m_var.m_ulonglong;
|
|
} else if (m_type == t_longlong) {
|
|
return m_var.m_longlong;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
return m_var.m_int128;
|
|
#endif
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else if (m_type == t_stdstring) {
|
|
long l = 0;
|
|
tl::from_string (*m_var.m_stdstring, l);
|
|
return l;
|
|
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
|
|
long l = 0;
|
|
tl::from_string (to_string (), l);
|
|
return l;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
Variant::to_int () const
|
|
{
|
|
return (int) to_long ();
|
|
}
|
|
|
|
unsigned int
|
|
Variant::to_uint () const
|
|
{
|
|
return (unsigned int) to_ulong ();
|
|
}
|
|
|
|
short
|
|
Variant::to_short () const
|
|
{
|
|
return (short) to_long ();
|
|
}
|
|
|
|
unsigned short
|
|
Variant::to_ushort () const
|
|
{
|
|
return (unsigned short) to_ulong ();
|
|
}
|
|
|
|
char
|
|
Variant::to_char () const
|
|
{
|
|
return (char) to_long ();
|
|
}
|
|
|
|
signed char
|
|
Variant::to_schar () const
|
|
{
|
|
return (signed char) to_long ();
|
|
}
|
|
|
|
unsigned char
|
|
Variant::to_uchar () const
|
|
{
|
|
return (unsigned char) to_ulong ();
|
|
}
|
|
|
|
size_t
|
|
Variant::to_id () const
|
|
{
|
|
if (m_type == t_id) {
|
|
return m_var.m_id;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
double
|
|
Variant::to_double () const
|
|
{
|
|
if (m_type == t_nil) {
|
|
return 0;
|
|
} else if (m_type == t_double) {
|
|
return m_var.m_double;
|
|
} else if (m_type == t_float) {
|
|
return m_var.m_float;
|
|
} else if (m_type == t_uchar) {
|
|
return m_var.m_uchar;
|
|
} else if (m_type == t_schar) {
|
|
return m_var.m_schar;
|
|
} else if (m_type == t_char) {
|
|
return m_var.m_char;
|
|
} else if (m_type == t_ushort) {
|
|
return m_var.m_ushort;
|
|
} else if (m_type == t_short) {
|
|
return m_var.m_short;
|
|
} else if (m_type == t_uint) {
|
|
return m_var.m_uint;
|
|
} else if (m_type == t_int) {
|
|
return m_var.m_int;
|
|
} else if (m_type == t_ulong) {
|
|
return m_var.m_ulong;
|
|
} else if (m_type == t_long) {
|
|
return m_var.m_long;
|
|
} else if (m_type == t_ulonglong) {
|
|
return m_var.m_ulonglong;
|
|
} else if (m_type == t_longlong) {
|
|
return m_var.m_longlong;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (m_type == t_int128) {
|
|
return m_var.m_int128;
|
|
#endif
|
|
} else if (m_type == t_bool) {
|
|
return m_var.m_bool;
|
|
} else if (m_type == t_stdstring) {
|
|
double d = 0;
|
|
tl::from_string (*m_var.m_stdstring, d);
|
|
return d;
|
|
} else if (m_type == t_string || m_type == t_qstring || m_type == t_qbytearray) {
|
|
double d = 0;
|
|
tl::from_string (to_string (), d);
|
|
return d;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
float
|
|
Variant::to_float () const
|
|
{
|
|
return to_double ();
|
|
}
|
|
|
|
const void *
|
|
Variant::native_ptr () const
|
|
{
|
|
switch (m_type) {
|
|
case t_user:
|
|
return m_var.mp_user.object;
|
|
case t_user_ref:
|
|
return reinterpret_cast<const WeakOrSharedPtr *> (m_var.mp_user_ref.ptr)->get ();
|
|
case t_double:
|
|
return &m_var.m_double;
|
|
case t_float:
|
|
return &m_var.m_float;
|
|
case t_ulonglong:
|
|
return &m_var.m_ulonglong;
|
|
case t_longlong:
|
|
return &m_var.m_longlong;
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
return &m_var.m_int128;
|
|
#endif
|
|
case t_ulong:
|
|
return &m_var.m_ulong;
|
|
case t_long:
|
|
return &m_var.m_long;
|
|
case t_bool:
|
|
return &m_var.m_bool;
|
|
case t_char:
|
|
return &m_var.m_char;
|
|
case t_uchar:
|
|
return &m_var.m_uchar;
|
|
case t_schar:
|
|
return &m_var.m_schar;
|
|
case t_short:
|
|
return &m_var.m_short;
|
|
case t_ushort:
|
|
return &m_var.m_ushort;
|
|
case t_int:
|
|
return &m_var.m_int;
|
|
case t_uint:
|
|
return &m_var.m_uint;
|
|
case t_string:
|
|
return m_string;
|
|
case t_qstring:
|
|
return m_var.m_qstring;
|
|
case t_qbytearray:
|
|
return m_var.m_qbytearray;
|
|
case t_stdstring:
|
|
return m_var.m_stdstring;
|
|
case t_array:
|
|
return m_var.m_array;
|
|
case t_list:
|
|
return m_var.m_list;
|
|
case t_nil:
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
tl::Variant
|
|
Variant::empty_list ()
|
|
{
|
|
static std::vector<tl::Variant> empty_list;
|
|
return tl::Variant (empty_list.begin (), empty_list.end ());
|
|
}
|
|
|
|
tl::Variant
|
|
Variant::empty_array ()
|
|
{
|
|
tl::Variant e;
|
|
e.set_array ();
|
|
return e;
|
|
}
|
|
|
|
tl::Variant *
|
|
tl::Variant::find (const tl::Variant &k)
|
|
{
|
|
if (m_type != t_array) {
|
|
return 0;
|
|
} else {
|
|
array_iterator a = m_var.m_array->find (k);
|
|
if (a != m_var.m_array->end ()) {
|
|
return &a->second;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the value for the given key or 0 if the variant is not an array or does not contain the key
|
|
*/
|
|
const tl::Variant *
|
|
tl::Variant::find (const tl::Variant &k) const
|
|
{
|
|
if (m_type != t_array) {
|
|
return 0;
|
|
} else {
|
|
const_array_iterator a = m_var.m_array->find (k);
|
|
if (a != m_var.m_array->end ()) {
|
|
return &a->second;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string
|
|
Variant::to_parsable_string () const
|
|
{
|
|
if (is_long ()) {
|
|
return "#" + tl::to_string (to_long ());
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (is_int128 ()) {
|
|
return "#ll" + tl::to_string (to_int128 ());
|
|
#endif
|
|
} else if (is_longlong ()) {
|
|
return "#l" + tl::to_string (to_longlong ());
|
|
} else if (is_ulong ()) {
|
|
return "#u" + tl::to_string (to_ulong ());
|
|
} else if (is_ulonglong ()) {
|
|
return "#lu" + tl::to_string (to_ulonglong ());
|
|
} else if (is_double ()) {
|
|
return "##" + tl::to_string (to_double ());
|
|
} else if (is_bool ()) {
|
|
return m_var.m_bool ? "true" : "false";
|
|
} else if (is_nil ()) {
|
|
return "nil";
|
|
} else if (is_stdstring ()) {
|
|
return tl::to_quoted_string (*m_var.m_stdstring);
|
|
} else if (is_cstring () || is_qstring () || is_qbytearray ()) {
|
|
return tl::to_quoted_string (to_string ());
|
|
} else if (is_list ()) {
|
|
std::string r = "(";
|
|
for (tl::Variant::const_iterator l = begin (); l != end (); ++l) {
|
|
if (l != begin ()) {
|
|
r += ",";
|
|
}
|
|
r += l->to_parsable_string ();
|
|
}
|
|
r += ")";
|
|
return r;
|
|
} else if (is_array ()) {
|
|
std::string r = "{";
|
|
for (tl::Variant::const_array_iterator l = begin_array (); l != end_array (); ++l) {
|
|
if (l != begin_array ()) {
|
|
r += ",";
|
|
}
|
|
r += l->first.to_parsable_string ();
|
|
r += "=>";
|
|
r += l->second.to_parsable_string ();
|
|
}
|
|
r += "}";
|
|
return r;
|
|
} else if (is_id ()) {
|
|
return "[id" + tl::to_string (m_var.m_id) + "]";
|
|
} else if (is_user ()) {
|
|
if (user_cls ()) {
|
|
// for downward compatibility we use lower case name + do a translation
|
|
return "[" + tl::VariantUserClassBase::translate_class_name (tl::to_lower_case (user_cls ()->name ())) + ":" + user_cls ()->to_string (to_user ()) + "]";
|
|
} else {
|
|
return "[unknown_user_type]";
|
|
}
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
void
|
|
tl::Variant::swap (tl::Variant &other)
|
|
{
|
|
ValueHolder a = m_var;
|
|
if (m_type == t_user_ref) {
|
|
new (a.mp_user_ref.ptr) tl::WeakOrSharedPtr (*reinterpret_cast <tl::WeakOrSharedPtr *> (m_var.mp_user_ref.ptr));
|
|
reinterpret_cast <tl::WeakOrSharedPtr *> (m_var.mp_user_ref.ptr)->~WeakOrSharedPtr ();
|
|
}
|
|
m_var = other.m_var;
|
|
if (other.m_type == t_user_ref) {
|
|
new (m_var.mp_user_ref.ptr) tl::WeakOrSharedPtr (*reinterpret_cast <tl::WeakOrSharedPtr *> (other.m_var.mp_user_ref.ptr));
|
|
reinterpret_cast <tl::WeakOrSharedPtr *> (other.m_var.mp_user_ref.ptr)->~WeakOrSharedPtr ();
|
|
}
|
|
other.m_var = a;
|
|
if (m_type == t_user_ref) {
|
|
new (other.m_var.mp_user_ref.ptr) tl::WeakOrSharedPtr (*reinterpret_cast <tl::WeakOrSharedPtr *> (a.mp_user_ref.ptr));
|
|
reinterpret_cast <tl::WeakOrSharedPtr *> (a.mp_user_ref.ptr)->~WeakOrSharedPtr ();
|
|
}
|
|
|
|
std::swap (m_type, other.m_type);
|
|
std::swap (m_string, other.m_string);
|
|
}
|
|
|
|
QVariant Variant::to_qvariant () const
|
|
{
|
|
switch (m_type) {
|
|
case t_nil:
|
|
return QVariant ();
|
|
case t_double:
|
|
return QVariant (m_var.m_double);
|
|
case t_float:
|
|
return QVariant ((double) m_var.m_float);
|
|
case t_char:
|
|
return QVariant ((unsigned int) m_var.m_char);
|
|
case t_schar:
|
|
return QVariant ((int) m_var.m_schar);
|
|
case t_uchar:
|
|
return QVariant ((unsigned int) m_var.m_uchar);
|
|
case t_short:
|
|
return QVariant ((int) m_var.m_short);
|
|
case t_ushort:
|
|
return QVariant ((unsigned int) m_var.m_ushort);
|
|
case t_int:
|
|
return QVariant (m_var.m_int);
|
|
case t_uint:
|
|
return QVariant (m_var.m_uint);
|
|
case t_long:
|
|
// TODO: will int == long always?
|
|
return QVariant ((int) m_var.m_long);
|
|
case t_ulong:
|
|
// TODO: will unsigned int == long always?
|
|
return QVariant ((unsigned int) m_var.m_ulong);
|
|
case t_longlong:
|
|
return QVariant (m_var.m_longlong);
|
|
case t_ulonglong:
|
|
return QVariant (m_var.m_ulonglong);
|
|
#if defined(HAVE_64BIT_COORD)
|
|
case t_int128:
|
|
// TODO: support for int128 in QVariant?
|
|
return QVariant ((double) m_var.m_m128);
|
|
#endif
|
|
case t_bool:
|
|
return QVariant (m_var.m_bool);
|
|
case t_qstring:
|
|
return QVariant (*m_var.m_qstring);
|
|
case t_stdstring:
|
|
return QVariant (tl::to_qstring (*m_var.m_stdstring));
|
|
case t_string:
|
|
return QVariant (tl::to_qstring (m_string));
|
|
case t_qbytearray:
|
|
return QVariant (*m_var.m_qbytearray);
|
|
case t_list:
|
|
{
|
|
QList<QVariant> l;
|
|
for (std::vector<tl::Variant>::const_iterator v = m_var.m_list->begin (); v != m_var.m_list->end (); ++v) {
|
|
l.append (v->to_qvariant ());
|
|
}
|
|
return QVariant (l);
|
|
}
|
|
case t_array:
|
|
{
|
|
QMap<QString, QVariant> a;
|
|
for (const_array_iterator v = m_var.m_array->begin (); v != m_var.m_array->end (); ++v) {
|
|
a.insert (v->first.to_qstring (), v->second.to_qvariant ());
|
|
}
|
|
return QVariant (a);
|
|
}
|
|
case t_id:
|
|
return QVariant ((unsigned int) m_var.m_id);
|
|
case t_user:
|
|
{
|
|
const tl::VariantUserClassBase *cls = user_cls ();
|
|
// try any of the other supported classes of QVariant:
|
|
if (dynamic_cast<const tl::VariantUserClass<QBitArray> *> (cls)) {
|
|
return QVariant (to_user<QBitArray> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QBitArray> *> (cls)) {
|
|
return QVariant (to_user<QBitArray> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QBitmap> *> (cls)) {
|
|
return QVariant (to_user<QBitmap> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QBrush> *> (cls)) {
|
|
return QVariant (to_user<QBrush> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QChar> *> (cls)) {
|
|
return QVariant (to_user<QChar> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QColor> *> (cls)) {
|
|
return QVariant (to_user<QColor> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QCursor> *> (cls)) {
|
|
return QVariant (to_user<QCursor> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QDate> *> (cls)) {
|
|
return QVariant (to_user<QDate> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QDateTime> *> (cls)) {
|
|
return QVariant (to_user<QDateTime> ());
|
|
#if QT_VERSION >= 0x040700
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QEasingCurve> *> (cls)) {
|
|
return QVariant (to_user<QEasingCurve> ());
|
|
#endif
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QFont> *> (cls)) {
|
|
return QVariant (to_user<QFont> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QIcon> *> (cls)) {
|
|
return QVariant (to_user<QIcon> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QImage> *> (cls)) {
|
|
return QVariant (to_user<QImage> ());
|
|
#if QT_VERSION >= 0x050000
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QKeySequence> *> (cls)) {
|
|
return QVariant (to_user<QKeySequence> ());
|
|
#endif
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QLine> *> (cls)) {
|
|
return QVariant (to_user<QLine> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QLineF> *> (cls)) {
|
|
return QVariant (to_user<QLineF> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QLocale> *> (cls)) {
|
|
return QVariant (to_user<QLocale> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QTransform> *> (cls)) {
|
|
return QVariant (to_user<QTransform> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QMatrix4x4> *> (cls)) {
|
|
return QVariant (to_user<QMatrix4x4> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QPalette> *> (cls)) {
|
|
return QVariant (to_user<QPalette> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QPen> *> (cls)) {
|
|
return QVariant (to_user<QPen> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QPixmap> *> (cls)) {
|
|
return QVariant (to_user<QPixmap> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QPoint> *> (cls)) {
|
|
return QVariant (to_user<QPoint> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QPointF> *> (cls)) {
|
|
return QVariant (to_user<QPointF> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QPolygon> *> (cls)) {
|
|
return QVariant (to_user<QPolygon> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QQuaternion> *> (cls)) {
|
|
return QVariant (to_user<QQuaternion> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QRect> *> (cls)) {
|
|
return QVariant (to_user<QRect> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QRectF> *> (cls)) {
|
|
return QVariant (to_user<QRectF> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QRegExp> *> (cls)) {
|
|
return QVariant (to_user<QRegExp> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QRegion> *> (cls)) {
|
|
return QVariant (to_user<QRegion> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QSize> *> (cls)) {
|
|
return QVariant (to_user<QSize> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QSizeF> *> (cls)) {
|
|
return QVariant (to_user<QSizeF> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QSizePolicy> *> (cls)) {
|
|
return QVariant (to_user<QSizePolicy> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QTextFormat> *> (cls)) {
|
|
return QVariant (to_user<QTextFormat> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QTextLength> *> (cls)) {
|
|
return QVariant (to_user<QTextLength> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QTime> *> (cls)) {
|
|
return QVariant (to_user<QTime> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QUrl> *> (cls)) {
|
|
return QVariant (to_user<QUrl> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QVector2D> *> (cls)) {
|
|
return QVariant (to_user<QVector2D> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QVector3D> *> (cls)) {
|
|
return QVariant (to_user<QVector3D> ());
|
|
} else if (dynamic_cast<const tl::VariantUserClass<QVector4D> *> (cls)) {
|
|
return QVariant (to_user<QVector4D> ());
|
|
} else {
|
|
return QVariant ();
|
|
}
|
|
}
|
|
default:
|
|
return QVariant ();
|
|
}
|
|
}
|
|
|
|
void Variant::set_user_object (void *obj, bool shared)
|
|
{
|
|
m_var.mp_user.object = obj;
|
|
m_var.mp_user.shared = shared;
|
|
}
|
|
|
|
bool Variant::user_is_const () const
|
|
{
|
|
tl_assert (is_user ());
|
|
return user_cls ()->is_const ();
|
|
}
|
|
|
|
bool Variant::user_is_ref () const
|
|
{
|
|
if (m_type == t_user) {
|
|
return !m_var.mp_user.shared;
|
|
} else if (m_type == t_user_ref) {
|
|
return !reinterpret_cast <const tl::WeakOrSharedPtr *> (m_var.mp_user_ref.ptr)->is_shared ();
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void Variant::user_destroy ()
|
|
{
|
|
tl_assert (is_user ());
|
|
void *obj = to_user ();
|
|
if (obj) {
|
|
user_cls ()->destroy (obj);
|
|
}
|
|
reset ();
|
|
}
|
|
|
|
void Variant::user_assign (const tl::Variant &other)
|
|
{
|
|
tl_assert (is_user ());
|
|
tl_assert (other.is_user ());
|
|
if (user_cls () == other.user_cls ()) {
|
|
user_cls ()->assign (to_user (), other.to_user ());
|
|
}
|
|
}
|
|
|
|
tl::Variant Variant::user_dup () const
|
|
{
|
|
tl_assert (is_user ());
|
|
return tl::Variant (user_cls ()->clone (to_user ()), user_cls (), true);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
// Extractor implementation
|
|
|
|
template <>
|
|
TL_PUBLIC bool test_extractor_impl (tl::Extractor &ex, tl::Variant &v)
|
|
{
|
|
std::string s;
|
|
|
|
if (ex.test ("##")) {
|
|
|
|
double x = 0;
|
|
ex.read (x);
|
|
v = x;
|
|
return true;
|
|
|
|
#if defined(HAVE_64BIT_COORD)
|
|
} else if (ex.test ("#ll")) {
|
|
|
|
__int128 x = 0;
|
|
ex.read (x);
|
|
v = x;
|
|
return true;
|
|
|
|
#endif
|
|
|
|
} else if (ex.test ("#lu")) {
|
|
|
|
unsigned long long x = 0;
|
|
ex.read (x);
|
|
v = x;
|
|
return true;
|
|
|
|
} else if (ex.test ("#l")) {
|
|
|
|
long long x = 0;
|
|
ex.read (x);
|
|
v = x;
|
|
return true;
|
|
|
|
} else if (ex.test ("#u")) {
|
|
|
|
unsigned long x = 0;
|
|
ex.read (x);
|
|
v = x;
|
|
return true;
|
|
|
|
} else if (ex.test ("#")) {
|
|
|
|
long x = 0;
|
|
ex.read (x);
|
|
v = x;
|
|
return true;
|
|
|
|
} else if (ex.test ("nil")) {
|
|
|
|
v = tl::Variant ();
|
|
return true;
|
|
|
|
} else if (ex.test ("false")) {
|
|
|
|
v = false;
|
|
return true;
|
|
|
|
} else if (ex.test ("true")) {
|
|
|
|
v = true;
|
|
return true;
|
|
|
|
} else if (ex.test ("[")) {
|
|
|
|
std::string cls;
|
|
ex.read_word_or_quoted (cls);
|
|
|
|
const VariantUserClassBase *ccls = tl::VariantUserClassBase::find_cls_by_name (cls);
|
|
if (ccls) {
|
|
void *obj = ccls->create ();
|
|
v.set_user (obj, ccls, true);
|
|
ex.test (":");
|
|
ccls->read (obj, ex);
|
|
}
|
|
|
|
ex.test ("]");
|
|
return true;
|
|
|
|
} else if (ex.test ("(")) {
|
|
|
|
std::vector<tl::Variant> values;
|
|
if (! ex.test (")")) {
|
|
while (true) {
|
|
values.push_back (tl::Variant ());
|
|
ex.read (values.back ());
|
|
if (ex.test (",")) {
|
|
// .. continue
|
|
} else {
|
|
ex.expect (")");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
v = tl::Variant (values.begin (), values.end ());
|
|
return true;
|
|
|
|
} else if (ex.test ("{")) {
|
|
|
|
v = tl::Variant::empty_array ();
|
|
if (! ex.test ("}")) {
|
|
while (true) {
|
|
tl::Variant k, x;
|
|
ex.read (k);
|
|
if (ex.test ("=>")) {
|
|
ex.read (x);
|
|
}
|
|
v.insert (k, x);
|
|
if (ex.test (",")) {
|
|
// .. continue
|
|
} else {
|
|
ex.expect ("}");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
|
|
} else if (ex.try_read_word_or_quoted (s)) {
|
|
|
|
v = tl::Variant (s);
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
}
|
|
|
|
template <>
|
|
TL_PUBLIC void extractor_impl (tl::Extractor &ex, tl::Variant &v)
|
|
{
|
|
if (! test_extractor_impl (ex, v)) {
|
|
ex.error (tl::to_string (QObject::tr ("Expected a value specification")));
|
|
}
|
|
}
|
|
|
|
} // namespace tl
|
|
|