From e1c9fbde607b8cbb2aea09f611478cf56b7fc0c2 Mon Sep 17 00:00:00 2001 From: Yat Ho Date: Mon, 1 Apr 2024 03:06:36 +0800 Subject: [PATCH] fix: restore loose data type parsing in RPC and `settings.json` (#6723) * refactor: incorporate lenient parsing from `tr_variantGet*()` functions into `tr_variant` * fix: restore loose data types in RPC and settings.json * fix: workaround GCC defect * fix: MSVC build --- libtransmission/rpcimpl.cc | 186 ++++++++++++++++++------------------ libtransmission/session.cc | 12 +-- libtransmission/settings.cc | 40 ++++---- libtransmission/variant.cc | 173 +++++++++++++++++---------------- libtransmission/variant.h | 30 +++++- 5 files changed, 238 insertions(+), 203 deletions(-) diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index 3bd5b65ce..ce7f547b9 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -105,12 +105,12 @@ void tr_idle_function_done(struct tr_rpc_idle_data* data, std::string_view resul { tr_torrent* tor = nullptr; - if (auto const* val = var.get_if(); val != nullptr) + if (auto const val = var.value_if()) { tor = torrents.get(*val); } - if (auto const* val = var.get_if(); val != nullptr) + if (auto const val = var.value_if()) { if (*val == "recently-active"sv) { @@ -741,7 +741,7 @@ char const* torrentGet(tr_session* session, tr_variant::Map const& args_in, tr_v keys.reserve(n_fields); for (auto const& field : *fields_vec) { - if (auto const* field_sv = field.get_if(); field_sv != nullptr) + if (auto const field_sv = field.value_if()) { if (auto const key = tr_quark_lookup(*field_sv); key && isSupportedTorrentGetField(*key)) { @@ -788,7 +788,7 @@ char const* torrentGet(tr_session* session, tr_variant::Map const& args_in, tr_v labels.reserve(n_labels); for (auto const& label_var : labels_vec) { - if (auto const* value = label_var.get_if(); value != nullptr) + if (auto const value = label_var.value_if()) { auto const label = tr_strv_strip(*value); @@ -840,7 +840,7 @@ char const* set_labels(tr_torrent* tor, tr_variant::Vector const& list) { for (auto const& file_var : files_vec) { - if (auto const* val = file_var.get_if(); val != nullptr) + if (auto const val = file_var.value_if()) { if (auto const idx = static_cast(*val); idx < n_files) { @@ -887,7 +887,7 @@ char const* add_tracker_urls(tr_torrent* tor, tr_variant::Vector const& urls_vec for (auto const& url_var : urls_vec) { - if (auto const* val = url_var.get_if(); val != nullptr) + if (auto const val = url_var.value_if()) { ann.add(*val); } @@ -909,10 +909,10 @@ char const* replace_trackers(tr_torrent* tor, tr_variant::Vector const& urls_vec for (size_t i = 0, vec_size = std::size(urls_vec); i + 1 < vec_size; i += 2U) { - auto const* id = urls_vec[i].get_if(); - auto const* url = urls_vec[i + 1U].get_if(); + auto const id = urls_vec[i].value_if(); + auto const url = urls_vec[i + 1U].value_if(); - if (id != nullptr && url != nullptr) + if (id && url) { ann.replace(static_cast(*id), *url); } @@ -934,7 +934,7 @@ char const* remove_trackers(tr_torrent* tor, tr_variant::Vector const& ids_vec) for (auto const& id_var : ids_vec) { - if (auto const* val = id_var.get_if(); val != nullptr) + if (auto const val = id_var.value_if()) { ann.remove(static_cast(*val)); } @@ -955,7 +955,7 @@ char const* torrentSet(tr_session* session, tr_variant::Map const& args_in, tr_v for (auto* tor : getTorrents(session, args_in)) { - if (auto const* val = args_in.find_if(TR_KEY_bandwidthPriority); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_bandwidthPriority)) { if (auto const priority = static_cast(*val); tr_isPriority(priority)) { @@ -963,7 +963,7 @@ char const* torrentSet(tr_session* session, tr_variant::Map const& args_in, tr_v } } - if (auto const* val = args_in.find_if(TR_KEY_group); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_group)) { tor->set_bandwidth_group(*val); } @@ -983,7 +983,7 @@ char const* torrentSet(tr_session* session, tr_variant::Map const& args_in, tr_v errmsg = set_file_dls(tor, true, *val); } - if (auto const* val = args_in.find_if(TR_KEY_peer_limit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_peer_limit)) { tr_torrentSetPeerLimit(tor, *val); } @@ -1003,77 +1003,77 @@ char const* torrentSet(tr_session* session, tr_variant::Map const& args_in, tr_v errmsg = set_file_priorities(tor, TR_PRI_NORMAL, *val); } - if (auto const* val = args_in.find_if(TR_KEY_downloadLimit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_downloadLimit)) { tr_torrentSetSpeedLimit_KBps(tor, TR_DOWN, *val); } - if (auto const* val = args_in.find_if(TR_KEY_sequentialDownload); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_sequentialDownload)) { tor->set_sequential_download(*val); } - if (auto const* val = args_in.find_if(TR_KEY_downloadLimited); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_downloadLimited)) { tor->use_speed_limit(TR_DOWN, *val); } - if (auto const* val = args_in.find_if(TR_KEY_honorsSessionLimits); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_honorsSessionLimits)) { tr_torrentUseSessionLimits(tor, *val); } - if (auto const* val = args_in.find_if(TR_KEY_uploadLimit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_uploadLimit)) { tr_torrentSetSpeedLimit_KBps(tor, TR_UP, *val); } - if (auto const* val = args_in.find_if(TR_KEY_uploadLimited); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_uploadLimited)) { tor->use_speed_limit(TR_UP, *val); } - if (auto const* val = args_in.find_if(TR_KEY_seedIdleLimit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seedIdleLimit)) { tor->set_idle_limit_minutes(static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_seedIdleMode); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seedIdleMode)) { tor->set_idle_limit_mode(static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_seedRatioLimit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seedRatioLimit)) { tor->set_seed_ratio(*val); } - if (auto const* val = args_in.find_if(TR_KEY_seedRatioMode); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seedRatioMode)) { tor->set_seed_ratio_mode(static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_queuePosition); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_queuePosition)) { tr_torrentSetQueuePosition(tor, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_trackerAdd); val != nullptr) + if (auto const* val = args_in.find_if(TR_KEY_trackerAdd)) { errmsg = add_tracker_urls(tor, *val); } - if (auto const* val = args_in.find_if(TR_KEY_trackerRemove); val != nullptr) + if (auto const* val = args_in.find_if(TR_KEY_trackerRemove)) { errmsg = remove_trackers(tor, *val); } - if (auto const* val = args_in.find_if(TR_KEY_trackerReplace); val != nullptr) + if (auto const* val = args_in.find_if(TR_KEY_trackerReplace)) { errmsg = replace_trackers(tor, *val); } - if (auto const* val = args_in.find_if(TR_KEY_trackerList); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_trackerList)) { if (!tor->set_announce_list(*val)) { @@ -1089,8 +1089,8 @@ char const* torrentSet(tr_session* session, tr_variant::Map const& args_in, tr_v char const* torrentSetLocation(tr_session* session, tr_variant::Map const& args_in, tr_variant::Map& /*args_out*/) { - auto const* const location = args_in.find_if(TR_KEY_location); - if (location == nullptr) + auto const location = args_in.value_if(TR_KEY_location); + if (!location) { return "no location"; } @@ -1174,7 +1174,7 @@ char const* portTest(tr_session* session, tr_variant::Map const& args_in, struct auto options = tr_web::FetchOptions{ url, onPortTested, idle_data }; options.timeout_secs = TimeoutSecs; - if (auto const* val = args_in.find_if(TR_KEY_ipProtocol); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_ipProtocol)) { if (*val == "ipv4"sv) { @@ -1359,7 +1359,7 @@ bool isCurlURL(std::string_view url) files.reserve(n_files); for (auto const& idx_var : idx_vec) { - if (auto const* val = idx_var.get_if(); val != nullptr) + if (auto const val = idx_var.value_if()) { files.emplace_back(static_cast(*val)); } @@ -1395,52 +1395,52 @@ char const* torrentAdd(tr_session* session, tr_variant::Map const& args_in, tr_r ctor.set_download_dir(TR_FORCE, *download_dir); } - if (auto const* val = args_in.find_if(TR_KEY_paused); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_paused)) { ctor.set_paused(TR_FORCE, *val); } - if (auto const* val = args_in.find_if(TR_KEY_peer_limit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_peer_limit)) { ctor.set_peer_limit(TR_FORCE, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_bandwidthPriority); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_bandwidthPriority)) { ctor.set_bandwidth_priority(static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_files_unwanted); val != nullptr) + if (auto const val = args_in.find_if(TR_KEY_files_unwanted)) { auto const files = file_list_from_list(*val); ctor.set_files_wanted(std::data(files), std::size(files), false); } - if (auto const* val = args_in.find_if(TR_KEY_files_wanted); val != nullptr) + if (auto const val = args_in.find_if(TR_KEY_files_wanted)) { auto const files = file_list_from_list(*val); ctor.set_files_wanted(std::data(files), std::size(files), true); } - if (auto const* val = args_in.find_if(TR_KEY_priority_low); val != nullptr) + if (auto const val = args_in.find_if(TR_KEY_priority_low)) { auto const files = file_list_from_list(*val); ctor.set_file_priorities(std::data(files), std::size(files), TR_PRI_LOW); } - if (auto const* val = args_in.find_if(TR_KEY_priority_normal); val != nullptr) + if (auto const* val = args_in.find_if(TR_KEY_priority_normal)) { auto const files = file_list_from_list(*val); ctor.set_file_priorities(std::data(files), std::size(files), TR_PRI_NORMAL); } - if (auto const* val = args_in.find_if(TR_KEY_priority_high); val != nullptr) + if (auto const* val = args_in.find_if(TR_KEY_priority_high)) { auto const files = file_list_from_list(*val); ctor.set_file_priorities(std::data(files), std::size(files), TR_PRI_HIGH); } - if (auto const* val = args_in.find_if(TR_KEY_labels); val != nullptr) + if (auto const* val = args_in.find_if(TR_KEY_labels)) { auto [labels, errmsg] = make_labels(*val); @@ -1493,7 +1493,7 @@ char const* torrentAdd(tr_session* session, tr_variant::Map const& args_in, tr_r void add_strings_from_var(std::set& strings, tr_variant const& var) { - if (auto const* val = var.get_if(); val != nullptr) + if (auto const val = var.value_if()) { strings.insert(*val); return; @@ -1548,29 +1548,29 @@ char const* groupSet(tr_session* session, tr_variant::Map const& args_in, tr_var auto& group = session->getBandwidthGroup(name); auto limits = group.get_limits(); - if (auto const* const val = args_in.find_if(TR_KEY_speed_limit_down_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_down_enabled)) { limits.down_limited = *val; } - if (auto const* const val = args_in.find_if(TR_KEY_speed_limit_up_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_up_enabled)) { limits.up_limited = *val; } - if (auto const* const val = args_in.find_if(TR_KEY_speed_limit_down); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_down)) { limits.down_limit = Speed{ *val, Speed::Units::KByps }; } - if (auto const* const val = args_in.find_if(TR_KEY_speed_limit_up); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_up)) { limits.up_limit = Speed{ *val, Speed::Units::KByps }; } group.set_limits(limits); - if (auto const* const val = args_in.find_if(TR_KEY_honorsSessionLimits); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_honorsSessionLimits)) { group.honor_parent_limits(TR_UP, *val); group.honor_parent_limits(TR_DOWN, *val); @@ -1595,52 +1595,52 @@ char const* sessionSet(tr_session* session, tr_variant::Map const& args_in, tr_v return "incomplete torrents directory path is not absolute"; } - if (auto const* val = args_in.find_if(TR_KEY_cache_size_mb); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_cache_size_mb)) { tr_sessionSetCacheLimit_MB(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_up); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_up)) { tr_sessionSetAltSpeed_KBps(session, TR_UP, *val); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_down); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_down)) { tr_sessionSetAltSpeed_KBps(session, TR_DOWN, *val); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_enabled)) { tr_sessionUseAltSpeed(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_time_begin); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_time_begin)) { tr_sessionSetAltSpeedBegin(session, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_time_end); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_time_end)) { tr_sessionSetAltSpeedEnd(session, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_time_day); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_time_day)) { tr_sessionSetAltSpeedDay(session, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_alt_speed_time_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_alt_speed_time_enabled)) { tr_sessionUseAltSpeedTime(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_blocklist_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_blocklist_enabled)) { session->set_blocklist_enabled(*val); } - if (auto const* val = args_in.find_if(TR_KEY_blocklist_url); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_blocklist_url)) { session->setBlocklistUrl(*val); } @@ -1650,27 +1650,27 @@ char const* sessionSet(tr_session* session, tr_variant::Map const& args_in, tr_v session->setDownloadDir(*download_dir); } - if (auto const* val = args_in.find_if(TR_KEY_queue_stalled_minutes); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_queue_stalled_minutes)) { tr_sessionSetQueueStalledMinutes(session, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_queue_stalled_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_queue_stalled_enabled)) { tr_sessionSetQueueStalledEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_default_trackers); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_default_trackers)) { session->setDefaultTrackers(*val); } - if (auto const* val = args_in.find_if(TR_KEY_download_queue_size); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_download_queue_size)) { tr_sessionSetQueueSize(session, TR_DOWN, *val); } - if (auto const* val = args_in.find_if(TR_KEY_download_queue_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_download_queue_enabled)) { tr_sessionSetQueueEnabled(session, TR_DOWN, *val); } @@ -1680,135 +1680,135 @@ char const* sessionSet(tr_session* session, tr_variant::Map const& args_in, tr_v session->setIncompleteDir(*incomplete_dir); } - if (auto const* val = args_in.find_if(TR_KEY_incomplete_dir_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_incomplete_dir_enabled)) { session->useIncompleteDir(*val); } - if (auto const* val = args_in.find_if(TR_KEY_peer_limit_global); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_peer_limit_global)) { tr_sessionSetPeerLimit(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_peer_limit_per_torrent); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_peer_limit_per_torrent)) { tr_sessionSetPeerLimitPerTorrent(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_pex_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_pex_enabled)) { tr_sessionSetPexEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_dht_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_dht_enabled)) { tr_sessionSetDHTEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_utp_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_utp_enabled)) { tr_sessionSetUTPEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_lpd_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_lpd_enabled)) { tr_sessionSetLPDEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_peer_port_random_on_start); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_peer_port_random_on_start)) { tr_sessionSetPeerPortRandomOnStart(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_peer_port); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_peer_port)) { tr_sessionSetPeerPort(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_port_forwarding_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_port_forwarding_enabled)) { tr_sessionSetPortForwardingEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_rename_partial_files); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_rename_partial_files)) { tr_sessionSetIncompleteFileNamingEnabled(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_seedRatioLimit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seedRatioLimit)) { tr_sessionSetRatioLimit(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_seedRatioLimited); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seedRatioLimited)) { tr_sessionSetRatioLimited(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_idle_seeding_limit); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_idle_seeding_limit)) { tr_sessionSetIdleLimit(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_idle_seeding_limit_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_idle_seeding_limit_enabled)) { tr_sessionSetIdleLimited(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_start_added_torrents); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_start_added_torrents)) { tr_sessionSetPaused(session, !*val); } - if (auto const* val = args_in.find_if(TR_KEY_seed_queue_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seed_queue_enabled)) { tr_sessionSetQueueEnabled(session, TR_UP, *val); } - if (auto const* val = args_in.find_if(TR_KEY_seed_queue_size); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_seed_queue_size)) { tr_sessionSetQueueSize(session, TR_UP, *val); } for (auto const& [enabled_key, script_key, script] : tr_session::Scripts) { - if (auto const* val = args_in.find_if(enabled_key); val != nullptr) + if (auto const val = args_in.value_if(enabled_key)) { session->useScript(script, *val); } - if (auto const* val = args_in.find_if(script_key); val != nullptr) + if (auto const val = args_in.value_if(script_key)) { session->setScript(script, *val); } } - if (auto const* val = args_in.find_if(TR_KEY_trash_original_torrent_files); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_trash_original_torrent_files)) { tr_sessionSetDeleteSource(session, *val); } - if (auto const* val = args_in.find_if(TR_KEY_speed_limit_down); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_down)) { session->set_speed_limit(TR_DOWN, Speed{ *val, Speed::Units::KByps }); } - if (auto const* val = args_in.find_if(TR_KEY_speed_limit_down_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_down_enabled)) { tr_sessionLimitSpeed(session, TR_DOWN, *val); } - if (auto const* val = args_in.find_if(TR_KEY_speed_limit_up); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_up)) { session->set_speed_limit(TR_UP, Speed{ *val, Speed::Units::KByps }); } - if (auto const* val = args_in.find_if(TR_KEY_speed_limit_up_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_speed_limit_up_enabled)) { tr_sessionLimitSpeed(session, TR_UP, *val); } - if (auto const* val = args_in.find_if(TR_KEY_encryption); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_encryption)) { if (*val == "required"sv) { @@ -1824,12 +1824,12 @@ char const* sessionSet(tr_session* session, tr_variant::Map const& args_in, tr_v } } - if (auto const* val = args_in.find_if(TR_KEY_anti_brute_force_threshold); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_anti_brute_force_threshold)) { tr_sessionSetAntiBruteForceThreshold(session, static_cast(*val)); } - if (auto const* val = args_in.find_if(TR_KEY_anti_brute_force_enabled); val != nullptr) + if (auto const val = args_in.value_if(TR_KEY_anti_brute_force_enabled)) { tr_sessionSetAntiBruteForceEnabled(session, *val); } @@ -1994,7 +1994,7 @@ namespace session_get_helpers { for (auto const& field_var : *fields_vec) { - if (auto const* field_name = field_var.get_if(); field_name != nullptr) + if (auto const field_name = field_var.value_if()) { if (auto const field_id = tr_quark_lookup(*field_name); field_id) { @@ -2126,13 +2126,13 @@ void tr_rpc_request_exec(tr_session* session, tr_variant const& request, tr_rpc_ if (request_map != nullptr) { // find the args - if (auto const* val = request_map->find_if(TR_KEY_arguments); val != nullptr) + if (auto const* val = request_map->find_if(TR_KEY_arguments)) { args_in = val; } // find the requested method - if (auto const* val = request_map->find_if(TR_KEY_method); val != nullptr) + if (auto const val = request_map->value_if(TR_KEY_method)) { method_name = *val; } diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 8fdbada0c..67f76b532 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -101,29 +101,29 @@ void bandwidthGroupRead(tr_session* session, std::string_view config_dir) auto& group = session->getBandwidthGroup(tr_interned_string{ key }); auto limits = tr_bandwidth_limits{}; - if (auto const* val = group_map->find_if(TR_KEY_uploadLimited); val != nullptr) + if (auto const val = group_map->value_if(TR_KEY_uploadLimited)) { limits.up_limited = *val; } - if (auto const* val = group_map->find_if(TR_KEY_downloadLimited); val != nullptr) + if (auto const val = group_map->value_if(TR_KEY_downloadLimited)) { limits.down_limited = *val; } - if (auto const* val = group_map->find_if(TR_KEY_uploadLimit); val != nullptr) + if (auto const val = group_map->value_if(TR_KEY_uploadLimit)) { limits.up_limit = Speed{ *val, Speed::Units::KByps }; } - if (auto const* val = group_map->find_if(TR_KEY_downloadLimit); val != nullptr) + if (auto const val = group_map->value_if(TR_KEY_downloadLimit)) { limits.down_limit = Speed{ *val, Speed::Units::KByps }; } group.set_limits(limits); - if (auto const* val = group_map->find_if(TR_KEY_honorsSessionLimits); val != nullptr) + if (auto const val = group_map->value_if(TR_KEY_honorsSessionLimits)) { group.honor_parent_limits(TR_UP, *val); group.honor_parent_limits(TR_DOWN, *val); @@ -565,7 +565,7 @@ tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled // if logging is desired, start it now before doing more work if (auto const* settings_map = settings.get_if(); settings_map != nullptr) { - if (auto const* val = settings_map->find_if(TR_KEY_message_level); val != nullptr) + if (auto const val = settings_map->value_if(TR_KEY_message_level)) { tr_logSetLevel(static_cast(*val)); } diff --git a/libtransmission/settings.cc b/libtransmission/settings.cc index dee8754d2..24f0a5034 100644 --- a/libtransmission/settings.cc +++ b/libtransmission/settings.cc @@ -38,7 +38,7 @@ using Lookup = std::array, N>; bool load_bool(tr_variant const& src, bool* tgt) { - if (auto val = src.get_if(); val != nullptr) + if (auto val = src.value_if()) { *tgt = *val; return true; @@ -56,7 +56,7 @@ tr_variant save_bool(bool const& val) bool load_double(tr_variant const& src, double* tgt) { - if (auto val = src.get_if(); val != nullptr) + if (auto val = src.value_if()) { *tgt = *val; return true; @@ -82,7 +82,7 @@ bool load_encryption_mode(tr_variant const& src, tr_encryption_mode* tgt) { static constexpr auto& Keys = EncryptionKeys; - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { auto const needle = tr_strlower(tr_strv_strip(*val)); @@ -96,7 +96,7 @@ bool load_encryption_mode(tr_variant const& src, tr_encryption_mode* tgt) } } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { for (auto const& [key, encryption] : Keys) { @@ -132,7 +132,7 @@ bool load_log_level(tr_variant const& src, tr_log_level* tgt) { static constexpr auto& Keys = LogKeys; - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { auto const needle = tr_strlower(tr_strv_strip(*val)); @@ -146,7 +146,7 @@ bool load_log_level(tr_variant const& src, tr_log_level* tgt) } } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { for (auto const& [name, log_level] : Keys) { @@ -170,7 +170,7 @@ tr_variant save_log_level(tr_log_level const& val) bool load_mode_t(tr_variant const& src, tr_mode_t* tgt) { - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { if (auto const mode = tr_num_parse(*val, nullptr, 8); mode) { @@ -179,7 +179,7 @@ bool load_mode_t(tr_variant const& src, tr_mode_t* tgt) } } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { *tgt = static_cast(*val); return true; @@ -197,7 +197,7 @@ tr_variant save_mode_t(tr_mode_t const& val) bool load_msec(tr_variant const& src, std::chrono::milliseconds* tgt) { - if (auto val = src.get_if(); val != nullptr) + if (auto val = src.value_if()) { *tgt = std::chrono::milliseconds(*val); return true; @@ -215,7 +215,7 @@ tr_variant save_msec(std::chrono::milliseconds const& src) bool load_port(tr_variant const& src, tr_port* tgt) { - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { *tgt = tr_port::from_host(*val); return true; @@ -243,7 +243,7 @@ bool load_preallocation_mode(tr_variant const& src, tr_open_files::Preallocation { static constexpr auto& Keys = PreallocationKeys; - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { auto const needle = tr_strlower(tr_strv_strip(*val)); @@ -257,7 +257,7 @@ bool load_preallocation_mode(tr_variant const& src, tr_open_files::Preallocation } } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { for (auto const& [name, value] : Keys) { @@ -288,7 +288,7 @@ bool load_preferred_transport(tr_variant const& src, tr_preferred_transport* tgt { static constexpr auto& Keys = PreferredTransportKeys; - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { auto const needle = tr_strlower(tr_strv_strip(*val)); @@ -302,7 +302,7 @@ bool load_preferred_transport(tr_variant const& src, tr_preferred_transport* tgt } } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { for (auto const& [name, value] : Keys) { @@ -334,7 +334,7 @@ tr_variant save_preferred_transport(tr_preferred_transport const& val) bool load_size_t(tr_variant const& src, size_t* tgt) { - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { *tgt = static_cast(*val); return true; @@ -352,7 +352,7 @@ tr_variant save_size_t(size_t const& val) bool load_string(tr_variant const& src, std::string* tgt) { - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { *tgt = std::string{ *val }; return true; @@ -370,7 +370,7 @@ tr_variant save_string(std::string const& val) bool load_tos_t(tr_variant const& src, tr_tos_t* tgt) { - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { if (auto const tos = tr_tos_t::from_string(*val); tos) { @@ -381,7 +381,7 @@ bool load_tos_t(tr_variant const& src, tr_tos_t* tgt) return false; } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { *tgt = tr_tos_t{ static_cast(*val) }; return true; @@ -406,7 +406,7 @@ bool load_verify_added_mode(tr_variant const& src, tr_verify_added_mode* tgt) { static constexpr auto& Keys = VerifyModeKeys; - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { auto const needle = tr_strlower(tr_strv_strip(*val)); @@ -420,7 +420,7 @@ bool load_verify_added_mode(tr_variant const& src, tr_verify_added_mode* tgt) } } - if (auto const* val = src.get_if(); val != nullptr) + if (auto const val = src.value_if()) { for (auto const& [name, value] : Keys) { diff --git a/libtransmission/variant.cc b/libtransmission/variant.cc index df8c42cd5..ee207d9b4 100644 --- a/libtransmission/variant.cc +++ b/libtransmission/variant.cc @@ -50,6 +50,21 @@ namespace return tr_variant::NoneIndex; } +template +[[nodiscard]] bool value_if(tr_variant const* const var, T* const setme) +{ + if (var != nullptr) + { + if (auto val = var->value_if()) + { + *setme = *val; + return true; + } + } + + return false; +} + template [[nodiscard]] tr_variant* dict_set(tr_variant* const var, tr_quark const key, T&& val) { @@ -82,6 +97,79 @@ template // --- +// Specialisations for int64_t and bool could have been inline and constexpr, +// but aren't because https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282 + +template<> +[[nodiscard]] std::optional tr_variant::value_if() noexcept +{ + switch (index()) + { + case IntIndex: + return *get_if(); + + case BoolIndex: + return *get_if() ? 1 : 0; + + default: + return {}; + } +} + +template<> +[[nodiscard]] std::optional tr_variant::value_if() noexcept +{ + switch (index()) + { + case BoolIndex: + return *get_if(); + + case IntIndex: + if (auto const val = *get_if(); val == 0 || val == 1) + { + return val != 0; + } + break; + + case StringIndex: + if (auto const val = *get_if(); val == "true") + { + return true; + } + else if (val == "false") + { + return false; + } + break; + + default: + break; + } + + return {}; +} + +template<> +[[nodiscard]] std::optional tr_variant::value_if() noexcept +{ + switch (index()) + { + case DoubleIndex: + return *get_if(); + + case IntIndex: + return static_cast(*get_if()); + + case StringIndex: + return tr_num_parse(*get_if()); + + default: + return {}; + } +} + +// --- + tr_variant::StringHolder::StringHolder(std::string&& str) noexcept : str_{ std::move(str) } { @@ -206,38 +294,12 @@ bool tr_variantListRemove(tr_variant* const var, size_t pos) bool tr_variantGetInt(tr_variant const* const var, int64_t* setme) { - switch (variant_index(var)) - { - case tr_variant::IntIndex: - if (setme != nullptr) - { - *setme = *var->get_if(); - } - return true; - - case tr_variant::BoolIndex: - if (setme != nullptr) - { - *setme = *var->get_if() ? 1 : 0; - } - return true; - - default: - return false; - } + return value_if(var, setme); } bool tr_variantGetStrView(tr_variant const* const var, std::string_view* setme) { - switch (variant_index(var)) - { - case tr_variant::StringIndex: - *setme = *var->get_if(); - return true; - - default: - return false; - } + return value_if(var, setme); } bool tr_variantGetRaw(tr_variant const* v, std::byte const** setme_raw, size_t* setme_len) @@ -266,63 +328,12 @@ bool tr_variantGetRaw(tr_variant const* v, uint8_t const** setme_raw, size_t* se bool tr_variantGetBool(tr_variant const* const var, bool* setme) { - switch (variant_index(var)) - { - case tr_variant::BoolIndex: - *setme = *var->get_if(); - return true; - - case tr_variant::IntIndex: - if (auto const val = *var->get_if(); val == 0 || val == 1) - { - *setme = val != 0; - return true; - } - break; - - case tr_variant::StringIndex: - if (auto const val = *var->get_if(); val == "true"sv) - { - *setme = true; - return true; - } - else if (val == "false"sv) - { - *setme = false; - return true; - } - break; - - default: - break; - } - - return false; + return value_if(var, setme); } bool tr_variantGetReal(tr_variant const* const var, double* setme) { - switch (variant_index(var)) - { - case tr_variant::DoubleIndex: - *setme = *var->get_if(); - return true; - - case tr_variant::IntIndex: - *setme = static_cast(*var->get_if()); - return true; - - case tr_variant::StringIndex: - if (auto const val = tr_num_parse(*var->get_if()); val) - { - *setme = *val; - return true; - } - [[fallthrough]]; - - default: - return false; - } + return value_if(var, setme); } bool tr_variantDictFindInt(tr_variant* const var, tr_quark key, int64_t* setme) diff --git a/libtransmission/variant.h b/libtransmission/variant.h index ad82d6c74..dcb251052 100644 --- a/libtransmission/variant.h +++ b/libtransmission/variant.h @@ -158,11 +158,11 @@ public: } template - [[nodiscard]] TR_CONSTEXPR20 std::optional value_if(tr_quark const key) const noexcept + [[nodiscard]] std::optional value_if(tr_quark const key) const noexcept { - if (auto const* const value = find_if(key); value != nullptr) + if (auto it = find(key); it != end()) { - return std::optional{ *value }; + return it->second.value_if(); } return {}; @@ -310,6 +310,23 @@ public: return const_cast(this)->get_if(); } + template + [[nodiscard]] constexpr std::optional value_if() noexcept + { + if (auto const* const val = get_if()) + { + return *val; + } + + return {}; + } + + template + [[nodiscard]] std::optional value_if() const noexcept + { + return const_cast(this)->value_if(); + } + template [[nodiscard]] constexpr bool holds_alternative() const noexcept { @@ -371,6 +388,13 @@ private: std::variant val_; }; +template<> +[[nodiscard]] std::optional tr_variant::value_if() noexcept; +template<> +[[nodiscard]] std::optional tr_variant::value_if() noexcept; +template<> +[[nodiscard]] std::optional tr_variant::value_if() noexcept; + // --- Strings bool tr_variantGetStrView(tr_variant const* variant, std::string_view* setme);