diff --git a/libtransmission/api-compat.cc b/libtransmission/api-compat.cc index 06f0d6bc0..acc43d3cf 100644 --- a/libtransmission/api-compat.cc +++ b/libtransmission/api-compat.cc @@ -276,9 +276,9 @@ auto constexpr SessionKeys = std::array{ { { TR_KEY_download_dir, TR_KEY_download_dir_kebab }, // TODO(ckerr) legacy duplicate { TR_KEY_download_queue_enabled, TR_KEY_download_queue_enabled_kebab }, { TR_KEY_download_queue_size, TR_KEY_download_queue_size_kebab }, - { TR_KEY_downloaded_bytes, TR_KEY_downloaded_bytes_kebab }, // TODO(ckerr) legacy duplicate + { TR_KEY_downloaded_bytes, TR_KEY_downloaded_bytes_kebab_APICOMPAT }, { TR_KEY_downloading_time_seconds, TR_KEY_downloading_time_seconds_kebab }, - { TR_KEY_files_added, TR_KEY_files_added_kebab }, // TODO(ckerr) legacy duplicate + { TR_KEY_files_added, TR_KEY_files_added_kebab_APICOMPAT }, { TR_KEY_filter_mode, TR_KEY_filter_mode_kebab }, { TR_KEY_filter_text, TR_KEY_filter_text_kebab }, { TR_KEY_filter_trackers, TR_KEY_filter_trackers_kebab }, @@ -344,11 +344,11 @@ auto constexpr SessionKeys = std::array{ { { TR_KEY_script_torrent_done_filename, TR_KEY_script_torrent_done_filename_kebab }, { TR_KEY_script_torrent_done_seeding_enabled, TR_KEY_script_torrent_done_seeding_enabled_kebab }, { TR_KEY_script_torrent_done_seeding_filename, TR_KEY_script_torrent_done_seeding_filename_kebab }, - { TR_KEY_seconds_active, TR_KEY_seconds_active_kebab }, // TODO(ckerr) legacy duplicate + { TR_KEY_seconds_active, TR_KEY_seconds_active_kebab_APICOMPAT }, { TR_KEY_seed_queue_enabled, TR_KEY_seed_queue_enabled_kebab }, { TR_KEY_seed_queue_size, TR_KEY_seed_queue_size_kebab }, { TR_KEY_seeding_time_seconds, TR_KEY_seeding_time_seconds_kebab }, - { TR_KEY_session_count, TR_KEY_session_count_kebab }, // TODO(ckerr) legacy duplicate + { TR_KEY_session_count, TR_KEY_session_count_kebab_APICOMPAT }, { TR_KEY_show_backup_trackers, TR_KEY_show_backup_trackers_kebab }, { TR_KEY_show_extra_peer_details, TR_KEY_show_extra_peer_details_kebab }, { TR_KEY_show_filterbar, TR_KEY_show_filterbar_kebab }, @@ -378,7 +378,7 @@ auto constexpr SessionKeys = std::array{ { { TR_KEY_trash_can_enabled, TR_KEY_trash_can_enabled_kebab }, { TR_KEY_trash_original_torrent_files, TR_KEY_trash_original_torrent_files_kebab }, { TR_KEY_upload_slots_per_torrent, TR_KEY_upload_slots_per_torrent_kebab }, - { TR_KEY_uploaded_bytes, TR_KEY_uploaded_bytes_kebab }, // TODO(ckerr) legacy duplicate + { TR_KEY_uploaded_bytes, TR_KEY_uploaded_bytes_kebab_APICOMPAT }, { TR_KEY_use_global_speed_limit, TR_KEY_use_global_speed_limit_kebab }, { TR_KEY_use_speed_limit, TR_KEY_use_speed_limit_kebab }, { TR_KEY_utp_enabled, TR_KEY_utp_enabled_kebab }, diff --git a/libtransmission/quark.h b/libtransmission/quark.h index 8ff90b394..0f12a50b0 100644 --- a/libtransmission/quark.h +++ b/libtransmission/quark.h @@ -9,11 +9,26 @@ #include #include -/* Quarks — a 2-way association between a string and a unique integer identifier */ +/** + * Quarks — a 2-way association between a compile-time interned string + * and a unique integer identifier. Used to make well-known strings + * (e.g. strings in settings files, the JSON-RPC API, and BitTorrent protocol) + * cheap to store, cheap to compare, and usable in switch-case statements. + */ using tr_quark = size_t; -/* +/** * Predefined Quarks. + * + * IMPORTANT: + * + * * Use snake case for new entries. + * + * * Entries whose names contain `_camel`, `_kebab`, or `_APICOMPAT` are + * all deprecated. Do not use them in new code except in api_compat. + * - `_camel` means the entry's string is in camelCase. + * - `_kebab` means the entry's string is in kebab-case. + * - `_APICOMPAT` means the entry is only used in api_compat. */ enum // NOLINT(performance-enum-size) { @@ -149,7 +164,7 @@ enum // NOLINT(performance-enum-size) TR_KEY_download_queue_size, TR_KEY_download_speed, TR_KEY_downloaded, - TR_KEY_downloaded_bytes_kebab, + TR_KEY_downloaded_bytes_kebab_APICOMPAT, TR_KEY_downloaded_bytes_camel, TR_KEY_downloaded_ever_camel, TR_KEY_downloaded_bytes, @@ -178,7 +193,7 @@ enum // NOLINT(performance-enum-size) TR_KEY_file_stats, TR_KEY_filename, TR_KEY_files, - TR_KEY_files_added_kebab, + TR_KEY_files_added_kebab_APICOMPAT, TR_KEY_files_unwanted_kebab, TR_KEY_files_wanted_kebab, TR_KEY_files_added_camel, @@ -526,7 +541,7 @@ enum // NOLINT(performance-enum-size) TR_KEY_script_torrent_done_filename, TR_KEY_script_torrent_done_seeding_enabled, TR_KEY_script_torrent_done_seeding_filename, - TR_KEY_seconds_active_kebab, + TR_KEY_seconds_active_kebab_APICOMPAT, TR_KEY_seconds_active_camel, TR_KEY_seconds_downloading_camel, TR_KEY_seconds_seeding_camel, @@ -554,7 +569,7 @@ enum // NOLINT(performance-enum-size) TR_KEY_sequential_download, TR_KEY_sequential_download_from_piece, TR_KEY_session_close_kebab, - TR_KEY_session_count_kebab, + TR_KEY_session_count_kebab_APICOMPAT, TR_KEY_session_get_kebab, TR_KEY_session_id_kebab, TR_KEY_session_set_kebab, @@ -701,7 +716,7 @@ enum // NOLINT(performance-enum-size) TR_KEY_upload_slots_per_torrent, TR_KEY_upload_speed, TR_KEY_uploaded, - TR_KEY_uploaded_bytes_kebab, + TR_KEY_uploaded_bytes_kebab_APICOMPAT, TR_KEY_uploaded_bytes_camel, TR_KEY_uploaded_ever_camel, TR_KEY_uploaded_bytes, diff --git a/libtransmission/stats.cc b/libtransmission/stats.cc index 04880c3bf..fe673500c 100644 --- a/libtransmission/stats.cc +++ b/libtransmission/stats.cc @@ -9,6 +9,7 @@ #include "libtransmission/transmission.h" +#include "libtransmission/api-compat.h" #include "libtransmission/file.h" #include "libtransmission/quark.h" #include "libtransmission/stats.h" @@ -17,24 +18,29 @@ #include "libtransmission/variant.h" using namespace std::literals; +namespace api_compat = libtransmission::api_compat; namespace { -std::optional load_stats(std::string_view config_dir) +[[nodiscard]] auto load_stats(std::string_view config_dir) { - if (auto filename = tr_pathbuf{ config_dir, "/stats.json"sv }; tr_sys_path_exists(filename)) + auto var = std::optional{}; + + if (auto file = tr_pathbuf{ config_dir, "/stats.json"sv }; tr_sys_path_exists(file)) { - return tr_variant_serde::json().parse_file(filename); + var = tr_variant_serde::json().parse_file(file); + } + else if (auto oldfile = tr_pathbuf{ config_dir, "/stats.benc"sv }; tr_sys_path_exists(oldfile)) + { + var = tr_variant_serde::benc().parse_file(oldfile); } - // maybe the user just upgraded from an old version of Transmission - // that was still using stats.benc - if (auto filename = tr_pathbuf{ config_dir, "/stats.benc"sv }; tr_sys_path_exists(filename)) + if (var) { - return tr_variant_serde::benc().parse_file(filename); + var = api_compat::convert_incoming_data(*var); } - return {}; + return var; } } // namespace @@ -52,21 +58,21 @@ tr_session_stats tr_stats::load_old_stats(std::string_view config_dir) return {}; } - auto const load = [map](std::initializer_list keys, uint64_t& dst) + auto const load = [map](auto const key, uint64_t& tgt) { - if (auto const val = map->value_if(keys); val) + if (auto const val = map->value_if(key)) { - dst = *val; + tgt = *val; } }; auto ret = tr_session_stats{}; - load({ TR_KEY_downloaded_bytes, TR_KEY_downloaded_bytes_kebab }, ret.downloadedBytes); - load({ TR_KEY_files_added, TR_KEY_files_added_kebab }, ret.filesAdded); - load({ TR_KEY_seconds_active, TR_KEY_seconds_active_kebab }, ret.secondsActive); - load({ TR_KEY_session_count, TR_KEY_session_count_kebab }, ret.sessionCount); - load({ TR_KEY_uploaded_bytes, TR_KEY_uploaded_bytes_kebab }, ret.uploadedBytes); + load(TR_KEY_downloaded_bytes, ret.downloadedBytes); + load(TR_KEY_files_added, ret.filesAdded); + load(TR_KEY_seconds_active, ret.secondsActive); + load(TR_KEY_session_count, ret.sessionCount); + load(TR_KEY_uploaded_bytes, ret.uploadedBytes); return ret; } @@ -80,7 +86,10 @@ void tr_stats::save() const map.try_emplace(TR_KEY_seconds_active, saveme.secondsActive); map.try_emplace(TR_KEY_session_count, saveme.sessionCount); map.try_emplace(TR_KEY_uploaded_bytes, saveme.uploadedBytes); - tr_variant_serde::json().to_file(tr_variant{ std::move(map) }, tr_pathbuf{ config_dir_, "/stats.json"sv }); + + auto var = tr_variant{ std::move(map) }; + var = api_compat::convert_outgoing_data(var); + tr_variant_serde::json().to_file(var, tr_pathbuf{ config_dir_, "/stats.json"sv }); } void tr_stats::clear()