[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kdb] src: Improve KDb::cstringToVariant()
From:       Jaroslaw Staniek <staniek () kde ! org>
Date:       2015-06-30 22:09:07
Message-ID: E1ZA3iF-00042Q-Rj () scm ! kde ! org
[Download RAW message or body]

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 <QApplication>
 #include <QDir>
 #include <QProcess>
+#include <QtDebug>
 
 #include <memory>
 
@@ -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 \
                is needed. */
-QVariant KDb::cstringToVariant(const char* data, KDbField* f, int length)
+// Try to convert from string to type T
+template <typename T>
+QVariant convert(T (QString::*ConvertToT)(bool*,int) const, const char \
*data, int size, +                 qlonglong minValue, qlonglong maxValue, \
bool *ok)  {
-    if (!data)
+    T v = (QString::fromLatin1(data, size).*ConvertToT)(ok, 10);
+    if (*ok) {
+        *ok = minValue <= v && v <= 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 = ok ? ok : &tempOk;
+    if (!data || type > KDbField::LastType) {
+        *thisOk = false;
         return QVariant();
+    }
     // from most to least frequently used types:
 
-    if (!f || f->isTextType())
+    if (KDbField::isTextType(type)) {
+        *thisOk = true;
+        //! @todo use KDbDriverBehaviour::TEXT_TYPE_MAX_LENGTH for Text \
type?  return QString::fromUtf8(data, length);
-    if (f->isIntegerType()) {
-        if (f->type() == 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() == KDbField::BLOB)
-        return QByteArray(data, length);
+    }
+    if (KDbField::isIntegerType(type)) {
+        qlonglong minValue, maxValue;
+        const bool isUnsigned = signedness == 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, \
maxValue, thisOk) +                : convert(&QString::toShort, data, \
length, minValue, maxValue, thisOk); +        case KDbField::Integer:
+            return isUnsigned ?
+                convert(&QString::toUInt, data, length, minValue, \
maxValue, thisOk) +                : convert(&QString::toInt, data, length, \
minValue, maxValue, thisOk); +        case KDbField::BigInteger:
+            return isUnsigned ?
+                convert(&QString::toULongLong, data, length, minValue, \
maxValue, thisOk) +                : convert(&QString::toLongLong, data, \
length, minValue, maxValue, 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 == KDbField::BLOB) {
+        *thisOk = length >= 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 = false;
         return QVariant();
+    }
+    *thisOk = 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 \
type, qlonglong *minValue,  of 100 * 100 exceeds the range of Byte. */
 KDB_EXPORT KDbField::Type maximumForIntegerFieldTypes(KDbField::Type t1, \
KDbField::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 \
                is needed. */
-KDB_EXPORT QVariant cstringToVariant(const char* data, KDbField* f, int \
length = -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 \
KDbField::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 BLOB 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 types; 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 \
type, + QVariant::toTime() for time type. */
+KDB_EXPORT QVariant cstringToVariant(const char* data, KDbField::Type \
type, bool *ok, int length = -1, +                                     \
KDb::Signedness signedness = KDb::Signed);  
 /*! @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 \
&stringIfEmpty)  return iifNotEmpty(string, QString(stringIfEmpty));
 }
 
+//! @return @a value if @a ok is true, else returns default value T().
+template<typename T>
+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::libraryPaths() that have readable  subdirectory "kdb".


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic