aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/common
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2016-06-13 18:42:42 -0400
committerLibravatarUnit 193 <unit193@ubuntu.com>2016-06-13 18:42:42 -0400
commit5d9314f134ddd3dc4c853e398ac90ba247fb2e4f (patch)
tree5c457fc188036988d7abd29a3eb09931e406510f /SQLiteStudio3/coreSQLiteStudio/common
parent8e640722c62692818ab840d50b3758f89a41a54e (diff)
Imported Upstream version 3.1.0upstream/3.1.0
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/common')
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp213
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h213
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/sortedset.h64
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/strhash.h23
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils.cpp43
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils.h40
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp62
-rw-r--r--SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h4
8 files changed, 459 insertions, 203 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp
new file mode 100644
index 0000000..091121c
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp
@@ -0,0 +1,213 @@
+#include "bistrhash.h"
+
+BiStrHash::BiStrHash(std::initializer_list<std::pair<QString, QString> > list)
+{
+ hash = QHash<QString,QString>(list);
+ initInvertedAndLower();
+}
+
+BiStrHash::BiStrHash(const QHash<QString, QString>& other)
+{
+ unite(other);
+}
+
+BiStrHash::BiStrHash(const BiStrHash& other) : hash(other.hash), inverted(other.inverted),
+ lowerHash(other.lowerHash), lowerInverted(other.lowerInverted)
+{
+}
+
+void BiStrHash::insert(const QString& left, const QString& right)
+{
+ if (lowerHash.contains(left.toLower()))
+ removeLeft(left, Qt::CaseInsensitive);
+
+ if (lowerInverted.contains(right.toLower()))
+ removeRight(right, Qt::CaseInsensitive);
+
+ inverted.insert(right, left);
+ hash.insert(left, right);
+ lowerHash.insert(left.toLower(), left);
+ lowerInverted.insert(right.toLower(), right);
+}
+
+bool BiStrHash::containsLeft(const QString& left, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ return hash.contains(left);
+ else
+ return lowerHash.contains(left.toLower());
+}
+
+bool BiStrHash::containsRight(const QString& right, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ return inverted.contains(right);
+ else
+ return lowerInverted.contains(right.toLower());
+}
+
+int BiStrHash::removeLeft(const QString& left, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ if (!hash.contains(left))
+ return 0;
+
+ inverted.remove(hash.value(left));
+ hash.remove(left);
+
+ return 1;
+ }
+ else
+ {
+ QString lowerLeft = left.toLower();
+ if (!lowerHash.contains(lowerLeft))
+ return 0;
+
+ QString right = hash.value(lowerHash.value(lowerLeft));
+
+ hash.remove(inverted.value(right));
+ inverted.remove(right);
+ lowerHash.remove(lowerLeft);
+ lowerInverted.remove(right.toLower());
+
+ return 1;
+ }
+}
+
+int BiStrHash::removeRight(const QString& right, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ if (!inverted.contains(right))
+ return 0;
+
+ hash.remove(inverted.value(right));
+ inverted.remove(right);
+
+ return 1;
+ }
+ else
+ {
+ QString lowerRight = right.toLower();
+ if (!lowerInverted.contains(lowerRight))
+ return 0;
+
+ QString left = inverted.value(lowerInverted.value(lowerRight));
+
+ inverted.remove(hash.value(left));
+ hash.remove(left);
+ lowerHash.remove(left.toLower());
+ lowerInverted.remove(lowerRight);
+
+ return 1;
+ }
+}
+
+QString BiStrHash::takeLeft(const QString& left, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ QString right = hash.take(left);
+ inverted.remove(right);
+ return right;
+ }
+ else
+ {
+ QString right = hash.take(lowerHash.take(left.toLower()));
+ inverted.remove(lowerInverted.take(right.toLower()));
+ return right;
+ }
+}
+
+QString BiStrHash::takeRight(const QString& right, Qt::CaseSensitivity cs)
+{
+ if (cs == Qt::CaseSensitive)
+ {
+ QString left = inverted.take(right);
+ hash.remove(left);
+ return left;
+ }
+ else
+ {
+ QString left = inverted.take(lowerInverted.take(right.toLower()));
+ hash.remove(lowerHash.take(left.toLower()));
+ return left;
+ }
+}
+
+BiStrHash& BiStrHash::unite(const BiStrHash& other)
+{
+ unite(other.hash);
+ return *this;
+}
+
+BiStrHash& BiStrHash::unite(const QHash<QString, QString>& other)
+{
+ QHashIterator<QString, QString> it(other);
+ while (it.hasNext())
+ insert(it.next().key(), it.value());
+
+ return *this;
+}
+
+QString BiStrHash::valueByLeft(const QString& left, Qt::CaseSensitivity cs) const
+{
+ if (cs == Qt::CaseSensitive)
+ return hash.value(left);
+ else
+ return hash.value(lowerHash.value(left.toLower()));
+}
+
+QString BiStrHash::valueByRight(const QString& right, Qt::CaseSensitivity cs) const
+{
+ if (cs == Qt::CaseSensitive)
+ return inverted.value(right);
+ else
+ return inverted.value(lowerInverted.value(right.toLower()));
+}
+
+QStringList BiStrHash::leftValues() const
+{
+ return hash.keys();
+}
+
+QStringList BiStrHash::rightValues() const
+{
+ return inverted.keys();
+}
+
+QHashIterator<QString, QString> BiStrHash::iterator() const
+{
+ return QHashIterator<QString,QString>(hash);
+}
+
+void BiStrHash::clear()
+{
+ hash.clear();
+ inverted.clear();
+ lowerHash.clear();
+ lowerInverted.clear();
+}
+
+int BiStrHash::count() const
+{
+ return hash.count();
+}
+
+bool BiStrHash::isEmpty() const
+{
+ return hash.isEmpty();
+}
+
+void BiStrHash::initInvertedAndLower()
+{
+ QHashIterator<QString,QString> it(hash);
+ while (it.hasNext())
+ {
+ it.next();
+ inverted[it.value()] = it.key();
+ lowerHash[it.key().toLower()] = it.key();
+ lowerInverted[it.value().toLower()] = it.value();
+ }
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h
index 65c907b..2089010 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.h
@@ -2,6 +2,7 @@
#define BISTRHASH_H
#include "bihash.h"
+#include "coreSQLiteStudio_global.h"
#include <QHash>
#include <QString>
@@ -14,7 +15,7 @@
*
* Just like BiHash, the BiStrHash doesn't provide operator[]. For more details see BiHash.
*/
-class BiStrHash
+class API_EXPORT BiStrHash
{
public:
/**
@@ -26,11 +27,7 @@ class BiStrHash
* @brief Creates pre-initialized hash.
* @param list C++11 style initializer list, like: <tt>{{"x"="y"}, {"a"="b"}}</tt>
*/
- BiStrHash(std::initializer_list<std::pair<QString, QString>> list)
- {
- hash = QHash<QString,QString>(list);
- initInvertedAndLower();
- }
+ BiStrHash(std::initializer_list<std::pair<QString, QString>> list);
/**
* @brief Creates BiStrHash basing on QHash.
@@ -39,17 +36,13 @@ class BiStrHash
* Any conflicting values from the \p other hash will overwrite
* current values in the hash.
*/
- BiStrHash(const QHash<QString, QString> & other)
- {
- unite(other);
- }
+ BiStrHash(const QHash<QString, QString> & other);
/**
* @brief Copy constructor.
* @param other Other hash to copy.
*/
- BiStrHash(const BiStrHash& other) : hash(other.hash), inverted(other.inverted),
- lowerHash(other.lowerHash), lowerInverted(other.lowerInverted) {}
+ BiStrHash(const BiStrHash& other);
/**
* @brief Inserts entry into the hash.
@@ -59,19 +52,7 @@ class BiStrHash
* Inserting to the hash is done in case-insensitive manner, hence any conflicting
* values matched with case insensitive method will be replaced with the new entry.
*/
- void insert(const QString& left, const QString& right)
- {
- if (lowerHash.contains(left.toLower()))
- removeLeft(left, Qt::CaseInsensitive);
-
- if (lowerInverted.contains(right.toLower()))
- removeRight(right, Qt::CaseInsensitive);
-
- inverted.insert(right, left);
- hash.insert(left, right);
- lowerHash.insert(left.toLower(), left);
- lowerInverted.insert(right.toLower(), right);
- }
+ void insert(const QString& left, const QString& right);
/**
* @brief Tests if given value is in the left values of the hash.
@@ -79,13 +60,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return true if the key was matched in left side values, or false otherwise.
*/
- bool containsLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- return hash.contains(left);
- else
- return lowerHash.contains(left.toLower());
- }
+ bool containsLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Tests if given value is in the right values of the hash.
@@ -93,13 +68,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return true if the key was matched in right side values, or false otherwise.
*/
- bool containsRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- return inverted.contains(right);
- else
- return lowerInverted.contains(right.toLower());
- }
+ bool containsRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry matching given value in left-side values.
@@ -107,34 +76,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Number of entries removed.
*/
- int removeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- if (!hash.contains(left))
- return 0;
-
- inverted.remove(hash.value(left));
- hash.remove(left);
-
- return 1;
- }
- else
- {
- QString lowerLeft = left.toLower();
- if (!lowerHash.contains(lowerLeft))
- return 0;
-
- QString right = hash.value(lowerHash.value(lowerLeft));
-
- hash.remove(inverted.value(right));
- inverted.remove(right);
- lowerHash.remove(lowerLeft);
- lowerInverted.remove(right.toLower());
-
- return 1;
- }
- }
+ int removeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry matching given value in right-side values.
@@ -142,34 +84,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Number of entries removed.
*/
- int removeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- if (!inverted.contains(right))
- return 0;
-
- hash.remove(inverted.value(right));
- inverted.remove(right);
-
- return 1;
- }
- else
- {
- QString lowerRight = right.toLower();
- if (!lowerInverted.contains(lowerRight))
- return 0;
-
- QString left = inverted.value(lowerInverted.value(lowerRight));
-
- inverted.remove(hash.value(left));
- hash.remove(left);
- lowerHash.remove(left.toLower());
- lowerInverted.remove(lowerRight);
-
- return 1;
- }
- }
+ int removeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry from hash and returns it.
@@ -177,21 +92,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Right side value, or null string if the \p left was not matched.
*/
- QString takeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- QString right = hash.take(left);
- inverted.remove(right);
- return right;
- }
- else
- {
- QString right = hash.take(lowerHash.take(left.toLower()));
- inverted.remove(lowerInverted.take(right.toLower()));
- return right;
- }
- }
+ QString takeLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Removes entry from hash and returns it.
@@ -199,44 +100,19 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Left side value, or null string if the \p left was not matched.
*/
- QString takeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive)
- {
- if (cs == Qt::CaseSensitive)
- {
- QString left = inverted.take(right);
- hash.remove(left);
- return left;
- }
- else
- {
- QString left = inverted.take(lowerInverted.take(right.toLower()));
- hash.remove(lowerHash.take(left.toLower()));
- return left;
- }
- }
+ QString takeRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive);
/**
* @brief Copies all entries from the other hash to this hash.
* @param other Other hash to copy values from.
* @return Reference to this hash, after update.
*/
- BiStrHash& unite(const BiStrHash& other)
- {
- unite(other.hash);
- return *this;
- }
+ BiStrHash& unite(const BiStrHash& other);
/**
* @overload
*/
- BiStrHash& unite(const QHash<QString,QString>& other)
- {
- QHashIterator<QString, QString> it(other);
- while (it.hasNext())
- insert(it.next().key(), it.value());
-
- return *this;
- }
+ BiStrHash& unite(const QHash<QString,QString>& other);
/**
* @brief Finds right-side value by matching the left-side value.
@@ -244,13 +120,7 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Right-side value, or null string if left-side value was not matched.
*/
- QString valueByLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- {
- if (cs == Qt::CaseSensitive)
- return hash.value(left);
- else
- return hash.value(lowerHash.value(left.toLower()));
- }
+ QString valueByLeft(const QString& left, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
/**
* @brief Finds left-side value by matching the right-side value.
@@ -258,85 +128,48 @@ class BiStrHash
* @param cs Case sensitivity flag.
* @return Left-side value, or null string if right-side value was not matched.
*/
- QString valueByRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- {
- if (cs == Qt::CaseSensitive)
- return inverted.value(right);
- else
- return inverted.value(lowerInverted.value(right.toLower()));
- }
+ QString valueByRight(const QString& right, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
/**
* @brief Gives all left-side values.
* @return List of values.
*/
- QStringList leftValues() const
- {
- return hash.keys();
- }
+ QStringList leftValues() const;
/**
* @brief Gives all right-side values.
* @return List of values.
*/
- QStringList rightValues() const
- {
- return inverted.keys();
- }
+ QStringList rightValues() const;
/**
* @brief Provides java-style iterator for this hash.
* @return Iterator object.
*/
- QHashIterator<QString,QString> iterator() const
- {
- return QHashIterator<QString,QString>(hash);
- }
+ QHashIterator<QString,QString> iterator() const;
/**
* @brief Removes all entries from the hash.
*/
- void clear()
- {
- hash.clear();
- inverted.clear();
- lowerHash.clear();
- lowerInverted.clear();
- }
+ void clear();
/**
* @brief Counts all entries in the hash.
* @return Number of entries in the hash.
*/
- int count() const
- {
- return hash.count();
- }
+ int count() const;
/**
* @brief Tests whether the hash is empty or not.
* @return true if the hash is empty, false otherwise.
*/
- bool isEmpty() const
- {
- return hash.isEmpty();
- }
+ bool isEmpty() const;
private:
/**
* @brief Fills inverted and lower internal hashes basing on the main hash class member.
*/
- void initInvertedAndLower()
- {
- QHashIterator<QString,QString> it(hash);
- while (it.hasNext())
- {
- it.next();
- inverted[it.value()] = it.key();
- lowerHash[it.key().toLower()] = it.key();
- lowerInverted[it.value().toLower()] = it.value();
- }
- }
+ void initInvertedAndLower();
/**
* @brief Standard mapping - left to right.
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/sortedset.h b/SQLiteStudio3/coreSQLiteStudio/common/sortedset.h
new file mode 100644
index 0000000..266e409
--- /dev/null
+++ b/SQLiteStudio3/coreSQLiteStudio/common/sortedset.h
@@ -0,0 +1,64 @@
+#ifndef SORTEDSET_H
+#define SORTEDSET_H
+
+#include "common/sortedhash.h"
+
+template <class T>
+class SortedSet : private SortedHash<T, bool>
+{
+ public:
+ bool contains(const T &value) const
+ {
+ return QHash<T, bool>::containsKey(value);
+ }
+
+ int count() const
+ {
+ return size();
+ }
+
+ bool isEmpty() const
+ {
+ return SortedHash<T, bool>::isEmpty();
+ }
+
+ bool remove(const T& value)
+ {
+ return SortedHash<T, bool>::remove(value);
+ }
+
+ int size() const
+ {
+ return QHash<T, bool>::size();
+ }
+
+ void swap(SortedSet<T>& other)
+ {
+ return SortedHash<T, bool>::swap(other);
+ }
+
+ SortedSet<T>& operator+=(const T& value)
+ {
+ SortedHash<T, bool>::insert(value, true);
+ return *this;
+ }
+
+ SortedSet<T>& operator-=(const T& value)
+ {
+ SortedHash<T, bool>::remove(value);
+ return *this;
+ }
+
+ QSet<T>& operator<<(const T &value)
+ {
+ SortedHash<T, bool>::insert(value, true);
+ return *this;
+ }
+
+ QList<T> toList()
+ {
+ return SortedHash<T, bool>::keys();
+ }
+};
+
+#endif // SORTEDSET_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/strhash.h b/SQLiteStudio3/coreSQLiteStudio/common/strhash.h
index 4fb7bb3..41b3d11 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/strhash.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/strhash.h
@@ -11,12 +11,12 @@ class StrHash
{
public:
StrHash() {}
- StrHash(std::initializer_list<std::pair<QString,T>> list) : hash(QHash<QString,T>(list))
+ StrHash(std::initializer_list<std::pair<QString, T>> list) : hash(QHash<QString, T>(list))
{
initLower();
}
- StrHash(const QHash<QString,T>& other) : hash(QHash<QString,T>(other))
+ StrHash(const QHash<QString, T>& other) : hash(QHash<QString, T>(other))
{
initLower();
}
@@ -87,9 +87,9 @@ class StrHash
return *this;
}
- StrHash<T>& unite(const QHash<QString,T>& other)
+ StrHash<T>& unite(const QHash<QString, T>& other)
{
- QHashIterator<QString,T> it(other);
+ QHashIterator<QString, T> it(other);
while (it.hasNext())
{
it.next();
@@ -117,9 +117,9 @@ class StrHash
return hash.keys();
}
- QHashIterator<QString,T> iterator() const
+ QHashIterator<QString, T> iterator() const
{
- return QHashIterator<QString,T>(hash);
+ return QHashIterator<QString, T>(hash);
}
void clear()
@@ -146,6 +146,11 @@ class StrHash
return hash.isEmpty();
}
+ QHash<QString, T> toQHash() const
+ {
+ return hash;
+ }
+
T& operator[](const QString& key)
{
if (lowerCaseHash.contains(key.toLower()) && !hash.contains(key))
@@ -167,7 +172,7 @@ class StrHash
private:
void initLower()
{
- QHashIterator<QString,T> it(hash);
+ QHashIterator<QString, T> it(hash);
while (it.hasNext())
{
it.next();
@@ -175,8 +180,8 @@ class StrHash
}
}
- QHash<QString,QString> lowerCaseHash;
- QHash<QString,T> hash;
+ QHash<QString, QString> lowerCaseHash;
+ QHash<QString, T> hash;
};
#endif // STRHASH_H
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
index f2b3d1c..6cf1892 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp
@@ -11,6 +11,8 @@
#include <QDebug>
#include <QRegularExpression>
#include <QDir>
+#include <QByteArray>
+#include <QDataStream>
#ifdef Q_OS_LINUX
#include <sys/utsname.h>
@@ -214,12 +216,12 @@ qint64 Range::length() const
return to - from + 1;
}
-QString generateUniqueName(const QString &baseName, const QStringList &existingNames)
+QString generateUniqueName(const QString& baseName, const QStringList& existingNames, Qt::CaseSensitivity cs)
{
QString name = baseName;
int i = 0;
- while (existingNames.contains(name))
- name = baseName+QString::number(i++);
+ while (existingNames.contains(name, cs))
+ name = baseName + QString::number(i++);
return name;
}
@@ -887,3 +889,38 @@ QString decryptRsa(const QString& input, const QString& modulus, const QString&
std::string result = RSA::Decrypt(inputStdStr, key);
return QString::fromStdString(result);
}
+
+QStringList concat(const QList<QStringList>& list)
+{
+ QStringList result;
+ for (const QStringList& item : list)
+ result.append(item);
+
+ return result;
+}
+
+QString doubleToString(double val)
+{
+ return QString::number(val, 'g', 16);
+}
+
+void sortWithReferenceList(QList<QString>& listToSort, const QList<QString>& referenceList, Qt::CaseSensitivity cs)
+{
+ qSort(listToSort.begin(), listToSort.end(), [referenceList, cs](const QString& s1, const QString& s2) -> bool
+ {
+ int idx1 = indexOf(referenceList, s1, cs);
+ int idx2 = indexOf(referenceList, s2, cs);
+ if (idx1 == -1 || idx2 == -1)
+ {
+ if (idx1 == -1 && idx2 == -1)
+ return false;
+
+ return (idx1 == -1);
+ }
+
+ if (idx1 == idx2)
+ return false;
+
+ return (idx1 > idx2);
+ });
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.h b/SQLiteStudio3/coreSQLiteStudio/common/utils.h
index 90d2d62..934e70a 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.h
@@ -57,7 +57,7 @@ API_EXPORT QString randStr(int length, bool numChars = true, bool whiteSpaces =
API_EXPORT QString randStr(int length, const QString& charCollection);
API_EXPORT QString randBinStr(int length);
API_EXPORT QString randStrNotIn(int length, const QSet<QString> set, bool numChars = true, bool whiteSpaces = false);
-API_EXPORT QString generateUniqueName(const QString& prefix, const QStringList& existingNames);
+API_EXPORT QString generateUniqueName(const QString& prefix, const QStringList& existingNames, Qt::CaseSensitivity cs = Qt::CaseSensitive);
API_EXPORT bool isNumeric(const QVariant& value);
API_EXPORT QString rStrip(const QString& str);
API_EXPORT QStringList tokenizeArgs(const QString& str);
@@ -73,6 +73,20 @@ API_EXPORT QHash<QString,QVariant> bytesToHash(const QByteArray& bytes);
API_EXPORT int indexOf(const QStringList& list, const QString& value, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive);
API_EXPORT int indexOf(const QStringList& list, const QString& value, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+template <class T>
+int indexOf(const QList<T>& list, std::function<bool(const T&)> predicate)
+{
+ int i = 0;
+ for (const T& item : list)
+ {
+ if (predicate(item))
+ return i;
+
+ ++i;
+ }
+ return -1;
+}
+
/**
* @brief Returns only those elements from the list, which passed the filter.
* @tparam T type for which the filter will be applied for. It should match the type in the list and in the function argument.
@@ -103,6 +117,18 @@ bool contains(const QList<T>& list, std::function<bool(const T& value)> testFunc
return false;
}
+template <class T>
+QList<T> concat(const QList<QList<T>>& list)
+{
+ QList<T> result;
+ for (const QList<T>& item : list)
+ result.append(item);
+
+ return result;
+}
+
+API_EXPORT QStringList concat(const QList<QStringList>& list);
+
/**
* @brief Appends or prepends characters to the string to make it of specified length.
* @param str Input string to work with.
@@ -205,6 +231,18 @@ API_EXPORT bool renameBetweenPartitions(const QString& src, const QString& dst);
API_EXPORT bool isWritableRecursively(const QString& dir);
API_EXPORT QString encryptRsa(const QString& input, const QString& modulus, const QString& exponent);
API_EXPORT QString decryptRsa(const QString& input, const QString& modulus, const QString& exponent);
+API_EXPORT QString doubleToString(double val);
+
+/**
+ * @brief Sorts string list using reference list for ordering.
+ * @param listToSort This list will be sorted.
+ * @param referenceList Should contain all elements from list to sort - it tells the order.
+ * @param cs Case sensitivity of the string comparision.
+ *
+ * Sorts \p listToSort using \p referenceList as a reference of what is the order.
+ * If any element from \p listToSort is not on the list of \p referenceList, then the element will be placed at the end.
+ */
+API_EXPORT void sortWithReferenceList(QList<QString>& listToSort, const QList<QString>& referenceList, Qt::CaseSensitivity cs = Qt::CaseSensitive);
enum class DistributionType
{
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
index eba10fa..5c7e7e9 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp
@@ -77,6 +77,16 @@ QString wrapObjIfNeeded(const QString& obj, Dialect dialect, NameWrapper favWrap
return obj;
}
+QString wrapObjIfNeeded(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper)
+{
+ return wrapObjIfNeeded(obj, dialect, ((useDoubleQuoteForEmptyValue && obj.isEmpty()) ? NameWrapper::DOUBLE_QUOTE : favWrapper));
+}
+
+QString wrapObjName(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper)
+{
+ return wrapObjName(obj, dialect, ((useDoubleQuoteForEmptyValue && obj.isEmpty()) ? NameWrapper::DOUBLE_QUOTE : favWrapper));
+}
+
QString wrapObjName(const QString& obj, Dialect dialect, NameWrapper favWrapper)
{
QString result = obj;
@@ -573,6 +583,8 @@ QueryAccessMode getQueryAccessMode(const QString& query, Dialect dialect, bool*
TokenList tokens = Lexer::tokenize(query, dialect);
int keywordIdx = tokens.indexOf(Token::KEYWORD);
+ if (keywordIdx < 0)
+ return QueryAccessMode::WRITE;
int cmdIdx = readOnlyCommands.indexOf(tokens[keywordIdx]->value.toUpper());
if (keywordIdx > -1 && cmdIdx > -1)
@@ -632,3 +644,53 @@ QueryAccessMode getQueryAccessMode(const QString& query, Dialect dialect, bool*
return QueryAccessMode::WRITE;
}
+
+QStringList valueListToSqlList(const QVariantList& values, Dialect dialect)
+{
+ QStringList argList;
+ for (const QVariant& value : values)
+ {
+ if (!value.isValid() || value.isNull())
+ {
+ argList << "NULL";
+ continue;
+ }
+
+ switch (value.userType())
+ {
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ argList << value.toString();
+ break;
+ case QVariant::Double:
+ argList << doubleToString(value.toDouble());
+ break;
+ case QVariant::Bool:
+ argList << QString::number(value.toInt());
+ break;
+ case QVariant::ByteArray:
+ {
+ if (dialect == Dialect::Sqlite3) // version 2 will go to the regular string processing
+ {
+ argList << "X'" + value.toByteArray().toHex().toUpper() + "'";
+ break;
+ }
+ }
+ default:
+ argList << wrapString(escapeString(value.toString()));
+ break;
+ }
+ }
+ return argList;
+}
+
+QStringList wrapStrings(const QStringList& strList)
+{
+ QStringList list;
+ for (const QString& str : strList)
+ list << wrapString(str);
+
+ return list;
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
index 038c146..ceccea0 100644
--- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
+++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.h
@@ -36,7 +36,9 @@ API_EXPORT bool isObjectWrapped(const QChar& c);
API_EXPORT bool doesStringNeedWrapping(const QString& str);
API_EXPORT bool isStringWrapped(const QString& str);
API_EXPORT QString wrapObjIfNeeded(const QString& obj, Dialect dialect, NameWrapper favWrapper = NameWrapper::null);
+API_EXPORT QString wrapObjIfNeeded(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper = NameWrapper::null);
API_EXPORT QString wrapObjName(const QString& obj, Dialect dialect, NameWrapper favWrapper = NameWrapper::null);
+API_EXPORT QString wrapObjName(const QString& obj, Dialect dialect, bool useDoubleQuoteForEmptyValue, NameWrapper favWrapper = NameWrapper::null);
API_EXPORT QString wrapObjName(const QString& obj, NameWrapper wrapper);
API_EXPORT TokenPtr stripObjName(TokenPtr token, Dialect dialect);
API_EXPORT QString stripObjName(const QString &str, Dialect dialect);
@@ -45,6 +47,7 @@ API_EXPORT bool isObjWrapped(const QString& str, Dialect dialect);
API_EXPORT NameWrapper getObjWrapper(const QString& str, Dialect dialect);
API_EXPORT bool isWrapperChar(const QChar& c, Dialect dialect);
API_EXPORT QString wrapString(const QString& str);
+API_EXPORT QStringList wrapStrings(const QStringList& strList);
API_EXPORT QString wrapStringIfNeeded(const QString& str);
API_EXPORT QString escapeString(QString &str);
API_EXPORT QString escapeString(const QString& str);
@@ -75,6 +78,7 @@ API_EXPORT QString trimBindParamPrefix(const QString& param);
API_EXPORT QString commentAllSqlLines(const QString& sql);
API_EXPORT QString getBindTokenName(const TokenPtr& token);
API_EXPORT QueryAccessMode getQueryAccessMode(const QString& query, Dialect dialect, bool* isSelect = nullptr);
+API_EXPORT QStringList valueListToSqlList(const QList<QVariant>& values, Dialect dialect);
#endif // UTILS_SQL_H