Improve removeIf() to support set types

We can now replace QMutable*Iterator by removeIf() which usage is more consistent with other
algorithm functions.
This commit is contained in:
Chocobo1
2019-05-12 13:26:06 +08:00
parent 4ed8b31641
commit c6f3da1097
7 changed files with 60 additions and 31 deletions

View File

@@ -28,14 +28,42 @@
#pragma once
namespace Dict
#include <type_traits>
namespace Algorithm
{
// To be used with QMap, QHash and it's variants
template <typename Dictionary, typename BinaryPredicate>
void removeIf(Dictionary &&dict, BinaryPredicate p)
template <typename ...>
using void_t = void; // replace this with std::void_t in C++17
template <typename T, typename = void>
struct HasMappedType
: std::false_type
{
};
template <typename T>
struct HasMappedType<T, void_t<typename T::mapped_type>>
: std::true_type
{
};
// To be used with associative array types, such as QMap, QHash and it's variants
template <typename T, typename BinaryPredicate
, typename std::enable_if_t<HasMappedType<T>::value, int> = 0>
void removeIf(T &dict, BinaryPredicate p)
{
auto it = dict.begin();
while (it != dict.end())
it = (p(it.key(), it.value()) ? dict.erase(it) : it + 1);
it = (p(it.key(), it.value()) ? dict.erase(it) : (it + 1));
}
// To be used with set types, such as QSet, std::set
template <typename T, typename UnaryPredicate
, typename std::enable_if_t<!HasMappedType<T>::value, int> = 0>
void removeIf(T &set, UnaryPredicate p)
{
auto it = set.begin();
while (it != set.end())
it = (p(*it) ? set.erase(it) : (it + 1));
}
}

View File

@@ -754,7 +754,7 @@ bool Session::removeCategory(const QString &name)
if (isSubcategoriesEnabled()) {
// remove subcategories
const QString test = name + '/';
Dict::removeIf(m_categories, [this, &test, &result](const QString &category, const QString &)
Algorithm::removeIf(m_categories, [this, &test, &result](const QString &category, const QString &)
{
if (category.startsWith(test)) {
result = true;

View File

@@ -122,7 +122,7 @@ void FileSystemWatcher::processPartialTorrents()
QStringList noLongerPartial;
// Check which torrents are still partial
Dict::removeIf(m_partialTorrents, [&noLongerPartial](const QString &torrentPath, int &value)
Algorithm::removeIf(m_partialTorrents, [&noLongerPartial](const QString &torrentPath, int &value)
{
if (!QFile::exists(torrentPath))
return true;

View File

@@ -32,7 +32,6 @@
#include <algorithm>
#include <QMutableListIterator>
#include <QNetworkProxy>
#include <QSslCipher>
#include <QSslConfiguration>
@@ -40,6 +39,7 @@
#include <QStringList>
#include <QTimer>
#include "base/algorithm.h"
#include "base/utils/net.h"
#include "connection.h"
@@ -119,14 +119,14 @@ void Server::removeConnection(Connection *connection)
void Server::dropTimedOutConnection()
{
QMutableSetIterator<Connection *> i(m_connections);
while (i.hasNext()) {
Connection *connection = i.next();
if (connection->hasExpired(KEEP_ALIVE_DURATION)) {
connection->deleteLater();
i.remove();
}
}
Algorithm::removeIf(m_connections, [](Connection *connection)
{
if (!connection->hasExpired(KEEP_ALIVE_DURATION))
return false;
connection->deleteLater();
return true;
});
}
bool Server::setupHttps(const QByteArray &certificates, const QByteArray &privateKey)

View File

@@ -31,7 +31,6 @@
#include <QDir>
#include <QLocale>
#include <QMutableListIterator>
#include <QSettings>
#ifndef DISABLE_GUI
@@ -49,6 +48,7 @@
#include <CoreServices/CoreServices.h>
#endif
#include "algorithm.h"
#include "global.h"
#include "settingsstorage.h"
#include "utils/fs.h"
@@ -516,13 +516,12 @@ QList<Utils::Net::Subnet> Preferences::getWebUiAuthSubnetWhitelist() const
void Preferences::setWebUiAuthSubnetWhitelist(QStringList subnets)
{
QMutableListIterator<QString> i(subnets);
while (i.hasNext()) {
Algorithm::removeIf(subnets, [](const QString &subnet)
{
bool ok = false;
const Utils::Net::Subnet subnet = Utils::Net::parseSubnet(i.next().trimmed(), &ok);
if (!ok)
i.remove();
}
Utils::Net::parseSubnet(subnet.trimmed(), &ok);
return !ok;
});
setValue("Preferences/WebUI/AuthSubnetWhitelist", subnets);
}