refactor: de-intern display mode strings (#8052)

* refactor: replace should_convert_child_strings() with a State.path stack

* refactor: de-intern the TR_KEY_sort_ keys

* refactor: de-intern the TR_KEY_show_ keys
This commit is contained in:
Charles Kerr
2026-01-03 07:41:06 -06:00
committed by GitHub
parent 046de3f6f0
commit c8d4ce9e9a
4 changed files with 90 additions and 160 deletions

View File

@@ -23,15 +23,15 @@ using Lookup = std::array<std::pair<std::string_view, T>, N>;
// ---
auto constexpr ShowKeys = std::array<std::pair<tr_quark, ShowMode>, ShowModeCount>{ {
{ TR_KEY_show_active, ShowMode::ShowActive },
{ TR_KEY_show_all, ShowMode::ShowAll },
{ TR_KEY_show_downloading, ShowMode::ShowDownloading },
{ TR_KEY_show_error, ShowMode::ShowError },
{ TR_KEY_show_finished, ShowMode::ShowFinished },
{ TR_KEY_show_paused, ShowMode::ShowPaused },
{ TR_KEY_show_seeding, ShowMode::ShowSeeding },
{ TR_KEY_show_verifying, ShowMode::ShowVerifying },
auto constexpr ShowKeys = std::array<std::pair<std::string_view, ShowMode>, ShowModeCount>{ {
{ "show_active", ShowMode::ShowActive },
{ "show_all", ShowMode::ShowAll },
{ "show_downloading", ShowMode::ShowDownloading },
{ "show_error", ShowMode::ShowError },
{ "show_finished", ShowMode::ShowFinished },
{ "show_paused", ShowMode::ShowPaused },
{ "show_seeding", ShowMode::ShowSeeding },
{ "show_verifying", ShowMode::ShowVerifying },
} };
bool to_show_mode(tr_variant const& src, ShowMode* tgt)
@@ -40,15 +40,12 @@ bool to_show_mode(tr_variant const& src, ShowMode* tgt)
if (auto const str = src.value_if<std::string_view>())
{
if (auto const needle = tr_quark_lookup(*str))
for (auto const& [key, val] : Keys)
{
for (auto const& [key, val] : Keys)
if (str == key)
{
if (needle == key)
{
*tgt = val;
return true;
}
*tgt = val;
return true;
}
}
}
@@ -68,22 +65,22 @@ tr_variant from_show_mode(ShowMode const& src)
}
}
return tr_variant::unmanaged_string(TR_KEY_show_all);
return from_show_mode(DefaultShowMode);
}
// ---
auto constexpr SortKeys = std::array<std::pair<tr_quark, SortMode>, SortModeCount>{ {
{ TR_KEY_sort_by_activity, SortMode::SortByActivity },
{ TR_KEY_sort_by_age, SortMode::SortByAge },
{ TR_KEY_sort_by_eta, SortMode::SortByEta },
{ TR_KEY_sort_by_id, SortMode::SortById },
{ TR_KEY_sort_by_name, SortMode::SortByName },
{ TR_KEY_sort_by_progress, SortMode::SortByProgress },
{ TR_KEY_sort_by_queue, SortMode::SortByQueue },
{ TR_KEY_sort_by_ratio, SortMode::SortByRatio },
{ TR_KEY_sort_by_size, SortMode::SortBySize },
{ TR_KEY_sort_by_state, SortMode::SortByState },
auto constexpr SortKeys = std::array<std::pair<std::string_view, SortMode>, SortModeCount>{ {
{ "sort_by_activity", SortMode::SortByActivity },
{ "sort_by_age", SortMode::SortByAge },
{ "sort_by_eta", SortMode::SortByEta },
{ "sort_by_id", SortMode::SortById },
{ "sort_by_name", SortMode::SortByName },
{ "sort_by_progress", SortMode::SortByProgress },
{ "sort_by_queue", SortMode::SortByQueue },
{ "sort_by_ratio", SortMode::SortByRatio },
{ "sort_by_size", SortMode::SortBySize },
{ "sort_by_state", SortMode::SortByState },
} };
bool to_sort_mode(tr_variant const& src, SortMode* tgt)
@@ -92,15 +89,12 @@ bool to_sort_mode(tr_variant const& src, SortMode* tgt)
if (auto const str = src.value_if<std::string_view>())
{
if (auto const needle = tr_quark_lookup(*str))
for (auto const& [key, val] : Keys)
{
for (auto const& [key, val] : Keys)
if (str == key)
{
if (needle == key)
{
*tgt = val;
return true;
}
*tgt = val;
return true;
}
}
}
@@ -120,7 +114,7 @@ tr_variant from_sort_mode(SortMode const& src)
}
}
return tr_variant::unmanaged_string(TR_KEY_sort_by_name);
return from_sort_mode(DefaultSortMode);
}
} // unnamed namespace

View File

@@ -6,6 +6,8 @@
#include <algorithm>
#include <array>
#include <cstddef>
#include <deque>
#include <initializer_list>
#include <string_view>
#include <vector>
@@ -246,7 +248,7 @@ auto constexpr RpcKeys = std::array<ApiKey, 212U>{ {
{ TR_KEY_torrent_verify, TR_KEY_torrent_verify_kebab_APICOMPAT },
} };
auto constexpr SessionKeys = std::array<ApiKey, 157U>{ {
auto constexpr SessionKeys = std::array<ApiKey, 139U>{ {
{ TR_KEY_activity_date, TR_KEY_activity_date_kebab_APICOMPAT },
{ TR_KEY_added_date, TR_KEY_added_date_kebab_APICOMPAT },
{ TR_KEY_alt_speed_down, TR_KEY_alt_speed_down_kebab_APICOMPAT },
@@ -350,33 +352,15 @@ auto constexpr SessionKeys = std::array<ApiKey, 157U>{ {
{ TR_KEY_seed_queue_size, TR_KEY_seed_queue_size_kebab_APICOMPAT },
{ TR_KEY_seeding_time_seconds, TR_KEY_seeding_time_seconds_kebab_APICOMPAT },
{ TR_KEY_session_count, TR_KEY_session_count_kebab_APICOMPAT },
{ TR_KEY_show_active, TR_KEY_show_active_kebab_APICOMPAT },
{ TR_KEY_show_all, TR_KEY_show_all_kebab_APICOMPAT },
{ TR_KEY_show_backup_trackers, TR_KEY_show_backup_trackers_kebab_APICOMPAT },
{ TR_KEY_show_downloading, TR_KEY_show_downloading_kebab_APICOMPAT },
{ TR_KEY_show_error, TR_KEY_show_error_kebab_APICOMPAT },
{ TR_KEY_show_extra_peer_details, TR_KEY_show_extra_peer_details_kebab_APICOMPAT },
{ TR_KEY_show_filterbar, TR_KEY_show_filterbar_kebab_APICOMPAT },
{ TR_KEY_show_finished, TR_KEY_show_finished_kebab_APICOMPAT },
{ TR_KEY_show_notification_area_icon, TR_KEY_show_notification_area_icon_kebab_APICOMPAT },
{ TR_KEY_show_options_window, TR_KEY_show_options_window_kebab_APICOMPAT },
{ TR_KEY_show_paused, TR_KEY_show_paused_kebab_APICOMPAT },
{ TR_KEY_show_seeding, TR_KEY_show_seeding_kebab_APICOMPAT },
{ TR_KEY_show_statusbar, TR_KEY_show_statusbar_kebab_APICOMPAT },
{ TR_KEY_show_toolbar, TR_KEY_show_toolbar_kebab_APICOMPAT },
{ TR_KEY_show_tracker_scrapes, TR_KEY_show_tracker_scrapes_kebab_APICOMPAT },
{ TR_KEY_show_verifying, TR_KEY_show_verifying_kebab_APICOMPAT },
{ TR_KEY_sleep_per_seconds_during_verify, TR_KEY_sleep_per_seconds_during_verify_kebab_APICOMPAT },
{ TR_KEY_sort_by_activity, TR_KEY_sort_by_activity_kebab_APICOMPAT },
{ TR_KEY_sort_by_age, TR_KEY_sort_by_age_kebab_APICOMPAT },
{ TR_KEY_sort_by_eta, TR_KEY_sort_by_eta_kebab_APICOMPAT },
{ TR_KEY_sort_by_id, TR_KEY_sort_by_id_kebab_APICOMPAT },
{ TR_KEY_sort_by_name, TR_KEY_sort_by_name_kebab_APICOMPAT },
{ TR_KEY_sort_by_progress, TR_KEY_sort_by_progress_kebab_APICOMPAT },
{ TR_KEY_sort_by_queue, TR_KEY_sort_by_queue_kebab_APICOMPAT },
{ TR_KEY_sort_by_ratio, TR_KEY_sort_by_ratio_kebab_APICOMPAT },
{ TR_KEY_sort_by_size, TR_KEY_sort_by_size_kebab_APICOMPAT },
{ TR_KEY_sort_by_state, TR_KEY_sort_by_state_kebab_APICOMPAT },
{ TR_KEY_sort_mode, TR_KEY_sort_mode_kebab_APICOMPAT },
{ TR_KEY_sort_reversed, TR_KEY_sort_reversed_kebab_APICOMPAT },
{ TR_KEY_speed_Bps, TR_KEY_speed_Bps_kebab_APICOMPAT },
@@ -467,15 +451,21 @@ auto constexpr PreferClearLegacy = std::string_view{ "tolerated" };
struct State
{
api_compat::Style style = {};
bool convert_strings = false;
bool is_free_space_response = false;
bool is_request = false;
bool is_response = false;
bool is_rpc = false;
bool is_settings = false;
bool is_success = false;
bool is_torrent = false;
bool was_jsonrpc = false;
bool was_legacy = false;
std::deque<tr_quark> path;
[[nodiscard]] bool current_key_is_any_of(std::initializer_list<tr_quark> const pool) const noexcept
{
return !std::empty(path) && std::count(std::cbegin(pool), std::cend(pool), path.back()) != 0U;
}
};
[[nodiscard]] State makeState(tr_variant::Map const& top)
@@ -489,6 +479,7 @@ struct State
auto const was_legacy_response = state.was_legacy && top.contains(TR_KEY_result);
state.is_response = was_jsonrpc_response || was_legacy_response;
state.is_rpc = state.is_request || state.is_response;
state.is_settings = !state.is_rpc;
state.is_success = state.is_response &&
(was_jsonrpc_response ? top.contains(TR_KEY_result) :
@@ -596,47 +587,65 @@ struct State
[[nodiscard]] std::optional<std::string_view> convert_string(State const& state, std::string_view const src)
{
if (!state.convert_strings)
if (state.is_settings && state.current_key_is_any_of({ TR_KEY_sort_mode, TR_KEY_sort_mode_kebab_APICOMPAT }))
{
return {};
static auto constexpr Strings = std::array<std::pair<std::string_view /*Tr5*/, std::string_view /*Tr4*/>, 10U>{ {
{ "sort_by_activity", "sort-by-activity" },
{ "sort_by_age", "sort-by-age" },
{ "sort_by_eta", "sort-by-eta" },
{ "sort_by_id", "sort-by-id" },
{ "sort_by_name", "sort-by-name" },
{ "sort_by_progress", "sort-by-progress" },
{ "sort_by_queue", "sort-by-queue" },
{ "sort_by_ratio", "sort-by-ratio" },
{ "sort_by_size", "sort-by-size" },
{ "sort_by_state", "sort-by-state" },
} };
for (auto const& [current, legacy] : Strings)
{
if (src == current || src == legacy)
{
return state.style == Style::Tr5 ? current : legacy;
}
}
}
auto const old_key = tr_quark_lookup(src);
if (!old_key)
if (state.is_settings && state.current_key_is_any_of({ TR_KEY_filter_mode, TR_KEY_filter_mode_kebab_APICOMPAT }))
{
return {};
static auto constexpr Strings = std::array<std::pair<std::string_view, std::string_view>, 8U>{ {
{ "show_active", "show-active" },
{ "show_all", "show-all" },
{ "show_downloading", "show-downloading" },
{ "show_error", "show-error" },
{ "show_finished", "show-finished" },
{ "show_paused", "show-paused" },
{ "show_seeding", "show-seeding" },
{ "show_verifying", "show-verifying" },
} };
for (auto const& [current, legacy] : Strings)
{
if (src == current || src == legacy)
{
return state.style == Style::Tr5 ? current : legacy;
}
}
}
auto const new_key = convert_key(state, *old_key);
if (*old_key == new_key)
{
return {};
}
auto ret = tr_quark_get_string_view(new_key);
return ret;
}
[[nodiscard]] bool should_convert_child_strings(State const& state, tr_quark const old_key, tr_quark const new_key)
{
// TODO(ckerr): replace `new_key == TR_KEY_TORRENTS` here to turn on convert
// if it's an array inside an array val whose key was `torrents`.
// This is for the edge case of table mode: `torrents : [ [ 'key1', 'key2' ], [ ... ] ]`
if (state.is_rpc &&
(new_key == TR_KEY_method || new_key == TR_KEY_fields || new_key == TR_KEY_ids || new_key == TR_KEY_torrents))
if (state.is_rpc && state.current_key_is_any_of({ TR_KEY_method, TR_KEY_fields, TR_KEY_ids, TR_KEY_torrents }))
{
return true;
if (auto const old_key = tr_quark_lookup(src))
{
if (auto const new_key = convert_key(state, *old_key); *old_key != new_key)
{
return tr_quark_get_string_view(new_key);
}
}
}
if (!state.is_rpc &&
(TR_KEY_filter_mode == new_key || TR_KEY_filter_mode == old_key || TR_KEY_filter_mode_kebab_APICOMPAT == new_key ||
TR_KEY_filter_mode_kebab_APICOMPAT == old_key || TR_KEY_sort_mode == new_key || TR_KEY_sort_mode == old_key ||
TR_KEY_sort_mode_kebab_APICOMPAT == new_key || TR_KEY_sort_mode_kebab_APICOMPAT == old_key))
{
return true;
}
return false;
return {};
}
void convert_keys(tr_variant& var, State& state)
@@ -674,10 +683,9 @@ void convert_keys(tr_variant& var, State& state)
val.replace_key(old_key, new_key);
}
auto const pop = state.convert_strings;
state.convert_strings |= should_convert_child_strings(state, old_key, new_key);
state.path.push_back(new_key);
convert_keys(child, state);
state.convert_strings = pop;
state.path.pop_back();
}
}
});

View File

@@ -568,38 +568,22 @@ auto constexpr MyStatic = std::array<std::string_view, TR_N_KEYS>{
"session_id"sv, // rpc
"session_set"sv, // rpc
"session_stats"sv, // rpc
"show-active",
"show-all",
"show-backup-trackers"sv, // gtk app, qt app
"show-downloading",
"show-error",
"show-extra-peer-details"sv, // gtk app
"show-filterbar"sv, // gtk app, qt app
"show-finished",
"show-notification-area-icon"sv, // gtk app, qt app
"show-options-window"sv, // gtk app, qt app
"show-paused",
"show-seeding",
"show-statusbar"sv, // gtk app, qt app
"show-toolbar"sv, // gtk app, qt app
"show-tracker-scrapes"sv, // gtk app, qt app
"show-verifying",
"show_active",
"show_all",
"show_backup_trackers"sv, // gtk app, qt app
"show_downloading",
"show_error",
"show_extra_peer_details"sv, // gtk app
"show_filterbar"sv, // gtk app, qt app
"show_finished",
"show_notification_area_icon"sv, // gtk app, qt app
"show_options_window"sv, // gtk app, qt app
"show_paused",
"show_seeding",
"show_statusbar"sv, // gtk app, qt app
"show_toolbar"sv, // gtk app, qt app
"show_tracker_scrapes"sv, // gtk app, qt app
"show_verifying",
"sitename"sv, // rpc
"size-bytes"sv, // rpc
"size-units"sv, // rpc
@@ -610,28 +594,8 @@ auto constexpr MyStatic = std::array<std::string_view, TR_N_KEYS>{
"sleep-per-seconds-during-verify"sv, // tr_session::Settings
"sleep_per_seconds_during_verify"sv, // tr_session::Settings
"socket_address"sv, // .resume
"sort-by-activity", // gtk app, qt app
"sort-by-age", // gtk app, qt app
"sort-by-eta", // gtk app, qt app
"sort-by-id", // gtk app, qt app
"sort-by-name", // gtk app, qt app
"sort-by-progress", // gtk app, qt app
"sort-by-queue", // gtk app, qt app
"sort-by-ratio", // gtk app, qt app
"sort-by-size", // gtk app, qt app
"sort-by-state", // gtk app, qt app
"sort-mode"sv, // gtk app, qt app
"sort-reversed"sv, // gtk app, qt app
"sort_by_activity", // gtk app, qt app
"sort_by_age", // gtk app, qt app
"sort_by_eta", // gtk app, qt app
"sort_by_id", // gtk app, qt app
"sort_by_name", // gtk app, qt app
"sort_by_progress", // gtk app, qt app
"sort_by_queue", // gtk app, qt app
"sort_by_ratio", // gtk app, qt app
"sort_by_size", // gtk app, qt app
"sort_by_state", // gtk app, qt app
"sort_mode"sv, // gtk app, qt app
"sort_reversed"sv, // gtk app, qt app
"source"sv, // .torrent

View File

@@ -581,38 +581,22 @@ enum // NOLINT(performance-enum-size)
TR_KEY_session_id,
TR_KEY_session_set,
TR_KEY_session_stats,
TR_KEY_show_active_kebab_APICOMPAT,
TR_KEY_show_all_kebab_APICOMPAT,
TR_KEY_show_backup_trackers_kebab_APICOMPAT,
TR_KEY_show_downloading_kebab_APICOMPAT,
TR_KEY_show_error_kebab_APICOMPAT,
TR_KEY_show_extra_peer_details_kebab_APICOMPAT,
TR_KEY_show_filterbar_kebab_APICOMPAT,
TR_KEY_show_finished_kebab_APICOMPAT,
TR_KEY_show_notification_area_icon_kebab_APICOMPAT,
TR_KEY_show_options_window_kebab_APICOMPAT,
TR_KEY_show_paused_kebab_APICOMPAT,
TR_KEY_show_seeding_kebab_APICOMPAT,
TR_KEY_show_statusbar_kebab_APICOMPAT,
TR_KEY_show_toolbar_kebab_APICOMPAT,
TR_KEY_show_tracker_scrapes_kebab_APICOMPAT,
TR_KEY_show_verifying_kebab_APICOMPAT,
TR_KEY_show_active,
TR_KEY_show_all,
TR_KEY_show_backup_trackers,
TR_KEY_show_downloading,
TR_KEY_show_error,
TR_KEY_show_extra_peer_details,
TR_KEY_show_filterbar,
TR_KEY_show_finished,
TR_KEY_show_notification_area_icon,
TR_KEY_show_options_window,
TR_KEY_show_paused,
TR_KEY_show_seeding,
TR_KEY_show_statusbar,
TR_KEY_show_toolbar,
TR_KEY_show_tracker_scrapes,
TR_KEY_show_verifying,
TR_KEY_sitename,
TR_KEY_size_bytes_kebab_APICOMPAT,
TR_KEY_size_units_kebab_APICOMPAT,
@@ -623,28 +607,8 @@ enum // NOLINT(performance-enum-size)
TR_KEY_sleep_per_seconds_during_verify_kebab_APICOMPAT,
TR_KEY_sleep_per_seconds_during_verify,
TR_KEY_socket_address,
TR_KEY_sort_by_activity_kebab_APICOMPAT,
TR_KEY_sort_by_age_kebab_APICOMPAT,
TR_KEY_sort_by_eta_kebab_APICOMPAT,
TR_KEY_sort_by_id_kebab_APICOMPAT,
TR_KEY_sort_by_name_kebab_APICOMPAT,
TR_KEY_sort_by_progress_kebab_APICOMPAT,
TR_KEY_sort_by_queue_kebab_APICOMPAT,
TR_KEY_sort_by_ratio_kebab_APICOMPAT,
TR_KEY_sort_by_size_kebab_APICOMPAT,
TR_KEY_sort_by_state_kebab_APICOMPAT,
TR_KEY_sort_mode_kebab_APICOMPAT,
TR_KEY_sort_reversed_kebab_APICOMPAT,
TR_KEY_sort_by_activity,
TR_KEY_sort_by_age,
TR_KEY_sort_by_eta,
TR_KEY_sort_by_id,
TR_KEY_sort_by_name,
TR_KEY_sort_by_progress,
TR_KEY_sort_by_queue,
TR_KEY_sort_by_ratio,
TR_KEY_sort_by_size,
TR_KEY_sort_by_state,
TR_KEY_sort_mode,
TR_KEY_sort_reversed,
TR_KEY_source,