[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