transmission/qt/VariantHelpers.h

227 lines
5.1 KiB
C++

// This file Copyright © 2020-2022 Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#pragma once
#include <ctime>
#include <optional>
#include <string_view>
#include <vector>
#include <QString>
#include <libtransmission/variant.h>
class QByteArray;
class Speed;
class TorrentHash;
struct Peer;
struct TorrentFile;
struct TrackerStat;
namespace trqt
{
namespace variant_helpers
{
template<typename T, typename std::enable_if_t<std::is_same_v<T, bool>>* = nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<T> ret;
if (auto value = T{}; tr_variantGetBool(variant, &value))
{
ret = value;
}
return ret;
}
template<
typename T,
typename std::enable_if_t<
std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t> || std::is_same_v<T, int> || std::is_same_v<T, time_t>>* =
nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<T> ret;
if (auto value = int64_t{}; tr_variantGetInt(variant, &value))
{
ret = value;
}
return ret;
}
template<typename T, typename std::enable_if_t<std::is_same_v<T, double>>* = nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<T> ret;
if (auto value = T{}; tr_variantGetReal(variant, &value))
{
ret = value;
}
return ret;
}
template<typename T, typename std::enable_if_t<std::is_same_v<T, QString>>* = nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<T> ret;
if (auto sv = std::string_view{}; tr_variantGetStrView(variant, &sv))
{
ret = QString::fromUtf8(std::data(sv), std::size(sv));
}
return ret;
}
template<typename T, typename std::enable_if_t<std::is_same_v<T, std::string_view>>* = nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<T> ret;
if (auto sv = std::string_view{}; tr_variantGetStrView(variant, &sv))
{
ret = std::string_view(std::data(sv), std::size(sv));
}
return ret;
}
template<
typename C,
typename T = typename C::value_type,
typename std::enable_if_t<
std::is_same_v<C, QStringList> || std::is_same_v<C, QList<T>> || std::is_same_v<C, std::vector<T>>>* = nullptr>
auto getValue(tr_variant const* variant)
{
std::optional<C> ret;
if (tr_variantIsList(variant))
{
auto list = C{};
for (size_t i = 0, n = tr_variantListSize(variant); i < n; ++i)
{
tr_variant* const child = tr_variantListChild(const_cast<tr_variant*>(variant), i);
auto const value = getValue<T>(child);
if (value)
{
list.push_back(*value);
}
}
ret = list;
}
return ret;
}
template<typename T>
bool change(T& setme, T const& value)
{
bool const changed = setme != value;
if (changed)
{
setme = value;
}
return changed;
}
bool change(double& setme, double const& value);
bool change(Speed& setme, tr_variant const* value);
bool change(Peer& setme, tr_variant const* value);
bool change(TorrentFile& setme, tr_variant const* value);
bool change(TorrentHash& setme, tr_variant const* value);
bool change(TrackerStat& setme, tr_variant const* value);
template<typename T>
bool change(T& setme, tr_variant const* variant)
{
auto const value = getValue<T>(variant);
return value && change(setme, *value);
}
template<typename T>
bool change(std::vector<T>& setme, tr_variant const* value)
{
bool changed = false;
auto const n = tr_variantListSize(value);
if (setme.size() != n)
{
setme.resize(n);
changed = true;
}
for (size_t i = 0; i < n; ++i)
{
changed = change(setme[i], tr_variantListChild(const_cast<tr_variant*>(value), i)) || changed;
}
return changed;
}
///
template<typename T>
auto dictFind(tr_variant* dict, tr_quark key)
{
std::optional<T> ret;
if (auto const* child = tr_variantDictFind(dict, key); child != nullptr)
{
ret = getValue<T>(child);
}
return ret;
}
///
void variantInit(tr_variant* init_me, bool value);
void variantInit(tr_variant* init_me, int64_t value);
void variantInit(tr_variant* init_me, int value);
void variantInit(tr_variant* init_me, double value);
void variantInit(tr_variant* init_me, QByteArray const& value);
void variantInit(tr_variant* init_me, QString const& value);
void variantInit(tr_variant* init_me, std::string_view value);
void variantInit(tr_variant* init_me, char const* value) = delete; // use string_view
template<typename C, typename T = typename C::value_type>
void variantInit(tr_variant* init_me, C const& value)
{
tr_variantInitList(init_me, std::size(value));
for (auto const& item : value)
{
variantInit(tr_variantListAdd(init_me), item);
}
}
template<typename T>
void listAdd(tr_variant* list, T const& value)
{
variantInit(tr_variantListAdd(list), value);
}
template<typename T>
void dictAdd(tr_variant* dict, tr_quark key, T const& value)
{
variantInit(tr_variantDictAdd(dict, key), value);
}
} // namespace variant_helpers
} // namespace trqt