From kde-commits Tue Jun 30 22:09:07 2015 From: Jaroslaw Staniek Date: Tue, 30 Jun 2015 22:09:07 +0000 To: kde-commits Subject: [kdb] src: Improve KDb::cstringToVariant() Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=143570216011543 Git commit 3eed88bb098e3c42760ea7b0c4e364126e48d3c8 by Jaroslaw Staniek. Committed on 30/06/2015 at 16:51. Pushed by staniek into branch 'master'. Improve KDb::cstringToVariant() - add signedness support for integers - extend the docs - add more sanity checks - fail on unsupported types (Null, etc.) or if data is 0 - set result in the ok OUT arg - much better convert integers (check limits) +Add KDb::iif helper M +57 -15 src/KDb.cpp M +25 -3 src/KDb.h http://commits.kde.org/kdb/3eed88bb098e3c42760ea7b0c4e364126e48d3c8 diff --git a/src/KDb.cpp b/src/KDb.cpp index cb716cb..6338880 100644 --- a/src/KDb.cpp +++ b/src/KDb.cpp @@ -43,6 +43,7 @@ #include #include #include +#include = #include = @@ -1552,30 +1553,71 @@ QString KDb::defaultFileBasedDriverId() return QLatin1String("org.kde.kdb.sqlite"); } = -/*! @return QVariant value converted from null-terminated @a data string. - In case of BLOB type, @a data is not null terminated, so passing length i= s needed. */ -QVariant KDb::cstringToVariant(const char* data, KDbField* f, int length) +// Try to convert from string to type T +template +QVariant convert(T (QString::*ConvertToT)(bool*,int) const, const char *da= ta, int size, + qlonglong minValue, qlonglong maxValue, bool *ok) { - if (!data) + T v =3D (QString::fromLatin1(data, size).*ConvertToT)(ok, 10); + if (*ok) { + *ok =3D minValue <=3D v && v <=3D maxValue; + } + return KDb::iif(*ok, QVariant(v)); +} + +QVariant KDb::cstringToVariant(const char* data, KDbField::Type type, bool= *ok, int length, + KDb::Signedness signedness) +{ + bool tempOk; + bool *thisOk =3D ok ? ok : &tempOk; + if (!data || type > KDbField::LastType) { + *thisOk =3D false; return QVariant(); + } // from most to least frequently used types: = - if (!f || f->isTextType()) + if (KDbField::isTextType(type)) { + *thisOk =3D true; + //! @todo use KDbDriverBehaviour::TEXT_TYPE_MAX_LENGTH for Text ty= pe? return QString::fromUtf8(data, length); - if (f->isIntegerType()) { - if (f->type() =3D=3D KDbField::BigInteger) - return QVariant(QString::fromLatin1(data, length).toLongLong()= ); - return QVariant(QString::fromLatin1(data, length).toInt()); - } - if (f->isFPNumericType()) - return QString::fromLatin1(data, length).toDouble(); - if (f->type() =3D=3D KDbField::BLOB) - return QByteArray(data, length); + } + if (KDbField::isIntegerType(type)) { + qlonglong minValue, maxValue; + const bool isUnsigned =3D signedness =3D=3D KDb::Unsigned; + KDb::getLimitsForFieldType(type, &minValue, &maxValue, signedness); + switch (type) { + case KDbField::Byte: // Byte here too, minValue/maxValue will take= care of limits + case KDbField::ShortInteger: + return isUnsigned ? + convert(&QString::toUShort, data, length, minValue, maxVal= ue, thisOk) + : convert(&QString::toShort, data, length, minValue, maxVa= lue, thisOk); + case KDbField::Integer: + return isUnsigned ? + convert(&QString::toUInt, data, length, minValue, maxValue= , thisOk) + : convert(&QString::toInt, data, length, minValue, maxValu= e, thisOk); + case KDbField::BigInteger: + return isUnsigned ? + convert(&QString::toULongLong, data, length, minValue, max= Value, thisOk) + : convert(&QString::toLongLong, data, length, minValue, ma= xValue, thisOk); + default: + qFatal("Unsupported integer type %d", type); + } + } + if (KDbField::isFPNumericType(type)) { + return KDb::iif(*thisOk, QVariant(QString::fromLatin1(data, length= ).toDouble(thisOk))); + } + if (type =3D=3D KDbField::BLOB) { + *thisOk =3D length >=3D 0; + return *thisOk ? QVariant(QByteArray(data, length)) : QVariant(); + } // the default //! @todo date/time? QVariant result(QString::fromUtf8(data, length)); - if (!result.convert(KDbField::variantType(f->type()))) + if (!result.convert(KDbField::variantType(type))) { + *thisOk =3D false; return QVariant(); + } + *thisOk =3D true; return result; } = diff --git a/src/KDb.h b/src/KDb.h index 7835464..f064247 100644 --- a/src/KDb.h +++ b/src/KDb.h @@ -418,9 +418,21 @@ KDB_EXPORT void getLimitsForFieldType(KDbField::Type t= ype, qlonglong *minValue, of 100 * 100 exceeds the range of Byte. */ KDB_EXPORT KDbField::Type maximumForIntegerFieldTypes(KDbField::Type t1, K= DbField::Type t2); = -/*! @return QVariant value converted from null-terminated @a data string. - In case of BLOB type, @a data is not null terminated, so passing length i= s needed. */ -KDB_EXPORT QVariant cstringToVariant(const char* data, KDbField* f, int le= ngth =3D -1); +//! @return QVariant value converted from a @a data string +/*! Conversion is based on the information about type @a type. + @a type has to be an element from KDbField::Type, not greater than KDbFie= ld::LastType. + For unsupported type this function fails. @a length value controls number= of characters + used in the conversion. It is optional value for all cases but for the BL= OB type because + for it @a data is not null-terminated so the length cannot be measured. + The value of @a signedness controls the conversion in case of integer typ= es; numbers can be + limited to unsigned or not. + If @a ok is not 0 *ok is set to false on failure and to true on success. = On failure a null + QVariant is returned. The function fails if @a data is 0. + For rules of conversion to the boolean type see the documentation of @ref= QVariant::toBool(), + QVariant::toDate() for date type, QVariant::toDateTime() for date+time ty= pe, + QVariant::toTime() for time type. */ +KDB_EXPORT QVariant cstringToVariant(const char* data, KDbField::Type type= , bool *ok, int length =3D -1, + KDb::Signedness signedness =3D KDb::S= igned); = /*! @return default file-based driver MIME type (typically something like "application/x-kexiproject-sqlite") */ @@ -489,6 +501,16 @@ T iifNotEmpty(const T &string, const QByteArray &strin= gIfEmpty) return iifNotEmpty(string, QString(stringIfEmpty)); } = +//! @return @a value if @a ok is true, else returns default value T(). +template +T iif(bool ok, const T &value) +{ + if (ok) { + return value; + } + return T(); +} + /*! @return a list of paths that KDb will search when dynamically loading = libraries (plugins) This is basicaly list of directories returned QCoreApplication::libraryPa= ths() that have readable subdirectory "kdb".