Merge branch 'main' into nevack/mojave-infowindow-fix

This commit is contained in:
Charles Kerr 2022-04-03 13:34:31 -05:00 committed by GitHub
commit 7aeb5d8b2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 503 additions and 526 deletions

View File

@ -61,6 +61,7 @@ If you're new to building programs from source code, this is typically easier th
$ cd Transmission/build
$ make clean
$ git submodule foreach --recursive git clean -xfd
$ git pull --rebase --prune
$ git submodule update --recursive
$ # Use -DCMAKE_BUILD_TYPE=RelWithDebInfo to build optimized binary.

View File

@ -10,6 +10,8 @@
#include <string>
#include <string_view>
#include <fmt/format.h>
#include <libtransmission/transmission.h>
#include <libtransmission/error.h>
@ -96,30 +98,29 @@ static int parseCommandLine(tr_variant*, int argc, char const** argv);
static void sigHandler(int signal);
static char* tr_strlratio(char* buf, double ratio, size_t buflen)
static std::string tr_strlratio(double ratio)
{
if ((int)ratio == TR_RATIO_NA)
if (static_cast<int>(ratio) == TR_RATIO_NA)
{
tr_strlcpy(buf, _("None"), buflen);
}
else if ((int)ratio == TR_RATIO_INF)
{
tr_strlcpy(buf, "Inf", buflen);
}
else if (ratio < 10.0)
{
tr_snprintf(buf, buflen, "%.2f", ratio);
}
else if (ratio < 100.0)
{
tr_snprintf(buf, buflen, "%.1f", ratio);
}
else
{
tr_snprintf(buf, buflen, "%.0f", ratio);
return _("None");
}
return buf;
if (static_cast<int>(ratio) == TR_RATIO_INF)
{
return _("Inf");
}
if (ratio < 10.0)
{
return fmt::format(FMT_STRING("{:.2f}"), ratio);
}
if (ratio < 100.0)
{
return fmt::format(FMT_STRING("{:.1f}"), ratio);
}
return fmt::format(FMT_STRING("{:.0f}"), ratio);
}
static bool waitingOnWeb;
@ -131,56 +132,45 @@ static void onTorrentFileDownloaded(tr_web::FetchResponse const& response)
waitingOnWeb = false;
}
static void getStatusStr(tr_stat const* st, char* buf, size_t buflen)
static std::string getStatusStr(tr_stat const* st)
{
if (st->activity == TR_STATUS_CHECK_WAIT)
{
tr_snprintf(buf, buflen, "Waiting to verify local files");
return "Waiting to verify local files";
}
else if (st->activity == TR_STATUS_CHECK)
if (st->activity == TR_STATUS_CHECK)
{
tr_snprintf(
buf,
buflen,
"Verifying local files (%.2f%%, %.2f%% valid)",
return fmt::format(
FMT_STRING("Verifying local files ({:.2f}%, {:.2f}% valid)"),
tr_truncd(100 * st->recheckProgress, 2),
tr_truncd(100 * st->percentDone, 2));
}
else if (st->activity == TR_STATUS_DOWNLOAD)
{
char ratioStr[80];
tr_strlratio(ratioStr, st->ratio, sizeof(ratioStr));
tr_snprintf(
buf,
buflen,
"Progress: %.1f%%, dl from %d of %d peers (%s), ul to %d (%s) [%s]",
if (st->activity == TR_STATUS_DOWNLOAD)
{
return fmt::format(
FMT_STRING("Progress: {:.1f}%, dl from {:d} of {:d} peers ({:s}), ul to {:d} ({:s}) [{:s}]"),
tr_truncd(100 * st->percentDone, 1),
st->peersSendingToUs,
st->peersConnected,
tr_formatter_speed_KBps(st->pieceDownloadSpeed_KBps).c_str(),
tr_formatter_speed_KBps(st->pieceDownloadSpeed_KBps),
st->peersGettingFromUs,
tr_formatter_speed_KBps(st->pieceUploadSpeed_KBps).c_str(),
ratioStr);
tr_formatter_speed_KBps(st->pieceUploadSpeed_KBps),
tr_strlratio(st->ratio));
}
else if (st->activity == TR_STATUS_SEED)
{
char ratioStr[80];
tr_strlratio(ratioStr, st->ratio, sizeof(ratioStr));
tr_snprintf(
buf,
buflen,
"Seeding, uploading to %d of %d peer(s), %s [%s]",
if (st->activity == TR_STATUS_SEED)
{
return fmt::format(
FMT_STRING("Seeding, uploading to {:d} of {:d} peer(s), {:s} [{:s}]"),
st->peersGettingFromUs,
st->peersConnected,
tr_formatter_speed_KBps(st->pieceUploadSpeed_KBps).c_str(),
ratioStr);
}
else
{
*buf = '\0';
tr_formatter_speed_KBps(st->pieceUploadSpeed_KBps),
tr_strlratio(st->ratio));
}
return "";
}
static char const* getConfigDir(int argc, char const** argv)
@ -319,8 +309,6 @@ int tr_main(int argc, char* argv[])
for (;;)
{
char line[LineWidth];
tr_stat const* st;
static auto constexpr messageName = std::array<char const*, 4>{
nullptr,
"Tracker gave a warning:",
@ -352,15 +340,14 @@ int tr_main(int argc, char* argv[])
}
}
st = tr_torrentStat(tor);
auto const* const st = tr_torrentStat(tor);
if (st->activity == TR_STATUS_STOPPED)
{
break;
}
getStatusStr(st, line, sizeof(line));
printf("\r%-*s", TR_ARG_TUPLE(LineWidth, line));
auto const status_str = getStatusStr(st);
printf("\r%-*s", TR_ARG_TUPLE(LineWidth, status_str.c_str()));
if (messageName[st->error])
{

View File

@ -692,9 +692,12 @@ static int daemon_start(void* varg, [[maybe_unused]] bool foreground)
if (ev_base == nullptr)
{
char buf[256];
tr_snprintf(buf, sizeof(buf), "Couldn't initialize daemon event state: %s", tr_strerror(errno));
printMessage(logfile, TR_LOG_ERROR, MyName, buf, __FILE__, __LINE__);
auto const error_code = errno;
auto const errmsg = fmt::format(
_("Couldn't initialize daemon: {error} ({error_code})"),
fmt::arg("error", tr_strerror(error_code)),
fmt::arg("error_code", error_code));
printMessage(logfile, TR_LOG_ERROR, MyName, errmsg, __FILE__, __LINE__);
return 1;
}

View File

@ -304,7 +304,7 @@ bool Application::Impl::refresh_actions()
sel_->selected_foreach(
[&canUpdate](auto const& /*path*/, auto const& iter)
{
auto* tor = static_cast<tr_torrent*>(iter->get_value(torrent_cols.torrent));
auto const* tor = static_cast<tr_torrent const*>(iter->get_value(torrent_cols.torrent));
canUpdate = canUpdate || tr_torrentCanManualUpdate(tor);
});
gtr_action_set_sensitive("torrent-reannounce", canUpdate);
@ -424,7 +424,7 @@ bool Application::Impl::on_rpc_changed_idle(tr_rpc_callback_type type, int torre
tr_variant* oldvals = gtr_pref_get_all();
tr_quark key;
std::vector<tr_quark> changed_keys;
auto* session = core_->get_session();
auto const* const session = core_->get_session();
tr_variantInitDict(&tmp, 100);
tr_sessionGetSettings(session, &tmp);
@ -1319,7 +1319,7 @@ bool Application::Impl::call_rpc_for_selected_torrents(std::string const& method
sel_->selected_foreach(
[ids](auto const& /*path*/, auto const& iter)
{
auto* tor = static_cast<tr_torrent*>(iter->get_value(torrent_cols.torrent));
auto const* const tor = static_cast<tr_torrent*>(iter->get_value(torrent_cols.torrent));
tr_variantListAddInt(ids, tr_torrentId(tor));
});

View File

@ -1353,7 +1353,7 @@ void refreshPeerRow(Gtk::TreeIter const& iter, tr_peer_stat const* peer)
void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torrents)
{
auto& hash = peer_hash_;
auto& store = peer_store_;
auto const& store = peer_store_;
/* step 1: get all the peers */
std::vector<tr_peer_stat*> peers;
@ -1440,7 +1440,7 @@ void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& tor
{
auto has_any_webseeds = bool{ false };
auto& hash = webseed_hash_;
auto& store = webseed_store_;
auto const& store = webseed_store_;
auto make_key = [](tr_torrent const* tor, char const* url)
{
@ -2152,7 +2152,7 @@ void DetailsDialog::Impl::refreshTracker(std::vector<tr_torrent*> const& torrent
{
std::ostringstream gstr;
auto& hash = tracker_hash_;
auto& store = tracker_store_;
auto const& store = tracker_store_;
auto* session = core_->get_session();
bool const showScrape = scrape_check_->get_active();
@ -2261,7 +2261,7 @@ void DetailsDialog::Impl::on_edit_trackers_response(int response, std::shared_pt
if (response == Gtk::RESPONSE_ACCEPT)
{
auto const torrent_id = GPOINTER_TO_INT(dialog->get_data(TORRENT_ID_KEY));
auto* const text_buffer = static_cast<Gtk::TextBuffer*>(dialog->get_data(TEXT_BUFFER_KEY));
auto const* const text_buffer = static_cast<Gtk::TextBuffer*>(dialog->get_data(TEXT_BUFFER_KEY));
if (auto* const tor = core_->find_torrent(torrent_id); tor != nullptr)
{
@ -2360,7 +2360,7 @@ void DetailsDialog::Impl::on_edit_trackers()
void DetailsDialog::Impl::on_tracker_list_selection_changed()
{
int const n = tracker_view_->get_selection()->count_selected_rows();
auto* tor = tracker_list_get_current_torrent();
auto const* const tor = tracker_list_get_current_torrent();
remove_tracker_button_->set_sensitive(n > 0);
add_tracker_button_->set_sensitive(tor != nullptr);
@ -2373,7 +2373,7 @@ void DetailsDialog::Impl::on_add_tracker_response(int response, std::shared_ptr<
if (response == Gtk::RESPONSE_ACCEPT)
{
auto* e = static_cast<Gtk::Entry*>(dialog->get_data(URL_ENTRY_KEY));
auto const* const e = static_cast<Gtk::Entry*>(dialog->get_data(URL_ENTRY_KEY));
auto const torrent_id = GPOINTER_TO_INT(dialog->get_data(TORRENT_ID_KEY));
auto const url = gtr_str_strip(e->get_text());

View File

@ -421,7 +421,7 @@ using FileRowNode = Glib::NodeTree<row_struct>;
void buildTree(FileRowNode& node, build_data& build)
{
auto& child_data = node.data();
auto const& child_data = node.data();
bool const isLeaf = node.child_count() == 0;
auto const mime_type = isLeaf ? gtr_get_mime_type_from_filename(child_data.name) : DirectoryMimeType;

View File

@ -62,7 +62,7 @@ std::string _icon_cache_get_icon_key(Glib::RefPtr<Gio::Icon> const& icon)
{
std::string key;
if (auto* const ticon = dynamic_cast<Gio::ThemedIcon*>(gtr_get_ptr(icon)); ticon != nullptr)
if (auto const* const ticon = dynamic_cast<Gio::ThemedIcon*>(gtr_get_ptr(icon)); ticon != nullptr)
{
std::ostringstream names;
for (auto const& name : ticon->get_names())

View File

@ -413,7 +413,7 @@ void TorrentFileChooserDialog::onOpenDialogResponse(int response, Glib::RefPtr<S
if (response == Gtk::RESPONSE_ACCEPT)
{
auto* tb = static_cast<Gtk::CheckButton*>(get_extra_widget());
auto const* const tb = static_cast<Gtk::CheckButton*>(get_extra_widget());
bool const do_start = gtr_pref_flag_get(TR_KEY_start_added_torrents);
bool const do_prompt = tb->get_active();
bool const do_notify = false;

View File

@ -99,7 +99,7 @@ bool spun_cb_idle(Gtk::SpinButton* spin, tr_quark const key, Glib::RefPtr<Sessio
bool keep_waiting = true;
/* has the user stopped making changes? */
if (auto* last_change = static_cast<Glib::Timer*>(spin->get_data(IdleDataKey)); last_change->elapsed() > 0.33)
if (auto const* const last_change = static_cast<Glib::Timer*>(spin->get_data(IdleDataKey)); last_change->elapsed() > 0.33)
{
/* update the core */
if (isDouble)

View File

@ -393,7 +393,7 @@ auto const ChildHiddenKey = Glib::Quark("gtr-child-hidden");
void gtr_widget_set_visible(Gtk::Widget& w, bool b)
{
/* toggle the transient children, too */
if (auto* const window = dynamic_cast<Gtk::Window*>(&w); window != nullptr)
if (auto const* const window = dynamic_cast<Gtk::Window*>(&w); window != nullptr)
{
for (auto* const l : Gtk::Window::list_toplevels())
{

View File

@ -194,8 +194,8 @@ static tr_scrape_info* tr_announcerGetScrapeInfo(tr_announcer* announcer, tr_int
}
auto& scrapes = announcer->scrape_info;
auto const it = scrapes.try_emplace(url, url, TR_MULTISCRAPE_MAX);
return &it.first->second;
auto const [it, is_new] = scrapes.try_emplace(url, url, TR_MULTISCRAPE_MAX);
return &it->second;
}
void tr_announcerInit(tr_session* session)
@ -403,7 +403,7 @@ struct tr_tier
auto const* const torrent_name = tr_torrentName(tor);
auto const* const current_tracker = currentTracker();
auto const host_sv = current_tracker == nullptr ? "?"sv : current_tracker->host.sv();
tr_snprintf(buf, buflen, "%s at %" TR_PRIsv, torrent_name, TR_PRIsv_ARG(host_sv));
*fmt::format_to_n(buf, buflen - 1, FMT_STRING("{:s} at {:s}"), torrent_name, host_sv).out = '\0';
}
[[nodiscard]] bool canManualAnnounce() const

View File

@ -14,7 +14,6 @@
#include <event2/util.h> /* evutil_ascii_strcasecmp() */
#include <fmt/core.h>
#include <fmt/format.h>
#include "transmission.h"
@ -326,7 +325,7 @@ static std::vector<std::byte> getHashInfo(tr_metainfo_builder* b)
if (!digest)
{
b->my_errno = EIO;
tr_snprintf(b->errfile, sizeof(b->errfile), "error hashing piece %" PRIu32, b->pieceIndex);
*fmt::format_to_n(b->errfile, sizeof(b->errfile) - 1, "error hashing piece {:d}", b->pieceIndex).out = '\0';
b->result = TrMakemetaResult::ERR_IO_READ;
break;
}

View File

@ -65,7 +65,7 @@ char const* tr_address_and_port_to_string(char* buf, size_t buflen, tr_address c
{
char addr_buf[INET6_ADDRSTRLEN];
tr_address_to_string_with_buf(addr, addr_buf, sizeof(addr_buf));
tr_snprintf(buf, buflen, "[%s]:%u", addr_buf, ntohs(port));
*fmt::format_to_n(buf, buflen - 1, FMT_STRING("[{:s}]:{:d}"), addr_buf, ntohs(port)).out = '\0';
return buf;
}

View File

@ -182,7 +182,7 @@ std::vector<tr_peer*> ActiveRequests::remove(tr_block_index_t block)
impl_->blocks_.erase(block);
}
for (auto* peer : removed)
for (auto const* const peer : removed)
{
impl_->decCount(peer);
}
@ -221,7 +221,7 @@ std::vector<std::pair<tr_block_index_t, tr_peer*>> ActiveRequests::sentBefore(ti
auto sent_before = std::vector<std::pair<tr_block_index_t, tr_peer*>>{};
sent_before.reserve(std::size(impl_->blocks_));
for (auto& [block, peers_at] : impl_->blocks_)
for (auto const& [block, peers_at] : impl_->blocks_)
{
for (auto const& sent : peers_at)
{

View File

@ -2111,7 +2111,7 @@ static void rechokeUploads(tr_swarm* s, uint64_t const now)
for (int i = 0; i < peerCount; ++i)
{
auto* const peer = peers[i];
struct peer_atom* const atom = peer->atom;
peer_atom const* const atom = peer->atom;
if (tr_peerIsSeed(peer))
{
@ -2363,7 +2363,7 @@ static void removePeer(tr_peer* peer)
static void closePeer(tr_peer* peer)
{
TR_ASSERT(peer != nullptr);
auto* const s = peer->swarm;
auto const* const s = peer->swarm;
/* if we transferred piece data, then they might be good peers,
so reset their `numFails' weight to zero. otherwise we connected

View File

@ -86,13 +86,10 @@ struct tr_rpc_idle_data
void* callback_user_data;
};
static void tr_idle_function_done(struct tr_rpc_idle_data* data, char const* result)
{
if (result == nullptr)
{
result = "success";
}
static auto constexpr SuccessResult = "success"sv;
static void tr_idle_function_done(struct tr_rpc_idle_data* data, std::string_view result)
{
tr_variantDictAddStr(data->response, TR_KEY_result, result);
(*data->callback)(data->session, data->response, data->callback_user_data);
@ -1069,7 +1066,7 @@ static char const* addTrackerUrls(tr_torrent* tor, tr_variant* urls)
for (size_t i = 0, n = tr_variantListSize(urls); i < n; ++i)
{
auto announce = std::string_view();
auto* const val = tr_variantListChild(urls, i);
auto const* const val = tr_variantListChild(urls, i);
if (val == nullptr || !tr_variantGetStrView(val, &announce))
{
continue;
@ -1121,7 +1118,7 @@ static char const* removeTrackers(tr_torrent* tor, tr_variant* ids)
for (size_t i = 0, n = tr_variantListSize(ids); i < n; ++i)
{
auto id = int64_t{};
auto* const val = tr_variantListChild(ids, i);
auto const* const val = tr_variantListChild(ids, i);
if (val == nullptr || !tr_variantGetInt(val, &id))
{
continue;
@ -1326,8 +1323,7 @@ static void torrentRenamePathDone(tr_torrent* tor, char const* oldpath, char con
tr_variantDictAddStr(data->args_out, TR_KEY_path, oldpath);
tr_variantDictAddStr(data->args_out, TR_KEY_name, newname);
char const* const result = error == 0 ? nullptr : tr_strerror(error);
tr_idle_function_done(data, result);
tr_idle_function_done(data, error != 0 ? tr_strerror(error) : SuccessResult);
}
static char const* torrentRenamePath(
@ -1363,21 +1359,23 @@ static char const* torrentRenamePath(
static void onPortTested(tr_web::FetchResponse const& web_response)
{
auto const& [status, body, did_connect, did_tmieout, user_data] = web_response;
char result[1024];
auto* data = static_cast<struct tr_rpc_idle_data*>(user_data);
if (status != 200)
{
tr_snprintf(result, sizeof(result), "portTested: http error %ld: %s", status, tr_webGetResponseStr(status));
tr_idle_function_done(
data,
fmt::format(
_("Couldn't test port: {error} ({error_code})"),
fmt::arg("error", tr_webGetResponseStr(status)),
fmt::arg("error_code", status)));
}
else /* success */
{
bool const isOpen = tr_strvStartsWith(body, '1');
tr_variantDictAddBool(data->args_out, TR_KEY_port_is_open, isOpen);
tr_snprintf(result, sizeof(result), "success");
tr_idle_function_done(data, SuccessResult);
}
tr_idle_function_done(data, result);
}
static char const* portTest(
@ -1402,13 +1400,15 @@ static void onBlocklistFetched(tr_web::FetchResponse const& web_response)
auto* data = static_cast<struct tr_rpc_idle_data*>(user_data);
auto* const session = data->session;
char result[1024] = {};
if (status != 200)
{
// we failed to download the blocklist...
tr_snprintf(result, sizeof(result), "gotNewBlocklist: http error %ld: %s", status, tr_webGetResponseStr(status));
tr_idle_function_done(data, result);
tr_idle_function_done(
data,
fmt::format(
_("Couldn't fetch blocklist: {error} ({error_code})"),
fmt::arg("error", tr_webGetResponseStr(status)),
fmt::arg("error_code", status)));
return;
}
@ -1446,15 +1446,14 @@ static void onBlocklistFetched(tr_web::FetchResponse const& web_response)
auto const filename = tr_pathbuf{ session->config_dir, "/blocklist.tmp"sv };
if (tr_error* error = nullptr; !tr_saveFile(filename, content, &error))
{
fmt::format_to_n(
result,
sizeof(result),
_("Couldn't save '{path}': {error} ({error_code})"),
fmt::arg("path", filename),
fmt::arg("error", error->message),
fmt::arg("error_code", error->code));
tr_idle_function_done(
data,
fmt::format(
_("Couldn't save '{path}': {error} ({error_code})"),
fmt::arg("path", filename),
fmt::arg("error", error->message),
fmt::arg("error_code", error->code)));
tr_error_clear(&error);
tr_idle_function_done(data, result);
return;
}
@ -1462,7 +1461,7 @@ static void onBlocklistFetched(tr_web::FetchResponse const& web_response)
int const rule_count = tr_blocklistSetContent(session, filename);
tr_variantDictAddInt(data->args_out, TR_KEY_blocklist_size, rule_count);
tr_sys_path_remove(filename);
tr_idle_function_done(data, "success");
tr_idle_function_done(data, SuccessResult);
}
static char const* blocklistUpdate(
@ -1485,39 +1484,33 @@ static void addTorrentImpl(struct tr_rpc_idle_data* data, tr_ctor* ctor)
tr_torrent* tor = tr_torrentNew(ctor, &duplicate_of);
tr_ctorFree(ctor);
auto key = tr_quark{};
char const* result = "invalid or corrupt torrent file";
if (tor != nullptr)
if (tor == nullptr && duplicate_of == nullptr)
{
key = TR_KEY_torrent_added;
result = nullptr;
}
else if (duplicate_of != nullptr)
{
tor = duplicate_of;
key = TR_KEY_torrent_duplicate;
result = "duplicate torrent";
tr_idle_function_done(data, "invalid or corrupt torrent file"sv);
return;
}
if (tor != nullptr && key != 0)
static auto constexpr Fields = std::array<tr_quark, 3>{ TR_KEY_id, TR_KEY_name, TR_KEY_hashString };
if (duplicate_of != nullptr)
{
tr_quark const fields[] = {
TR_KEY_id,
TR_KEY_name,
TR_KEY_hashString,
};
addTorrentInfo(tor, TrFormat::Object, tr_variantDictAdd(data->args_out, key), fields, TR_N_ELEMENTS(fields));
if (result == nullptr)
{
notify(data->session, TR_RPC_TORRENT_ADDED, tor);
}
result = nullptr;
addTorrentInfo(
duplicate_of,
TrFormat::Object,
tr_variantDictAdd(data->args_out, TR_KEY_torrent_duplicate),
std::data(Fields),
std::size(Fields));
tr_idle_function_done(data, "duplicate torrent"sv);
return;
}
tr_idle_function_done(data, result);
notify(data->session, TR_RPC_TORRENT_ADDED, tor);
addTorrentInfo(
tor,
TrFormat::Object,
tr_variantDictAdd(data->args_out, TR_KEY_torrent_added),
std::data(Fields),
std::size(Fields));
tr_idle_function_done(data, SuccessResult);
}
struct add_torrent_idle_data
@ -1544,9 +1537,12 @@ static void onMetadataFetched(tr_web::FetchResponse const& web_response)
}
else
{
char result[1024];
tr_snprintf(result, sizeof(result), "onMetadataFetched: http error %ld: %s", status, tr_webGetResponseStr(status));
tr_idle_function_done(data->data, result);
tr_idle_function_done(
data->data,
fmt::format(
_("Couldn't fetch torrent: {error} ({error_code})"),
fmt::arg("error", tr_webGetResponseStr(status)),
fmt::arg("error_code", status)));
}
tr_free(data);

View File

@ -32,7 +32,7 @@
#include <event2/event.h>
#include <fmt/core.h>
#include <fmt/format.h>
#include "transmission.h"
@ -106,12 +106,11 @@ static void bootstrap_from_name(char const* name, tr_port port, int af)
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = af;
/* No, just passing p + 1 to gai won't work. */
char pp[10];
tr_snprintf(pp, sizeof(pp), "%d", (int)port);
auto port_str = std::array<char, 16>{};
*fmt::format_to(std::data(port_str), FMT_STRING("{:d}"), port) = '\0';
addrinfo* info = nullptr;
if (int const rc = getaddrinfo(name, pp, &hints, &info); rc != 0)
if (int const rc = getaddrinfo(name, std::data(port_str), &hints, &info); rc != 0)
{
tr_logAddWarn(fmt::format(
_("Couldn't look up '{addresss}:{port}': {error} ({error_code})"),

View File

@ -114,6 +114,12 @@ public:
return std::basic_string_view<Char>{ data(), size() };
}
template<typename ContiguousRange>
[[nodiscard]] constexpr auto operator==(ContiguousRange const& x) const noexcept
{
return sv() == x;
}
///
[[nodiscard]] constexpr bool ends_with(Char const& x) const noexcept

View File

@ -140,18 +140,17 @@ static int tr_upnpGetSpecificPortMappingEntry(tr_upnp* handle, char const* proto
{
char intClient[16];
char intPort[16];
char portStr[16];
*intClient = '\0';
*intPort = '\0';
tr_snprintf(portStr, sizeof(portStr), "%d", handle->port);
auto const port_str = fmt::format(FMT_STRING("{:d}"), handle->port);
#if (MINIUPNPC_API_VERSION >= 10) /* adds remoteHost arg */
int const err = UPNP_GetSpecificPortMappingEntry(
handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
port_str.c_str(),
proto,
nullptr /*remoteHost*/,
intClient,
@ -163,7 +162,7 @@ static int tr_upnpGetSpecificPortMappingEntry(tr_upnp* handle, char const* proto
int const err = UPNP_GetSpecificPortMappingEntry(
handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
port_str.c_str(),
proto,
intClient,
intPort,
@ -174,7 +173,7 @@ static int tr_upnpGetSpecificPortMappingEntry(tr_upnp* handle, char const* proto
int const err = UPNP_GetSpecificPortMappingEntry(
handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
port_str.c_str(),
proto,
intClient,
intPort);
@ -186,17 +185,16 @@ static int tr_upnpGetSpecificPortMappingEntry(tr_upnp* handle, char const* proto
static int tr_upnpAddPortMapping(tr_upnp const* handle, char const* proto, tr_port port, char const* desc)
{
int const old_errno = errno;
char portStr[16];
errno = 0;
tr_snprintf(portStr, sizeof(portStr), "%d", (int)port);
auto const port_str = fmt::format(FMT_STRING("{:d}"), port);
#if (MINIUPNPC_API_VERSION >= 8)
int err = UPNP_AddPortMapping(
handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
portStr,
port_str.c_str(),
port_str.c_str(),
handle->lanaddr,
desc,
proto,
@ -206,8 +204,8 @@ static int tr_upnpAddPortMapping(tr_upnp const* handle, char const* proto, tr_po
int err = UPNP_AddPortMapping(
handle->urls.controlURL,
handle->data.first.servicetype,
portStr,
portStr,
port_str.c_str(),
port_str.c_str(),
handle->lanaddr,
desc,
proto,
@ -225,11 +223,9 @@ static int tr_upnpAddPortMapping(tr_upnp const* handle, char const* proto, tr_po
static void tr_upnpDeletePortMapping(tr_upnp const* handle, char const* proto, tr_port port)
{
char portStr[16];
auto const port_str = fmt::format(FMT_STRING("{:d}"), port);
tr_snprintf(portStr, sizeof(portStr), "%d", (int)port);
UPNP_DeletePortMapping(handle->urls.controlURL, handle->data.first.servicetype, portStr, proto, nullptr);
UPNP_DeletePortMapping(handle->urls.controlURL, handle->data.first.servicetype, port_str.c_str(), proto, nullptr);
}
/**
@ -338,11 +334,9 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool isEnabled, b
}
else
{
char desc[64];
tr_snprintf(desc, sizeof(desc), "%s at %d", TR_NAME, port);
int const err_tcp = tr_upnpAddPortMapping(handle, "TCP", port, desc);
int const err_udp = tr_upnpAddPortMapping(handle, "UDP", port, desc);
auto const desc = fmt::format(FMT_STRING("{:s} at {:d}"), TR_NAME, port);
int const err_tcp = tr_upnpAddPortMapping(handle, "TCP", port, desc.c_str());
int const err_udp = tr_upnpAddPortMapping(handle, "UDP", port, desc.c_str());
handle->isMapped = err_tcp == 0 || err_udp == 0;
}

View File

@ -428,12 +428,6 @@ char* tr_strvDup(std::string_view in)
return ret;
}
char* tr_strndup(void const* vin, size_t len)
{
auto const* const in = static_cast<char const*>(vin);
return in == nullptr ? nullptr : tr_strvDup({ in, len });
}
char* tr_strdup(void const* in)
{
return in == nullptr ? nullptr : tr_strvDup(static_cast<char const*>(in));
@ -722,7 +716,7 @@ static char* to_utf8(std::string_view sv)
iconv_close(cd);
if (rv != size_t(-1))
{
char* const ret = tr_strndup(out, buflen - outbytesleft);
char* const ret = tr_strvDup({ out, buflen - outbytesleft });
tr_free(out);
return ret;
}
@ -1129,18 +1123,14 @@ bool tr_moveFile(char const* oldpath, char const* newpath, tr_error** error)
return false;
}
if (tr_error* my_error = nullptr; !tr_sys_path_remove(oldpath, &my_error))
{
tr_error* my_error = nullptr;
if (!tr_sys_path_remove(oldpath, &my_error))
{
tr_logAddError(fmt::format(
_("Couldn't remove '{path}': {error} ({error_code})"),
fmt::arg("path", oldpath),
fmt::arg("error", my_error->message),
fmt::arg("error_code", my_error->code)));
tr_error_free(my_error);
}
tr_logAddError(fmt::format(
_("Couldn't remove '{path}': {error} ({error_code})"),
fmt::arg("path", oldpath),
fmt::arg("error", my_error->message),
fmt::arg("error_code", my_error->code)));
tr_error_free(my_error);
}
return true;

View File

@ -242,14 +242,6 @@ void* tr_memdup(void const* src, size_t byteCount);
#define tr_renew(struct_type, mem, n_structs) \
(static_cast<struct_type*>(tr_realloc((mem), sizeof(struct_type) * (size_t)(n_structs))))
/**
* @brief make a newly-allocated copy of a substring
* @param in is a void* so that callers can pass in both signed & unsigned without a cast
* @param len length of the substring to copy. if a length less than zero is passed in, strlen(len) is used
* @return a newly-allocated copy of `in' that can be freed with tr_free()
*/
char* tr_strndup(void const* in, size_t len) TR_GNUC_MALLOC;
/**
* @brief make a newly-allocated copy of a string
* @param in is a void* so that callers can pass in both signed & unsigned without a cast

View File

@ -12,6 +12,9 @@
#include <event2/buffer.h>
#include <fmt/compile.h>
#include <fmt/format.h>
#define LIBTRANSMISSION_VARIANT_MODULE
#include "transmission.h"
@ -19,7 +22,7 @@
#include "benc.h"
#include "tr-assert.h"
#include "quark.h"
#include "utils.h" /* tr_snprintf() */
#include "utils.h"
#include "variant-common.h"
#include "variant.h"
@ -256,13 +259,15 @@ bool tr_variantParseBenc(tr_variant& top, int parse_opts, std::string_view benc,
static void saveIntFunc(tr_variant const* val, void* vevbuf)
{
auto* evbuf = static_cast<struct evbuffer*>(vevbuf);
evbuffer_add_printf(evbuf, "i%" PRId64 "e", val->val.i);
auto buf = std::array<char, 64>{};
auto const out = fmt::format_to(std::data(buf), FMT_COMPILE("i{:d}e"), val->val.i);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
evbuffer_add(evbuf, std::data(buf), static_cast<size_t>(out - std::data(buf)));
}
static void saveBoolFunc(tr_variant const* val, void* vevbuf)
{
auto* evbuf = static_cast<struct evbuffer*>(vevbuf);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
if (val->val.b)
{
evbuffer_add(evbuf, "i1e", 3);
@ -273,41 +278,48 @@ static void saveBoolFunc(tr_variant const* val, void* vevbuf)
}
}
static void saveRealFunc(tr_variant const* val, void* vevbuf)
static void saveStringImpl(evbuffer* evbuf, std::string_view sv)
{
auto buf = std::array<char, 64>{};
int const len = tr_snprintf(std::data(buf), std::size(buf), "%f", val->val.d);
auto* evbuf = static_cast<evbuffer*>(vevbuf);
evbuffer_add_printf(evbuf, "%d:", len);
evbuffer_add(evbuf, std::data(buf), len);
// `${sv.size()}:${sv}`
auto prefix = std::array<char, 32>{};
auto out = fmt::format_to(std::data(prefix), FMT_COMPILE("{:d}:"), std::size(sv));
evbuffer_add(evbuf, std::data(prefix), out - std::data(prefix));
evbuffer_add(evbuf, std::data(sv), std::size(sv));
}
static void saveStringFunc(tr_variant const* v, void* vevbuf)
{
auto sv = std::string_view{};
(void)!tr_variantGetStrView(v, &sv);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
saveStringImpl(evbuf, sv);
}
auto* evbuf = static_cast<struct evbuffer*>(vevbuf);
evbuffer_add_printf(evbuf, "%zu:", std::size(sv));
evbuffer_add(evbuf, std::data(sv), std::size(sv));
static void saveRealFunc(tr_variant const* val, void* vevbuf)
{
// the benc spec doesn't handle floats; save it as a string.
auto buf = std::array<char, 64>{};
auto out = fmt::format_to(std::data(buf), FMT_COMPILE("{:f}"), val->val.d);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
saveStringImpl(evbuf, { std::data(buf), static_cast<size_t>(out - std::data(buf)) });
}
static void saveDictBeginFunc(tr_variant const* /*val*/, void* vevbuf)
{
auto* evbuf = static_cast<struct evbuffer*>(vevbuf);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
evbuffer_add(evbuf, "d", 1);
}
static void saveListBeginFunc(tr_variant const* /*val*/, void* vevbuf)
{
auto* evbuf = static_cast<struct evbuffer*>(vevbuf);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
evbuffer_add(evbuf, "l", 1);
}
static void saveContainerEndFunc(tr_variant const* /*val*/, void* vevbuf)
{
auto* evbuf = static_cast<struct evbuffer*>(vevbuf);
auto* const evbuf = static_cast<evbuffer*>(vevbuf);
evbuffer_add(evbuf, "e", 1);
}
@ -321,7 +333,7 @@ static struct VariantWalkFuncs const walk_funcs = {
saveContainerEndFunc, //
};
void tr_variantToBufBenc(tr_variant const* top, struct evbuffer* buf)
void tr_variantToBufBenc(tr_variant const* top, evbuffer* buf)
{
tr_variantWalk(top, &walk_funcs, buf, true);
}

View File

@ -16,7 +16,8 @@
#include <event2/buffer.h>
#include <fmt/core.h>
#include <fmt/compile.h>
#include <fmt/format.h>
#define LIBTRANSMISSION_VARIANT_MODULE
@ -162,7 +163,7 @@ static bool decode_hex_string(char const* in, unsigned int* setme)
return true;
}
static std::string_view extract_escaped_string(char const* in, size_t in_len, struct evbuffer* buf)
static std::string_view extract_escaped_string(char const* in, size_t in_len, evbuffer* buf)
{
char const* const in_end = in + in_len;
@ -225,27 +226,25 @@ static std::string_view extract_escaped_string(char const* in, size_t in_len, st
break;
case 'u':
if (in_end - in >= 6)
{
if (in_end - in >= 6)
{
unsigned int val = 0;
unsigned int val = 0;
if (decode_hex_string(in, &val))
if (decode_hex_string(in, &val))
{
try
{
try
{
auto buf8 = std::array<char, 8>{};
auto const it = utf8::append(val, std::data(buf8));
evbuffer_add(buf, std::data(buf8), it - std::data(buf8));
}
catch (utf8::exception const&)
{ // invalid codepoint
evbuffer_add(buf, "?", 1);
}
unescaped = true;
in += 6;
break;
auto buf8 = std::array<char, 8>{};
auto const it = utf8::append(val, std::data(buf8));
evbuffer_add(buf, std::data(buf8), it - std::data(buf8));
}
catch (utf8::exception const&)
{ // invalid codepoint
evbuffer_add(buf, "?", 1);
}
unescaped = true;
in += 6;
break;
}
}
}
@ -261,7 +260,7 @@ static std::string_view extract_escaped_string(char const* in, size_t in_len, st
return { (char const*)evbuffer_pullup(buf, -1), evbuffer_get_length(buf) };
}
static std::pair<std::string_view, bool> extract_string(jsonsl_t jsn, struct jsonsl_state_st* state, struct evbuffer* buf)
static std::pair<std::string_view, bool> extract_string(jsonsl_t jsn, struct jsonsl_state_st* state, evbuffer* buf)
{
// figure out where the string is
char const* in_begin = jsn->base + state->pos_begin;
@ -311,7 +310,7 @@ static void action_callback_POP(
else if (state->type == JSONSL_T_LIST || state->type == JSONSL_T_OBJECT)
{
int const depth = std::size(data->stack);
auto* v = data->stack.back();
auto const* const v = data->stack.back();
data->stack.pop_back();
if (depth < MaxDepth)
{
@ -407,7 +406,7 @@ struct jsonWalk
{
bool doIndent;
std::deque<ParentState> parents;
struct evbuffer* out;
evbuffer* out;
};
static void jsonIndent(struct jsonWalk* data)
@ -457,17 +456,15 @@ static void jsonChildFunc(struct jsonWalk* data)
}
case TR_VARIANT_TYPE_LIST:
++pstate.childIndex;
if (bool const is_last = pstate.childIndex == pstate.childCount; !is_last)
{
++pstate.childIndex;
if (bool const is_last = pstate.childIndex == pstate.childCount; !is_last)
{
evbuffer_add(data->out, ",", 1);
jsonIndent(data);
}
break;
evbuffer_add(data->out, ",", 1);
jsonIndent(data);
}
break;
default:
break;
}
@ -487,8 +484,10 @@ static void jsonPopParent(struct jsonWalk* data)
static void jsonIntFunc(tr_variant const* val, void* vdata)
{
auto* data = static_cast<struct jsonWalk*>(vdata);
evbuffer_add_printf(data->out, "%" PRId64, val->val.i);
auto buf = std::array<char, 64>{};
auto const out = fmt::format_to(std::data(buf), FMT_COMPILE("{:d}"), val->val.i);
auto* const data = static_cast<jsonWalk*>(vdata);
evbuffer_add(data->out, std::data(buf), static_cast<size_t>(out - std::data(buf)));
jsonChildFunc(data);
}
@ -514,11 +513,15 @@ static void jsonRealFunc(tr_variant const* val, void* vdata)
if (fabs(val->val.d - (int)val->val.d) < 0.00001)
{
evbuffer_add_printf(data->out, "%d", (int)val->val.d);
auto buf = std::array<char, 64>{};
auto const out = fmt::format_to(std::data(buf), FMT_COMPILE("{:.0f}"), val->val.d);
evbuffer_add(data->out, std::data(buf), static_cast<size_t>(out - std::data(buf)));
}
else
{
evbuffer_add_printf(data->out, "%.4f", tr_truncd(val->val.d, 4));
auto buf = std::array<char, 64>{};
auto const out = fmt::format_to(std::data(buf), FMT_COMPILE("{:.4f}"), val->val.d);
evbuffer_add(data->out, std::data(buf), static_cast<size_t>(out - std::data(buf)));
}
jsonChildFunc(data);
@ -526,7 +529,7 @@ static void jsonRealFunc(tr_variant const* val, void* vdata)
static void jsonStringFunc(tr_variant const* val, void* vdata)
{
struct evbuffer_iovec vec[1];
evbuffer_iovec vec[1];
auto* data = static_cast<struct jsonWalk*>(vdata);
auto sv = std::string_view{};
@ -591,7 +594,7 @@ static void jsonStringFunc(tr_variant const* val, void* vdata)
auto const* const end8 = begin8 + std::size(sv);
auto const* walk8 = begin8;
auto const uch32 = utf8::next(walk8, end8);
outwalk += tr_snprintf(outwalk, outend - outwalk, "\\u%04x", uch32);
outwalk = fmt::format_to_n(outwalk, outend - outwalk - 1, FMT_COMPILE("\\u{:04x}"), uch32).out;
sv.remove_prefix(walk8 - begin8 - 1);
}
catch (utf8::exception const&)
@ -667,7 +670,7 @@ static struct VariantWalkFuncs const walk_funcs = {
jsonContainerEndFunc, //
};
void tr_variantToBufJson(tr_variant const* top, struct evbuffer* buf, bool lean)
void tr_variantToBufJson(tr_variant const* top, evbuffer* buf, bool lean)
{
struct jsonWalk data;

View File

@ -239,6 +239,7 @@ set(${PROJECT_NAME}_HIDPI_IMAGES
ActionHover
ActionOn
Bandwidth
BlueDotFlat
CleanupTemplate
CompleteCheck
CreateLarge
@ -246,6 +247,7 @@ set(${PROJECT_NAME}_HIDPI_IMAGES
DownArrowTemplate
FavIcon
Globe
GreenDotFlat
Groups
GroupsNoneTemplate
InfoActivity
@ -256,6 +258,7 @@ set(${PROJECT_NAME}_HIDPI_IMAGES
InfoTracker
Lock
Magnet
OrangeDotFlat
PauseHover
PauseOff
PauseOn

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "mac",
"filename" : "BlueDotFlat.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"filename" : "BlueDotFlat@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "mac",
"filename" : "GreenDotFlat.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"filename" : "GreenDotFlat@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "mac",
"filename" : "OrangeDotFlat.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"filename" : "OrangeDotFlat@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 575 B

View File

@ -47,11 +47,11 @@
<font key="font" metaFont="menu"/>
<menu key="menu" title="OtherViews" id="16">
<items>
<menuItem title="Error" state="on" image="RedDotFlat" id="17"/>
<menuItem title="Warn" image="RedDotFlat" id="yoL-9H-kTt"/>
<menuItem title="Info" image="YellowDotFlat" id="18"/>
<menuItem title="Debug" image="PurpleDotFlat" id="19"/>
<menuItem title="Trace" image="PurpleDotFlat" id="2hu-LL-6A5"/>
<menuItem title="Error" state="on" image="RedDotFlat"/>
<menuItem title="Warn" image="OrangeDotFlat"/>
<menuItem title="Info" image="GreenDotFlat"/>
<menuItem title="Debug" image="BlueDotFlat"/>
<menuItem title="Trace" image="PurpleDotFlat"/>
</items>
</menu>
</popUpButtonCell>

View File

@ -270,13 +270,17 @@
{
case TR_LOG_CRITICAL:
case TR_LOG_ERROR:
case TR_LOG_WARN:
return [NSImage imageNamed:@"RedDotFlat"];
case TR_LOG_WARN:
return [NSImage imageNamed:@"OrangeDotFlat"];
case TR_LOG_INFO:
return [NSImage imageNamed:@"YellowDotFlat"];
return [NSImage imageNamed:@"GreenDotFlat"];
case TR_LOG_DEBUG:
return [NSImage imageNamed:@"BlueDotFlat"];
case TR_LOG_TRACE:
return [NSImage imageNamed:@"PurpleDotFlat"];

View File

@ -1462,7 +1462,7 @@ void DetailsDialog::initTrackerTab()
ui_.trackersView->setModel(tracker_filter_.get());
ui_.trackersView->setItemDelegate(tracker_delegate_.get());
auto& icons = IconCache::get();
auto const& icons = IconCache::get();
ui_.addTrackerButton->setIcon(icons.getThemeIcon(QStringLiteral("list-add"), QStyle::SP_DialogOpenButton));
ui_.editTrackersButton->setIcon(icons.getThemeIcon(QStringLiteral("document-properties"), QStyle::SP_DesktopIcon));
ui_.removeTrackerButton->setIcon(icons.getThemeIcon(QStringLiteral("list-remove"), QStyle::SP_TrashIcon));

View File

@ -51,7 +51,7 @@ FilterBarComboBox* FilterBar::createActivityCombo()
model->appendRow(new QStandardItem); // separator
FilterBarComboBoxDelegate::setSeparator(model, model->index(1, 0));
auto& icons = IconCache::get();
auto const& icons = IconCache::get();
row = new QStandardItem(icons.getThemeIcon(QStringLiteral("system-run")), tr("Active"));
row->setData(FilterMode::SHOW_ACTIVE, ACTIVITY_ROLE);
@ -279,7 +279,7 @@ void FilterBar::refreshPref(int key)
case Prefs::FILTER_MODE:
{
auto const m = prefs_.get<FilterMode>(key);
QAbstractItemModel* model = activity_combo_->model();
QAbstractItemModel const* const model = activity_combo_->model();
QModelIndexList indices = model->match(model->index(0, 0), ACTIVITY_ROLE, m.mode());
activity_combo_->setCurrentIndex(indices.isEmpty() ? 0 : indices.first().row());
break;

View File

@ -87,7 +87,7 @@ void FilterBarComboBox::paintEvent(QPaintEvent* e)
if (model_index.isValid())
{
QStyle* s = style();
QStyle const* const s = style();
int const hmargin = getHSpacing(this);
QRect rect = s->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);

View File

@ -38,7 +38,7 @@ void FilterBarComboBoxDelegate::setSeparator(QAbstractItemModel* model, QModelIn
{
model->setData(index, QStringLiteral("separator"), Qt::AccessibleDescriptionRole);
if (auto* m = qobject_cast<QStandardItemModel*>(model))
if (auto const* const m = qobject_cast<QStandardItemModel*>(model))
{
if (QStandardItem* item = m->itemFromIndex(index))
{
@ -109,7 +109,7 @@ QSize FilterBarComboBoxDelegate::sizeHint(QStyleOptionViewItem const& option, QM
return { pm, pm + 10 };
}
QStyle* s = combo_->style();
QStyle const* const s = combo_->style();
int const hmargin = getHSpacing(combo_);
QSize size = QItemDelegate::sizeHint(option, index);

View File

@ -84,7 +84,7 @@ QIcon MainWindow::addEmblem(QIcon base_icon, QStringList const& emblem_names) co
return base_icon;
}
auto& icons = IconCache::get();
auto const& icons = IconCache::get();
QIcon emblem_icon;
for (QString const& emblem_name : emblem_names)
@ -144,7 +144,7 @@ MainWindow::MainWindow(Session& session, Prefs& prefs, TorrentModel& model, bool
ui_.listView->setStyle(lvp_style_.get());
ui_.listView->setAttribute(Qt::WA_MacShowFocusRect, false);
auto& icons = IconCache::get();
auto const& icons = IconCache::get();
// icons
QIcon const icon_play = icons.getThemeIcon(QStringLiteral("media-playback-start"), QStyle::SP_MediaPlay);

View File

@ -123,7 +123,7 @@ void TorrentModel::removeTorrents(tr_variant* list)
torrents.reserve(tr_variantListSize(list));
int i = 0;
tr_variant* child = nullptr;
tr_variant const* child = nullptr;
while ((child = tr_variantListChild(list, i++)) != nullptr)
{
if (auto const id = getValue<int>(child); id)

View File

@ -30,7 +30,7 @@ protected:
auto const path1 = tr_strvPath(sandboxDir(), filename1);
/* Create a file. */
char* file_content = static_cast<char*>(tr_malloc(file_length));
auto* file_content = static_cast<char*>(tr_malloc(file_length));
tr_rand_buffer(file_content, file_length);
createFileWithContents(path1, file_content, file_length);
tr_free(file_content);
@ -91,8 +91,8 @@ private:
uint64_t bytes_left2 = info2.size;
size_t const buflen = 2 * 1024 * 1024; /* 2 MiB buffer */
char* readbuf1 = static_cast<char*>(tr_malloc(buflen));
char* readbuf2 = static_cast<char*>(tr_malloc(buflen));
auto* readbuf1 = static_cast<char*>(tr_malloc(buflen));
auto* readbuf2 = static_cast<char*>(tr_malloc(buflen));
while (bytes_left1 > 0 || bytes_left2 > 0)
{

View File

@ -9,6 +9,8 @@
#include <string>
#include <string_view>
#include <fmt/format.h>
#include "transmission.h"
#include "crypto-utils.h"
@ -44,10 +46,10 @@ protected:
{
// create a single input file
auto input_file = tr_strvPath(sandboxDir().data(), "test.XXXXXX");
createTmpfileWithContents(input_file, payload, payloadSize);
auto input_file = tr_pathbuf{ sandboxDir(), '/', "test.XXXXXX" };
createTmpfileWithContents(std::data(input_file), payload, payloadSize);
tr_sys_path_native_separators(std::data(input_file));
auto* builder = tr_metaInfoBuilderCreate(input_file.c_str());
auto* builder = tr_metaInfoBuilderCreate(input_file);
EXPECT_EQ(tr_file_index_t{ 1 }, builder->fileCount);
EXPECT_EQ(input_file, builder->top);
EXPECT_EQ(input_file, builder->files[0].filename);
@ -57,10 +59,10 @@ protected:
EXPECT_FALSE(builder->abortFlag);
// have tr_makeMetaInfo() build the torrent file
auto const torrent_file = tr_strvJoin(input_file, ".torrent"sv);
auto const torrent_file = tr_pathbuf{ input_file, ".torrent"sv };
tr_makeMetaInfo(
builder,
torrent_file.c_str(),
torrent_file,
trackers,
trackerCount,
webseeds,
@ -111,7 +113,7 @@ protected:
char const* source)
{
// create the top temp directory
auto top = tr_strvPath(sandboxDir(), "folder.XXXXXX");
auto top = tr_pathbuf{ sandboxDir(), '/', "folder.XXXXXX"sv };
tr_sys_path_native_separators(std::data(top));
tr_sys_dir_create_temp(std::data(top));
@ -122,10 +124,8 @@ protected:
for (size_t i = 0; i < payload_count; i++)
{
auto tmpl = std::array<char, 16>{};
tr_snprintf(tmpl.data(), tmpl.size(), "file.%04zu%s", i, "XXXXXX");
auto path = tr_strvPath(top, std::data(tmpl));
createTmpfileWithContents(path, payloads[i], payload_sizes[i]);
auto path = fmt::format(FMT_STRING("{:s}/file.{:04}XXXXXX"), top.sv(), i);
createTmpfileWithContents(std::data(path), payloads[i], payload_sizes[i]);
tr_sys_path_native_separators(std::data(path));
files.push_back(path);
total_size += payload_sizes[i];
@ -134,7 +134,7 @@ protected:
sync();
// init the builder
auto* builder = tr_metaInfoBuilderCreate(top.c_str());
auto* builder = tr_metaInfoBuilderCreate(top);
EXPECT_FALSE(builder->abortFlag);
EXPECT_EQ(top, builder->top);
EXPECT_EQ(payload_count, builder->fileCount);
@ -148,7 +148,7 @@ protected:
}
// build the torrent file
auto torrent_file = tr_strvJoin(top, ".torrent"sv);
auto const torrent_file = tr_pathbuf{ top, ".torrent"sv };
tr_makeMetaInfo(
builder,
torrent_file.c_str(),
@ -201,8 +201,8 @@ protected:
{
// build random payloads
size_t payload_count = 1 + tr_rand_int_weak(max_file_count);
void** payloads = tr_new0(void*, payload_count);
size_t* payload_sizes = tr_new0(size_t, payload_count);
auto** payloads = tr_new0(void*, payload_count);
auto* payload_sizes = tr_new0(size_t, payload_count);
for (size_t i = 0; i < payload_count; i++)
{

View File

@ -93,7 +93,7 @@ TEST_P(IncompleteDirTest, incompleteDir)
// now finish writing it
{
char* zero_block = tr_new0(char, tr_block_info::BlockSize);
auto* const zero_block = tr_new0(char, tr_block_info::BlockSize);
struct TestIncompleteDirData data = {};
data.session = session_;

View File

@ -88,17 +88,16 @@ public:
protected:
static std::string get_default_parent_dir()
{
auto* path = getenv("TMPDIR");
if (path != NULL)
if (auto* const path = getenv("TMPDIR"); path != nullptr)
{
return path;
}
tr_error* error = nullptr;
path = tr_sys_dir_get_current(&error);
if (path != nullptr)
if (auto* path = tr_sys_dir_get_current(&error); path != nullptr)
{
std::string const ret = path;
auto ret = std::string{ path };
tr_free(path);
return ret;
}
@ -179,7 +178,7 @@ protected:
return child;
}
void buildParentDir(std::string const& path) const
void buildParentDir(std::string_view path) const
{
auto const tmperr = errno;
@ -212,14 +211,14 @@ protected:
}
}
void createTmpfileWithContents(std::string& tmpl, void const* payload, size_t n) const
void createTmpfileWithContents(char* tmpl, void const* payload, size_t n) const
{
auto const tmperr = errno;
buildParentDir(tmpl);
// NOLINTNEXTLINE(clang-analyzer-cplusplus.InnerPointer)
auto const fd = tr_sys_file_open_temp(&tmpl.front());
auto const fd = tr_sys_file_open_temp(tmpl);
blockingFileWrite(fd, payload, n);
tr_sys_file_close(fd);
sync();

View File

@ -3,7 +3,15 @@
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <algorithm>
#include <array>
#include <cmath> // sqrt()
#include <cstdlib> // setenv(), unsetenv()
#include <iostream>
#include <sstream>
#include <string>
#include <string_view>
#include <utility>
#ifdef _WIN32
#include <windows.h>
@ -21,14 +29,6 @@
#include "test-fixtures.h"
#include <algorithm>
#include <array>
#include <cmath> // sqrt()
#include <cstdlib> // setenv(), unsetenv()
#include <iostream>
#include <sstream>
#include <string>
using ::libtransmission::test::makeString;
using UtilsTest = ::testing::Test;
using namespace std::literals;
@ -344,7 +344,7 @@ TEST_F(UtilsTest, trStrlcpy)
"This, very usefull string contains total of 104 characters not counting null. Almost like an easter egg!"
};
for (auto& test : tests)
for (auto const& test : tests)
{
auto c_string = test.c_str();
auto length = strlen(c_string);
@ -458,12 +458,22 @@ TEST_F(UtilsTest, saveFile)
TEST_F(UtilsTest, ratioToString)
{
// Testpairs contain ratio as a double and a string
std::vector<std::pair<double, std::string>> const tests{
{ 0.0, "0.00" }, { 0.01, "0.01" }, { 0.1, "0.10" }, { 1.0, "1.00" }, { 1.015, "1.01" },
{ 4.99, "4.99" }, { 4.996, "4.99" }, { 5.0, "5.0" }, { 5.09999, "5.0" }, { 5.1, "5.1" },
{ 99.99, "99.9" }, { 100.0, "100" }, { 4000.4, "4000" }, { 600000.0, "600000" }, { 900000000.0, "900000000" },
{ TR_RATIO_INF, "inf" }
};
static auto constexpr Tests = std::array<std::pair<double, std::string_view>, 16>{ { { 0.0, "0.00" },
{ 0.01, "0.01" },
{ 0.1, "0.10" },
{ 1.0, "1.00" },
{ 1.015, "1.01" },
{ 4.99, "4.99" },
{ 4.996, "4.99" },
{ 5.0, "5.0" },
{ 5.09999, "5.0" },
{ 5.1, "5.1" },
{ 99.99, "99.9" },
{ 100.0, "100" },
{ 4000.4, "4000" },
{ 600000.0, "600000" },
{ 900000000.0, "900000000" },
{ TR_RATIO_INF, "inf" } } };
char const nullchar = '\0';
ASSERT_EQ(tr_strratio(TR_RATIO_NA, "Ratio is NaN"), "None");
@ -471,8 +481,8 @@ TEST_F(UtilsTest, ratioToString)
// Inf contains only null character
ASSERT_EQ(tr_strratio(TR_RATIO_INF, &nullchar), "");
for (auto& test : tests)
for (auto const& [input, expected] : Tests)
{
ASSERT_EQ(tr_strratio(test.first, "inf"), test.second);
ASSERT_EQ(tr_strratio(input, "inf"), expected);
}
}

View File

@ -208,8 +208,8 @@ TEST_F(WebUtilsTest, urlPercentDecode)
"http://www.example.com/~user/?test=1&test1=2"sv },
} };
for (auto const& test : Tests)
for (auto const& [encoded, decoded] : Tests)
{
EXPECT_EQ(test.second, tr_urlPercentDecode(test.first));
EXPECT_EQ(decoded, tr_urlPercentDecode(encoded));
}
}

@ -1 +1 @@
Subproject commit 68ca04c261ded1b936ef5c121618247f7010d445
Subproject commit af29db7ec28d6df1c7f0f745186884091e602e07

View File

@ -324,7 +324,7 @@ int tr_main(int argc, char* argv[])
return EXIT_FAILURE;
}
if (options.add == nullptr && options.deleteme == nullptr && options.replace[0] == 0)
if (options.add == nullptr && options.deleteme == nullptr && options.replace[0] == nullptr)
{
fprintf(stderr, "ERROR: Must specify -a, -d or -r\n");
tr_getopt_usage(MyName, Usage, std::data(Options));

View File

@ -80,38 +80,33 @@ static char constexpr SpeedTStr[] = "TB/s";
****
***/
static void etaToString(char* buf, size_t buflen, int64_t eta)
static std::string etaToString(int64_t eta)
{
if (eta < 0)
{
tr_snprintf(buf, buflen, "Unknown");
return "Unknown";
}
else if (eta < 60)
if (eta < 60)
{
tr_snprintf(buf, buflen, "%" PRId64 " sec", eta);
return fmt::format(FMT_STRING("{:d} sec"), eta);
}
else if (eta < (60 * 60))
if (eta < (60 * 60))
{
tr_snprintf(buf, buflen, "%" PRId64 " min", eta / 60);
return fmt::format(FMT_STRING("{:d} min"), eta / 60);
}
else if (eta < (60 * 60 * 24))
if (eta < (60 * 60 * 24))
{
tr_snprintf(buf, buflen, "%" PRId64 " hrs", eta / (60 * 60));
}
else
{
tr_snprintf(buf, buflen, "%" PRId64 " days", eta / (60 * 60 * 24));
return fmt::format(FMT_STRING("{:d} hrs"), eta / (60 * 60));
}
return fmt::format(FMT_STRING("{:d} days"), eta / (60 * 60 * 24));
}
static char* tr_strltime(char* buf, int seconds, size_t buflen)
static std::string tr_strltime(int seconds)
{
char b[128];
char h[128];
char m[128];
char s[128];
char t[128];
if (seconds < 0)
{
seconds = 0;
@ -123,54 +118,32 @@ static char* tr_strltime(char* buf, int seconds, size_t buflen)
auto const minutes = (seconds % 3600) / 60;
seconds = (seconds % 3600) % 60;
tr_snprintf(h, sizeof(h), "%d %s", hours, hours == 1 ? "hour" : "hours");
tr_snprintf(m, sizeof(m), "%d %s", minutes, minutes == 1 ? "minute" : "minutes");
tr_snprintf(s, sizeof(s), "%d %s", seconds, seconds == 1 ? "second" : "seconds");
tr_snprintf(t, sizeof(t), "%d %s", total_seconds, total_seconds == 1 ? "second" : "seconds");
auto tmpstr = std::string{};
if (days != 0)
{
char d[128];
tr_snprintf(d, sizeof(d), "%d %s", days, days == 1 ? "day" : "days");
auto const hstr = fmt::format(FMT_STRING("{:d} {:s}"), hours, ngettext("hour", "hours", hours));
auto const mstr = fmt::format(FMT_STRING("{:d} {:s}"), minutes, ngettext("minute", "minutes", minutes));
auto const sstr = fmt::format(FMT_STRING("{:d} {:s}"), seconds, ngettext("seconds", "seconds", seconds));
if (days >= 4 || hours == 0)
{
tr_strlcpy(b, d, sizeof(b));
}
else
{
tr_snprintf(b, sizeof(b), "%s, %s", d, h);
}
}
else if (hours != 0)
if (days > 0)
{
if (hours >= 4 || minutes == 0)
{
tr_strlcpy(b, h, sizeof(b));
}
else
{
tr_snprintf(b, sizeof(b), "%s, %s", h, m);
}
auto const dstr = fmt::format(FMT_STRING("{:d} {:s}"), hours, ngettext("day", "days", days));
tmpstr = days >= 4 || hours == 0 ? dstr : fmt::format(FMT_STRING("{:s}, {:s}"), dstr, hstr);
}
else if (minutes != 0)
else if (hours > 0)
{
if (minutes >= 4 || seconds == 0)
{
tr_strlcpy(b, m, sizeof(b));
}
else
{
tr_snprintf(b, sizeof(b), "%s, %s", m, s);
}
tmpstr = hours >= 4 || minutes == 0 ? hstr : fmt::format(FMT_STRING("{:s}, {:s}"), hstr, mstr);
}
else if (minutes > 0)
{
tmpstr = minutes >= 4 || seconds == 0 ? mstr : fmt::format(FMT_STRING("{:s}, {:s}"), mstr, sstr);
}
else
{
tr_strlcpy(b, s, sizeof(b));
tmpstr = sstr;
}
tr_snprintf(buf, buflen, "%s (%s)", b, t);
return buf;
auto const totstr = fmt::format(FMT_STRING("{:d} {:s}"), total_seconds, ngettext("seconds", "seconds", total_seconds));
return fmt::format(FMT_STRING("{:s} ({:s})"), tmpstr, totstr);
}
static std::string strlpercent(double x)
@ -826,99 +799,70 @@ static long getTimeoutSecs(std::string_view req)
return 60L; /* default value */
}
static char* getStatusString(tr_variant* t, char* buf, size_t buflen)
static std::string getStatusString(tr_variant* t)
{
int64_t status;
bool boolVal;
auto from_us = int64_t{};
auto status = int64_t{};
auto to_us = int64_t{};
if (!tr_variantDictFindInt(t, TR_KEY_status, &status))
{
*buf = '\0';
return "";
}
else
switch (status)
{
switch (status)
case TR_STATUS_DOWNLOAD_WAIT:
case TR_STATUS_SEED_WAIT:
return "Queued";
case TR_STATUS_STOPPED:
if (auto flag = bool{}; tr_variantDictFindBool(t, TR_KEY_isFinished, &flag) && flag)
{
case TR_STATUS_DOWNLOAD_WAIT:
case TR_STATUS_SEED_WAIT:
tr_strlcpy(buf, "Queued", buflen);
break;
case TR_STATUS_STOPPED:
if (tr_variantDictFindBool(t, TR_KEY_isFinished, &boolVal) && boolVal)
{
tr_strlcpy(buf, "Finished", buflen);
}
else
{
tr_strlcpy(buf, "Stopped", buflen);
}
break;
case TR_STATUS_CHECK_WAIT:
case TR_STATUS_CHECK:
{
char const* str = status == TR_STATUS_CHECK_WAIT ? "Will Verify" : "Verifying";
double percent;
if (tr_variantDictFindReal(t, TR_KEY_recheckProgress, &percent))
{
tr_snprintf(buf, buflen, "%s (%.0f%%)", str, floor(percent * 100.0));
}
else
{
tr_strlcpy(buf, str, buflen);
}
break;
}
case TR_STATUS_DOWNLOAD:
case TR_STATUS_SEED:
{
int64_t fromUs = 0;
int64_t toUs = 0;
tr_variantDictFindInt(t, TR_KEY_peersGettingFromUs, &fromUs);
tr_variantDictFindInt(t, TR_KEY_peersSendingToUs, &toUs);
if (fromUs != 0 && toUs != 0)
{
tr_strlcpy(buf, "Up & Down", buflen);
}
else if (toUs != 0)
{
tr_strlcpy(buf, "Downloading", buflen);
}
else if (fromUs != 0)
{
int64_t leftUntilDone = 0;
tr_variantDictFindInt(t, TR_KEY_leftUntilDone, &leftUntilDone);
if (leftUntilDone > 0)
{
tr_strlcpy(buf, "Uploading", buflen);
}
else
{
tr_strlcpy(buf, "Seeding", buflen);
}
}
else
{
tr_strlcpy(buf, "Idle", buflen);
}
break;
}
default:
tr_strlcpy(buf, "Unknown", buflen);
break;
return "Finished";
}
}
return "Stopped";
return buf;
case TR_STATUS_CHECK_WAIT:
if (auto percent = double{}; tr_variantDictFindReal(t, TR_KEY_recheckProgress, &percent))
{
return fmt::format(FMT_STRING("Will Verify ({:.0f}%)"), floor(percent * 100.0));
}
return "Will Verify";
case TR_STATUS_CHECK:
if (auto percent = double{}; tr_variantDictFindReal(t, TR_KEY_recheckProgress, &percent))
{
return fmt::format(FMT_STRING("Verifying ({:.0f}%)"), floor(percent * 100.0));
}
return "Verifying";
case TR_STATUS_DOWNLOAD:
case TR_STATUS_SEED:
tr_variantDictFindInt(t, TR_KEY_peersGettingFromUs, &from_us);
tr_variantDictFindInt(t, TR_KEY_peersSendingToUs, &to_us);
if (from_us != 0 && to_us != 0)
{
return "Up & Down";
}
if (to_us != 0)
{
return "Downloading";
}
if (from_us == 0)
{
return "Idle";
}
if (auto left_until_done = int64_t{};
tr_variantDictFindInt(t, TR_KEY_leftUntilDone, &left_until_done) && left_until_done > 0)
{
return "Uploading";
}
return "Seeding";
default:
return "Unknown";
}
}
static char const* bandwidthPriorityNames[] = {
@ -1002,8 +946,7 @@ static void printDetails(tr_variant* top)
printf("\n");
printf("TRANSFER\n");
getStatusString(t, buf, sizeof(buf));
printf(" State: %s\n", buf);
printf(" State: %s\n", getStatusString(t).c_str());
if (tr_variantDictFindStrView(t, TR_KEY_downloadDir, &sv))
{
@ -1017,7 +960,7 @@ static void printDetails(tr_variant* top)
if (tr_variantDictFindInt(t, TR_KEY_eta, &i))
{
printf(" ETA: %s\n", tr_strltime(buf, i, sizeof(buf)));
printf(" ETA: %s\n", tr_strltime(i).c_str());
}
if (tr_variantDictFindInt(t, TR_KEY_rateDownload, &i))
@ -1144,12 +1087,12 @@ static void printDetails(tr_variant* top)
if (tr_variantDictFindInt(t, TR_KEY_secondsDownloading, &i) && i > 0)
{
printf(" Downloading Time: %s\n", tr_strltime(buf, i, sizeof(buf)));
printf(" Downloading Time: %s\n", tr_strltime(i).c_str());
}
if (tr_variantDictFindInt(t, TR_KEY_secondsSeeding, &i) && i > 0)
{
printf(" Seeding Time: %s\n", tr_strltime(buf, i, sizeof(buf)));
printf(" Seeding Time: %s\n", tr_strltime(i).c_str());
}
printf("\n");
@ -1508,50 +1451,25 @@ static void printTorrentList(tr_variant* top)
tr_variantDictFindInt(d, TR_KEY_sizeWhenDone, &sizeWhenDone) &&
tr_variantDictFindInt(d, TR_KEY_status, &status) && tr_variantDictFindReal(d, TR_KEY_uploadRatio, &ratio))
{
char etaStr[16];
char statusStr[64];
char doneStr[8];
int64_t error;
char errorMark;
if (sizeWhenDone != 0)
{
tr_snprintf(doneStr, sizeof(doneStr), "%d%%", (int)(100.0 * (sizeWhenDone - leftUntilDone) / sizeWhenDone));
}
else
{
tr_strlcpy(doneStr, "n/a", sizeof(doneStr));
}
if (leftUntilDone != 0 || eta != -1)
{
etaToString(etaStr, sizeof(etaStr), eta);
}
else
{
tr_snprintf(etaStr, sizeof(etaStr), "Done");
}
if (tr_variantDictFindInt(d, TR_KEY_error, &error) && error)
{
errorMark = '*';
}
else
{
errorMark = ' ';
}
auto const eta_str = leftUntilDone != 0 || eta != -1 ? etaToString(eta) : "Done";
auto const error_mark = tr_variantDictFindInt(d, TR_KEY_error, &error) && error ? '*' : ' ';
auto const done_str = sizeWhenDone != 0 ?
fmt::format(FMT_STRING("{:.0f}%"), (100.0 * (sizeWhenDone - leftUntilDone) / sizeWhenDone)) :
std::string{ "n/a" };
printf(
"%6d%c %4s %9s %-8s %6.1f %6.1f %5s %-11s %" TR_PRIsv "\n",
(int)torId,
errorMark,
doneStr,
error_mark,
done_str.c_str(),
strlsize(sizeWhenDone - leftUntilDone).c_str(),
etaStr,
eta_str.c_str(),
up / (double)tr_speed_K,
down / (double)tr_speed_K,
strlratio2(ratio).c_str(),
getStatusString(d, statusStr, sizeof(statusStr)),
getStatusString(d).c_str(),
TR_PRIsv_ARG(name));
total_up += up;
@ -1570,8 +1488,6 @@ static void printTorrentList(tr_variant* top)
static void printTrackersImpl(tr_variant* trackerStats)
{
char buf[512];
for (size_t i = 0, n = tr_variantListSize(trackerStats); i < n; ++i)
{
tr_variant* const t = tr_variantListChild(trackerStats, i);
@ -1641,11 +1557,11 @@ static void printTrackersImpl(tr_variant* trackerStats)
{
if (hasAnnounced && announceState != TR_TRACKER_INACTIVE)
{
tr_strltime(buf, now - lastAnnounceTime, sizeof(buf));
auto const timestr = tr_strltime(now - lastAnnounceTime);
if (lastAnnounceSucceeded)
{
printf(" Got a list of %d peers %s ago\n", (int)lastAnnouncePeerCount, buf);
printf(" Got a list of %d peers %s ago\n", (int)lastAnnouncePeerCount, timestr.c_str());
}
else if (lastAnnounceTimedOut)
{
@ -1653,7 +1569,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
}
else
{
printf(" Got an error \"%" TR_PRIsv "\" %s ago\n", TR_PRIsv_ARG(lastAnnounceResult), buf);
printf(" Got an error \"%" TR_PRIsv "\" %s ago\n", TR_PRIsv_ARG(lastAnnounceResult), timestr.c_str());
}
}
@ -1664,8 +1580,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
break;
case TR_TRACKER_WAITING:
tr_strltime(buf, nextAnnounceTime - now, sizeof(buf));
printf(" Asking for more peers in %s\n", buf);
printf(" Asking for more peers in %s\n", tr_strltime(nextAnnounceTime - now).c_str());
break;
case TR_TRACKER_QUEUED:
@ -1673,18 +1588,21 @@ static void printTrackersImpl(tr_variant* trackerStats)
break;
case TR_TRACKER_ACTIVE:
tr_strltime(buf, now - lastAnnounceStartTime, sizeof(buf));
printf(" Asking for more peers now... %s\n", buf);
printf(" Asking for more peers now... %s\n", tr_strltime(now - lastAnnounceStartTime).c_str());
break;
}
if (hasScraped)
{
tr_strltime(buf, now - lastScrapeTime, sizeof(buf));
auto const timestr = tr_strltime(now - lastScrapeTime);
if (lastScrapeSucceeded)
{
printf(" Tracker had %d seeders and %d leechers %s ago\n", (int)seederCount, (int)leecherCount, buf);
printf(
" Tracker had %d seeders and %d leechers %s ago\n",
(int)seederCount,
(int)leecherCount,
timestr.c_str());
}
else if (lastScrapeTimedOut)
{
@ -1692,7 +1610,10 @@ static void printTrackersImpl(tr_variant* trackerStats)
}
else
{
printf(" Got a scrape error \"%" TR_PRIsv "\" %s ago\n", TR_PRIsv_ARG(lastScrapeResult), buf);
printf(
" Got a scrape error \"%" TR_PRIsv "\" %s ago\n",
TR_PRIsv_ARG(lastScrapeResult),
timestr.c_str());
}
}
@ -1702,8 +1623,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
break;
case TR_TRACKER_WAITING:
tr_strltime(buf, nextScrapeTime - now, sizeof(buf));
printf(" Asking for peer counts in %s\n", buf);
printf(" Asking for peer counts in %s\n", tr_strltime(nextScrapeTime - now).c_str());
break;
case TR_TRACKER_QUEUED:
@ -1711,8 +1631,7 @@ static void printTrackersImpl(tr_variant* trackerStats)
break;
case TR_TRACKER_ACTIVE:
tr_strltime(buf, now - lastScrapeStartTime, sizeof(buf));
printf(" Asking for peer counts now... %s\n", buf);
printf(" Asking for peer counts now... %s\n", tr_strltime(now - lastScrapeStartTime).c_str());
break;
}
}
@ -1982,7 +1901,6 @@ static void printSessionStats(tr_variant* top)
if (tr_variantDictFindDict(top, TR_KEY_arguments, &args))
{
char buf[512];
int64_t up;
int64_t down;
int64_t secs;
@ -1995,7 +1913,7 @@ static void printSessionStats(tr_variant* top)
printf(" Uploaded: %s\n", strlsize(up).c_str());
printf(" Downloaded: %s\n", strlsize(down).c_str());
printf(" Ratio: %s\n", strlratio(up, down).c_str());
printf(" Duration: %s\n", tr_strltime(buf, secs, sizeof(buf)));
printf(" Duration: %s\n", tr_strltime(secs).c_str());
}
if (tr_variantDictFindDict(args, TR_KEY_cumulative_stats, &d) &&
@ -2007,7 +1925,7 @@ static void printSessionStats(tr_variant* top)
printf(" Uploaded: %s\n", strlsize(up).c_str());
printf(" Downloaded: %s\n", strlsize(down).c_str());
printf(" Ratio: %s\n", strlratio(up, down).c_str());
printf(" Duration: %s\n", tr_strltime(buf, secs, sizeof(buf)));
printf(" Duration: %s\n", tr_strltime(secs).c_str());
}
}
}
@ -2132,7 +2050,8 @@ static int processResponse(char const* rpcurl, std::string_view response)
if (tr_variantDictFindDict(&top, Arguments, &b) &&
tr_variantDictFindDict(b, TR_KEY_torrent_added, &b) && tr_variantDictFindInt(b, TR_KEY_id, &i))
{
tr_snprintf(id, sizeof(id), "%" PRId64, i);
auto const [out, len] = fmt::format_to_n(id, sizeof(id) - 1, FMT_STRING("{:d}"), i);
*out = '\0';
}
[[fallthrough]];
}
@ -2925,22 +2844,19 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
}
case 's': /* start */
if (tadd != nullptr)
{
if (tadd != nullptr)
{
tr_variantDictAddBool(tr_variantDictFind(tadd, TR_KEY_arguments), TR_KEY_paused, false);
}
else
{
auto* top = tr_new0(tr_variant, 1);
tr_variantInitDict(top, 2);
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-start"sv);
addIdArg(tr_variantDictAddDict(top, Arguments, 1), id, nullptr);
status |= flush(rpcurl, &top);
}
break;
tr_variantDictAddBool(tr_variantDictFind(tadd, TR_KEY_arguments), TR_KEY_paused, false);
}
else
{
auto* top = tr_new0(tr_variant, 1);
tr_variantInitDict(top, 2);
tr_variantDictAddStrView(top, TR_KEY_method, "torrent-start"sv);
addIdArg(tr_variantDictAddDict(top, Arguments, 1), id, nullptr);
status |= flush(rpcurl, &top);
}
break;
case 'S': /* stop */
if (tadd != nullptr)