/* * This file Copyright (C) 2020 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * */ #pragma once #include #include #include #include #include class QByteArray; class Speed; class TorrentHash; struct Peer; struct TorrentFile; struct TrackerStat; namespace trqt { namespace variant_helpers { template>::type* = nullptr> auto getValue(tr_variant const* variant) { std::optional ret; auto value = T{}; if (tr_variantGetBool(variant, &value)) { ret = value; } return ret; } template< typename T, typename std::enable_if< std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v>::type* = nullptr> auto getValue(tr_variant const* variant) { std::optional ret; auto value = int64_t{}; if (tr_variantGetInt(variant, &value)) { ret = value; } return ret; } template>::type* = nullptr> auto getValue(tr_variant const* variant) { std::optional ret; auto value = T{}; if (tr_variantGetReal(variant, &value)) { ret = value; } return ret; } template>::type* = nullptr> auto getValue(tr_variant const* variant) { std::optional ret; char const* str; size_t len; if (tr_variantGetStr(variant, &str, &len)) { ret = QString::fromUtf8(str, len); } return ret; } template>::type* = nullptr> auto getValue(tr_variant const* variant) { std::optional ret; char const* str; size_t len; if (tr_variantGetStr(variant, &str, &len)) { ret = std::string_view(str, len); } return ret; } template< typename C, typename T = typename C::value_type, typename std::enable_if< std::is_same_v || std::is_same_v> || std::is_same_v>>::type* = nullptr> auto getValue(tr_variant const* variant) { std::optional 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(variant), i); auto const value = getValue(child); if (value) { list.push_back(*value); } } ret = list; } return ret; } template 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 bool change(T& setme, tr_variant const* variant) { auto const value = getValue(variant); return value && change(setme, *value); } template bool change(QVector& setme, tr_variant const* value) { bool changed = false; int const n = tr_variantListSize(value); if (setme.size() != n) { setme.resize(n); changed = true; } for (int i = 0; i < n; ++i) { changed = change(setme[i], tr_variantListChild(const_cast(value), i)) || changed; } return changed; } /// template auto dictFind(tr_variant* dict, tr_quark key) { std::optional ret; auto const* child = tr_variantDictFind(dict, key); if (child != nullptr) { ret = getValue(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, unsigned 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 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 void listAdd(tr_variant* list, T const& value) { variantInit(tr_variantListAdd(list), value); } template void dictAdd(tr_variant* dict, tr_quark key, T const& value) { variantInit(tr_variantDictAdd(dict, key), value); } } // namespace variant_helpers } // namespace trqt