1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-21 23:32:35 +00:00

feat: add tr_strvToBuf() (#3657)

* feat: add tr_getDefaultConfigDirToBuf()

* feat: add tr_getDefaultDownloadDirToBuf()

* feat: add tr_strvToBuf()

* feat: add tr_torrentFindFileToBuf()

* feat: add tr_torrentGetMagnetLinkToBuf()

* refactor: remove unused makeString() from tests

* feat: add tr_torrentFilenameToBuf()

* feat: add tr_torrentGetTrackerListToBuf()

* chore: remove obsolete comment references to tr_free

* chore: remove unused tr_strdup()

* chore: remove unused forward declarations
This commit is contained in:
Charles Kerr 2022-08-16 19:28:57 -05:00 committed by GitHub
parent 988d8ff9ac
commit e49747ab51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 193 additions and 305 deletions

View file

@ -173,10 +173,9 @@ static std::string getStatusStr(tr_stat const* st)
return "";
}
static char const* getConfigDir(int argc, char const** argv)
static std::string getConfigDir(int argc, char const** argv)
{
int c;
char const* configDir = nullptr;
char const* my_optarg;
int const ind = tr_optind;
@ -184,19 +183,14 @@ static char const* getConfigDir(int argc, char const** argv)
{
if (c == 'g')
{
configDir = my_optarg;
return my_optarg;
break;
}
}
tr_optind = ind;
if (configDir == nullptr)
{
configDir = tr_getDefaultConfigDir(MyConfigName);
}
return configDir;
return tr_getDefaultConfigDir(MyConfigName);
}
int tr_main(int argc, char* argv[])
@ -218,8 +212,8 @@ int tr_main(int argc, char* argv[])
/* load the defaults from config file + libtransmission defaults */
tr_variantInitDict(&settings, 0);
char const* const configDir = getConfigDir(argc, (char const**)argv);
tr_sessionLoadSettings(&settings, configDir, MyConfigName);
auto const config_dir = getConfigDir(argc, (char const**)argv);
tr_sessionLoadSettings(&settings, config_dir.c_str(), MyConfigName);
/* the command line overrides defaults */
if (parseCommandLine(&settings, argc, (char const**)argv) != 0)
@ -256,7 +250,7 @@ int tr_main(int argc, char* argv[])
}
}
auto* const h = tr_sessionInit(configDir, false, &settings);
auto* const h = tr_sessionInit(config_dir.c_str(), false, &settings);
auto* const ctor = tr_ctorNew(h);
tr_ctorSetPaused(ctor, TR_FORCE, false);
@ -353,7 +347,7 @@ int tr_main(int argc, char* argv[])
}
}
tr_sessionSaveSettings(h, configDir, &settings);
tr_sessionSaveSettings(h, config_dir.c_str(), &settings);
printf("\n");
tr_variantFree(&settings);

View file

@ -202,10 +202,9 @@ static bool reopen_log_file(char const* filename)
return true;
}
static char const* getConfigDir(int argc, char const* const* argv)
static std::string getConfigDir(int argc, char const* const* argv)
{
int c;
char const* configDir = nullptr;
char const* optstr;
int const ind = tr_optind;
@ -213,19 +212,13 @@ static char const* getConfigDir(int argc, char const* const* argv)
{
if (c == 'g')
{
configDir = optstr;
break;
return optstr;
}
}
tr_optind = ind;
if (configDir == nullptr)
{
configDir = tr_getDefaultConfigDir(MyName);
}
return configDir;
return tr_getDefaultConfigDir(MyName);
}
static auto onFileAdded(tr_session* session, std::string_view dirname, std::string_view basename)
@ -671,7 +664,7 @@ static bool parse_args(
struct daemon_data
{
tr_variant settings;
char const* configDir;
std::string config_dir;
bool paused;
};
@ -719,7 +712,7 @@ static int daemon_start(void* varg, [[maybe_unused]] bool foreground)
auto* arg = static_cast<daemon_data*>(varg);
tr_variant* const settings = &arg->settings;
char const* const configDir = arg->configDir;
char const* const config_dir = arg->config_dir.c_str();
sd_notifyf(0, "MAINPID=%d\n", (int)getpid());
@ -744,10 +737,10 @@ static int daemon_start(void* varg, [[maybe_unused]] bool foreground)
tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr);
tr_formatter_size_init(DiskK, DiskKStr, DiskMStr, DiskGStr, DiskTStr);
tr_formatter_speed_init(SpeedK, SpeedKStr, SpeedMStr, SpeedGStr, SpeedTStr);
session = tr_sessionInit(configDir, true, settings);
session = tr_sessionInit(config_dir, true, settings);
tr_sessionSetRPCCallback(session, on_rpc_callback, nullptr);
tr_logAddInfo(fmt::format(_("Loading settings from '{path}'"), fmt::arg("path", configDir)));
tr_sessionSaveSettings(session, configDir, settings);
tr_logAddInfo(fmt::format(_("Loading settings from '{path}'"), fmt::arg("path", config_dir)));
tr_sessionSaveSettings(session, config_dir, settings);
auto sv = std::string_view{};
(void)tr_variantDictFindStrView(settings, key_pidfile, &sv);
@ -893,7 +886,7 @@ CLEANUP:
event_base_free(ev_base);
tr_sessionSaveSettings(mySession, configDir, settings);
tr_sessionSaveSettings(mySession, config_dir, settings);
tr_sessionClose(mySession);
pumpLogMessages(logfile);
printf(" done.\n");
@ -922,12 +915,12 @@ CLEANUP:
static bool init_daemon_data(int argc, char* argv[], struct daemon_data* data, bool* foreground, int* ret)
{
data->configDir = getConfigDir(argc, (char const* const*)argv);
data->config_dir = getConfigDir(argc, (char const* const*)argv);
/* load settings from defaults + config file */
tr_variantInitDict(&data->settings, 0);
tr_variantDictAddBool(&data->settings, TR_KEY_rpc_enabled, true);
bool const loaded = tr_sessionLoadSettings(&data->settings, data->configDir, MyName);
bool const loaded = tr_sessionLoadSettings(&data->settings, data->config_dir.c_str(), MyName);
bool dumpSettings;

View file

@ -1382,7 +1382,7 @@ tr_torrent* Application::Impl::get_first_selected_torrent() const
void Application::Impl::copy_magnet_link_to_clipboard(tr_torrent* tor) const
{
char* magnet = tr_torrentGetMagnetLink(tor);
auto const magnet = tr_torrentGetMagnetLink(tor);
auto const display = wind_->get_display();
GdkAtom selection;
Glib::RefPtr<Gtk::Clipboard> clipboard;
@ -1396,9 +1396,6 @@ void Application::Impl::copy_magnet_link_to_clipboard(tr_torrent* tor) const
selection = GDK_SELECTION_PRIMARY;
clipboard = Gtk::Clipboard::get_for_display(display, selection);
clipboard->set_text(magnet);
/* cleanup */
tr_free(magnet);
}
void gtr_actions_handler(Glib::ustring const& action_name, gpointer user_data)

View file

@ -22,7 +22,7 @@
#include <fmt/format.h>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> /* tr_free */
#include <libtransmission/utils.h>
#include <libtransmission/web-utils.h>
#include "Actions.h"
@ -2299,19 +2299,6 @@ void DetailsDialog::Impl::on_edit_trackers_response(int response, std::shared_pt
}
}
namespace
{
std::string get_editable_tracker_list(tr_torrent const* tor)
{
char* cstr = tr_torrentGetTrackerList(tor);
auto str = std::string{ cstr != nullptr ? cstr : "" };
tr_free(cstr);
return str;
}
} // namespace
void DetailsDialog::Impl::on_edit_trackers()
{
tr_torrent const* tor = tracker_list_get_current_torrent();
@ -2343,7 +2330,7 @@ void DetailsDialog::Impl::on_edit_trackers()
t->add_wide_control(row, *l);
auto* w = Gtk::make_managed<Gtk::TextView>();
w->get_buffer()->set_text(get_editable_tracker_list(tor));
w->get_buffer()->set_text(tr_torrentGetTrackerList(tor));
auto* fr = Gtk::make_managed<Gtk::Frame>();
fr->set_shadow_type(Gtk::SHADOW_IN);
auto* sw = Gtk::make_managed<Gtk::ScrolledWindow>();

View file

@ -49,9 +49,7 @@ static void tr_prefs_init_defaults(tr_variant* d)
if (dir.empty())
{
auto* const tmp = tr_getDefaultDownloadDir();
dir = tmp;
tr_free(tmp);
dir = tr_getDefaultDownloadDir();
}
tr_variantDictReserve(d, 31);

View file

@ -96,9 +96,7 @@ int main(int argc, char** argv)
/* set up the config dir */
if (std::empty(config_dir))
{
auto* const default_config_dir = tr_getDefaultConfigDir(AppConfigDirName);
config_dir = default_config_dir;
tr_free(default_config_dir);
config_dir = tr_getDefaultConfigDir(AppConfigDirName);
}
gtr_pref_init(config_dir);

View file

@ -110,40 +110,45 @@ static std::string xdgConfigHome()
return fmt::format("{:s}/.config"sv, getHomeDir());
}
char* tr_getDefaultConfigDir(char const* appname)
std::string tr_getDefaultConfigDir(std::string_view appname)
{
if (auto dir = tr_env_get_string("TRANSMISSION_HOME"sv); !std::empty(dir))
if (std::empty(appname))
{
return tr_strvDup(dir);
appname = "Transmission"sv;
}
if (tr_str_is_empty(appname))
if (auto dir = tr_env_get_string("TRANSMISSION_HOME"sv); !std::empty(dir))
{
appname = "Transmission";
return dir;
}
#ifdef __APPLE__
return tr_strvDup(fmt::format("{:s}/Library/Application Support/{:s}"sv, getHomeDir(), appname));
return fmt::format("{:s}/Library/Application Support/{:s}"sv, getHomeDir(), appname);
#elif defined(_WIN32)
auto const appdata = win32_get_known_folder(FOLDERID_LocalAppData);
return tr_strvDup(fmt::format("{:s}/{:s}"sv, appdata, appname));
return fmt::format("{:s}/{:s}"sv, appdata, appname);
#elif defined(__HAIKU__)
char buf[PATH_MAX];
find_directory(B_USER_SETTINGS_DIRECTORY, -1, true, buf, sizeof(buf));
return tr_strvDup(fmt::format("{:s}/{:s}"sv, buf, appname);
return fmt::format("{:s}/{:s}"sv, buf, appname);
#else
return tr_strvDup(fmt::format("{:s}/{:s}"sv, xdgConfigHome(), appname));
return fmt::format("{:s}/{:s}"sv, xdgConfigHome(), appname);
#endif
}
size_t tr_getDefaultConfigDirToBuf(char const* appname, char* buf, size_t buflen)
{
return tr_strvToBuf(tr_getDefaultConfigDir(appname != nullptr ? appname : ""), buf, buflen);
}
static std::string getXdgEntryFromUserDirs(std::string_view key)
{
auto content = std::vector<char>{};
@ -178,25 +183,30 @@ static std::string getXdgEntryFromUserDirs(std::string_view key)
return val;
}
char* tr_getDefaultDownloadDir()
std::string tr_getDefaultDownloadDir()
{
if (auto const dir = getXdgEntryFromUserDirs("XDG_DOWNLOAD_DIR"sv); !std::empty(dir))
if (auto dir = getXdgEntryFromUserDirs("XDG_DOWNLOAD_DIR"sv); !std::empty(dir))
{
return tr_strvDup(dir);
return dir;
}
#ifdef _WIN32
if (auto dir = win32_get_known_folder(FOLDERID_Downloads); !std::empty(dir))
{
return tr_strvDup(dir);
return dir;
}
#endif
#ifdef __HAIKU__
return tr_strvDup(fmt::format("{:s}/Desktop"sv, getHomeDir()));
return fmt::format("{:s}/Desktop"sv, getHomeDir());
#endif
return tr_strvDup(fmt::format("{:s}/Downloads"sv, getHomeDir()));
return fmt::format("{:s}/Downloads"sv, getHomeDir());
}
size_t tr_getDefaultDownloadDirToBuf(char* buf, size_t buflen)
{
return tr_strvToBuf(tr_getDefaultDownloadDir(), buf, buflen);
}
/***

View file

@ -296,7 +296,7 @@ tr_session::PublicAddressResult tr_session::publicAddress(tr_address_type type)
void tr_sessionGetDefaultSettings(tr_variant* setme_dictionary)
{
auto* const download_dir = tr_getDefaultDownloadDir();
auto const download_dir = tr_getDefaultDownloadDir();
auto* const d = setme_dictionary;
TR_ASSERT(tr_variantIsDict(d));
@ -376,8 +376,6 @@ void tr_sessionGetDefaultSettings(tr_variant* setme_dictionary)
tr_variantDictAddBool(d, TR_KEY_anti_brute_force_enabled, true);
tr_variantDictAddStrView(d, TR_KEY_announce_ip, "");
tr_variantDictAddBool(d, TR_KEY_announce_ip_enabled, false);
tr_free(download_dir);
}
void tr_sessionGetSettings(tr_session const* s, tr_variant* setme_dictionary)
@ -469,9 +467,8 @@ static void getSettingsFilename(tr_pathbuf& setme, char const* config_dir, char
return;
}
auto* const default_config_dir = tr_getDefaultConfigDir(appname);
auto const default_config_dir = tr_getDefaultConfigDir(appname);
setme.assign(std::string_view{ default_config_dir }, "/settings.json"sv);
tr_free(default_config_dir);
}
bool tr_sessionLoadSettings(tr_variant* dict, char const* config_dir, char const* appName)

View file

@ -414,7 +414,12 @@ double tr_torrentGetMetadataPercent(tr_torrent const* tor)
return m == nullptr || m->piece_count == 0 ? 0.0 : (m->piece_count - std::size(m->pieces_needed)) / (double)m->piece_count;
}
char* tr_torrentGetMagnetLink(tr_torrent const* tor)
std::string tr_torrentGetMagnetLink(tr_torrent const* tor)
{
return tr_strvDup(tor->metainfo_.magnet());
return std::string{ tor->metainfo_.magnet().sv() };
}
size_t tr_torrentGetMagnetLinkToBuf(tr_torrent const* tor, char* buf, size_t buflen)
{
return tr_strvToBuf(tr_torrentGetMagnetLink(tor), buf, buflen);
}

View file

@ -30,108 +30,6 @@
using namespace std::literals;
//// C BINDINGS
#if 0
/// Lifecycle
tr_torrent_metainfo* tr_torrentMetainfoNewFromData(char const* data, size_t data_len, struct tr_error** error)
{
auto* tm = new tr_torrent_metainfo{};
if (!tm->parseBenc(std::string_view{ data, data_len }, error))
{
delete tm;
return nullptr;
}
return tm;
}
tr_torrent_metainfo* tr_torrentMetainfoNewFromFile(char const* filename, struct tr_error** error)
{
auto* tm = new tr_torrent_metainfo{};
if (!tm->parseBencFromFile(filename ? filename : "", nullptr, error))
{
delete tm;
return nullptr;
}
return tm;
}
void tr_torrentMetainfoFree(tr_torrent_metainfo* tm)
{
delete tm;
}
//// Accessors
char* tr_torrentMetainfoMagnet(struct tr_torrent_metainfo const* tm)
{
return tr_strvDup(tm->magnet());
}
/// Info
tr_torrent_metainfo_info* tr_torrentMetainfoGet(tr_torrent_metainfo const* tm, tr_torrent_metainfo_info* setme)
{
setme->comment = tm->comment.c_str();
setme->creator = tm->creator.c_str();
setme->info_hash = tm->info_hash;
setme->info_hash_string = std::data(tm->info_hash_chars);
setme->is_private = tm->is_private;
setme->n_pieces = tm->n_pieces;
setme->name = tm->name.c_str();
setme->source = tm->source.c_str();
setme->time_created = tm->time_created;
setme->total_size = tm->total_size;
return setme;
}
/// Files
size_t tr_torrentMetainfoFileCount(tr_torrent_metainfo const* tm)
{
return std::size(tm->files);
}
tr_torrent_metainfo_file_info* tr_torrentMetainfoFile(
tr_torrent_metainfo const* tm,
size_t n,
tr_torrent_metainfo_file_info* setme)
{
auto& file = tm->files[n];
setme->path = file.path.c_str();
setme->size = file.size;
return setme;
}
/// Trackers
size_t tr_torrentMetainfoTrackerCount(tr_torrent_metainfo const* tm)
{
return std::size(tm->trackers);
}
tr_torrent_metainfo_tracker_info* tr_torrentMetainfoTracker(
tr_torrent_metainfo const* tm,
size_t n,
tr_torrent_metainfo_tracker_info* setme)
{
auto it = std::begin(tm->trackers);
std::advance(it, n);
auto const& tracker = it->second;
setme->announce_url = tr_quark_get_string(tracker.announce_url);
setme->scrape_url = tr_quark_get_string(tracker.scrape_url);
setme->tier = tracker.tier;
return setme;
}
#endif
/***
****
***/
/**
* @brief Ensure that the URLs for multfile torrents end in a slash.
*

View file

@ -1243,9 +1243,14 @@ tr_torrent_view tr_torrentView(tr_torrent const* tor)
return ret;
}
char* tr_torrentFilename(tr_torrent const* tor)
std::string tr_torrentFilename(tr_torrent const* tor)
{
return tr_strvDup(tor->torrentFile());
return std::string{ tor->torrentFile() };
}
size_t tr_torrentFilenameToBuf(tr_torrent const* tor, char* buf, size_t buflen)
{
return tr_strvToBuf(tr_torrentFilename(tor), buf, buflen);
}
/***
@ -2058,9 +2063,14 @@ bool tr_torrentSetTrackerList(tr_torrent* tor, char const* text)
return text != nullptr && tor->setTrackerList(text);
}
char* tr_torrentGetTrackerList(tr_torrent const* tor)
std::string tr_torrentGetTrackerList(tr_torrent const* tor)
{
return tr_strvDup(tor->trackerList());
return tor->trackerList();
}
size_t tr_torrentGetTrackerListToBuf(tr_torrent const* tor, char* buf, size_t buflen)
{
return tr_strvToBuf(tr_torrentGetTrackerList(tor), buf, buflen);
}
/**
@ -2310,11 +2320,15 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
****
***/
// TODO: clients that call this should call tr_torrent::findFile() instead
char* tr_torrentFindFile(tr_torrent const* tor, tr_file_index_t fileNum)
std::string tr_torrentFindFile(tr_torrent const* tor, tr_file_index_t file_num)
{
auto const found = tor->findFile(fileNum);
return found ? tr_strdup(found->filename()) : nullptr;
auto const found = tor->findFile(file_num);
return std::string{ found ? found->filename().sv() : ""sv };
}
size_t tr_torrentFindFileToBuf(tr_torrent const* tor, tr_file_index_t file_num, char* buf, size_t buflen)
{
return tr_strvToBuf(tr_torrentFindFile(tor, file_num), buf, buflen);
}
// decide whether we should be looking for files in downloadDir or incompleteDir

View file

@ -15,9 +15,7 @@
#pragma once
/***
****
**** Basic Types
****
***/
#include <stdbool.h> /* bool */
@ -25,6 +23,11 @@
#include <stdint.h> /* uintN_t */
#include <time.h> /* time_t */
#ifdef __cplusplus
#include <string>
#include <string_view>
#endif
#include "tr-macros.h"
using tr_file_index_t = uint32_t;
@ -49,8 +52,6 @@ struct tr_byte_span_t
uint64_t end;
};
class tr_announce_list;
struct tr_ctor;
struct tr_error;
struct tr_session;
@ -97,9 +98,7 @@ enum tr_encryption_mode
*/
/**
* @brief returns Transmission's default configuration file directory.
*
* Use tr_free() to free the string when done.
* @brief get Transmission's default configuration file directory.
*
* The default configuration directory is determined this way:
* -# If the TRANSMISSION_HOME environment variable is set, its value is used.
@ -108,19 +107,27 @@ enum tr_encryption_mode
* -# If XDG_CONFIG_HOME is set, "${XDG_CONFIG_HOME}/${appname}" is used.
* -# ${HOME}/.config/${appname}" is used as a last resort.
*/
char* tr_getDefaultConfigDir(char const* appname);
#ifdef __cplusplus
[[nodiscard]] std::string tr_getDefaultConfigDir(std::string_view appname);
#endif
/** @brief buffer variant of tr_getDefaultConfigDir(). See tr_strvToBuf(). */
size_t tr_getDefaultConfigDirToBuf(char const* appname, char* buf, size_t buflen);
/**
* @brief returns Transmisson's default download directory.
*
* Use tr_free() to free the string when done.
*
* The default download directory is determined this way:
* -# If the HOME environment variable is set, "${HOME}/Downloads" is used.
* -# On Windows, "${CSIDL_MYDOCUMENTS}/Downloads" is used.
* -# Otherwise, getpwuid(getuid())->pw_dir + "/Downloads" is used.
*/
char* tr_getDefaultDownloadDir();
#ifdef __cplusplus
[[nodiscard]] std::string tr_getDefaultDownloadDir();
#endif
/** @brief buffer variant of tr_getDefaultDownloadDir(). See tr_strvToBuf(). */
size_t tr_getDefaultDownloadDirToBuf(char* buf, size_t buflen);
#define TR_DEFAULT_BIND_ADDRESS_IPV4 "0.0.0.0"
#define TR_DEFAULT_BIND_ADDRESS_IPV6 "::"
@ -1010,13 +1017,16 @@ uint64_t tr_torrentTotalSize(tr_torrent const*);
/**
* @brief find the location of a torrent's file by looking with and without
* the ".part" suffix, looking in downloadDir and incompleteDir, etc.
* @return a newly-allocated string (that must be tr_free()d by the caller
* when done) that gives the location of this file on disk,
* or nullptr if no file exists yet.
* @return the path of this file, or an empty string if no file exists yet.
* @param tor the torrent whose file we're looking for
* @param fileNum the fileIndex, in [0...tr_torrentFileCount())
*/
char* tr_torrentFindFile(tr_torrent const* tor, tr_file_index_t fileNum);
#ifdef __cplusplus
[[nodiscard]] std::string tr_torrentFindFile(tr_torrent const* tor, tr_file_index_t file_num);
#endif
/** @brief buffer variant of tr_torrentFindFile(). See tr_strvToBuf(). */
size_t tr_torrentFindFileToBuf(tr_torrent const* tor, tr_file_index_t file_num, char* buf, size_t buflen);
/***
**** Torrent speed limits
@ -1130,17 +1140,21 @@ char const* tr_torrentGetDownloadDir(tr_torrent const* torrent);
char const* tr_torrentGetCurrentDir(tr_torrent const* tor);
/**
* Returns a newly-allocated string with a magnet link of the torrent.
* Use tr_free() to free the string when done.
* Returns a the magnet link to the torrent.
*/
char* tr_torrentGetMagnetLink(tr_torrent const* tor);
#ifdef __cplusplus
[[nodiscard]] std::string tr_torrentGetMagnetLink(tr_torrent const* tor);
#endif
/** @brief buffer variant of tr_torrentGetMagnetLink(). See tr_strvToBuf(). */
size_t tr_torrentGetMagnetLinkToBuf(tr_torrent const* tor, char* buf, size_t buflen);
/**
***
**/
/**
* Returns a newly-allocated string listing its tracker's announce URLs.
* Returns a string listing its tracker's announce URLs.
* One URL per line, with a blank line between tiers.
*
* NOTE: this only includes the trackers included in the torrent and,
@ -1149,7 +1163,12 @@ char* tr_torrentGetMagnetLink(tr_torrent const* tor);
* are applied to all public torrents. If you want a full display of all
* trackers, use tr_torrentTracker() and tr_torrentTrackerCount()
*/
char* tr_torrentGetTrackerList(tr_torrent const* tor);
#ifdef __cplusplus
[[nodiscard]] std::string tr_torrentGetTrackerList(tr_torrent const* tor);
#endif
/** @brief buffer variant of tr_torrentGetTrackerList(). See tr_strvToBuf(). */
size_t tr_torrentGetTrackerListToBuf(tr_torrent const* tor, char* buf, size_t buflen);
/**
* Sets a torrent's tracker list from a list of announce URLs with one
@ -1436,9 +1455,13 @@ struct tr_torrent_view tr_torrentView(tr_torrent const* tor);
/*
* Get the filename of Transmission's internal copy of the torrent file.
* This is a duplicate that must be freed with tr_free() when done.
*/
char* tr_torrentFilename(tr_torrent const* tor);
#ifdef __cplusplus
[[nodiscard]] std::string tr_torrentFilename(tr_torrent const* tor);
#endif
/** @brief buffer variant of tr_torrentFilename(). See tr_strvToBuf(). */
size_t tr_torrentFilenameToBuf(tr_torrent const* tor, char* buf, size_t buflen);
/***********************************************************************
* tr_torrentAvailability
@ -1475,7 +1498,6 @@ enum tr_torrent_activity
TR_STATUS_SEED_WAIT = 5, /* Queued to seed */
TR_STATUS_SEED = 6 /* Seeding */
};
enum
{
TR_PEER_FROM_INCOMING = 0, /* connections made to the listening port */

View file

@ -217,9 +217,21 @@ char* tr_strvDup(std::string_view in)
return ret;
}
char* tr_strdup(void const* in)
size_t tr_strvToBuf(std::string_view src, char* buf, size_t buflen)
{
return in == nullptr ? nullptr : tr_strvDup(static_cast<char const*>(in));
size_t const len = std::size(src);
if (buflen >= len)
{
auto const out = std::copy(std::begin(src), std::end(src), buf);
if (buflen > len)
{
*out = '\0';
}
}
return len;
}
extern "C"
@ -625,7 +637,6 @@ static bool parseNumberSection(std::string_view str, number_range& range)
* Given a string like "1-4" or "1-4,6,9,14-51", this allocates and returns an
* array of setmeCount ints of all the values in the array.
* For example, "5-8" will return [ 5, 6, 7, 8 ] and setmeCount will be 4.
* It's the caller's responsibility to call tr_free () on the returned array.
* If a fragment of the string can't be parsed, nullptr is returned.
*/
std::vector<int> tr_parseNumberRange(std::string_view str)

View file

@ -141,13 +141,6 @@ void tr_free(void* p);
#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 string
* @param in is a void* so that callers can pass in both signed & unsigned without a cast
* @return a newly-allocated copy of `in' that can be freed with tr_free()
*/
[[nodiscard]] char* tr_strdup(void const* in);
constexpr bool tr_str_is_empty(char const* value)
{
return value == nullptr || *value == '\0';
@ -236,6 +229,15 @@ constexpr bool tr_strvSep(std::string_view* sv, std::string_view* token, char de
std::string& tr_strvUtf8Clean(std::string_view cleanme, std::string& setme);
/**
* @brief copies `src` into `buf`.
*
* - Always returns std::size(src).
* - `src` will be copied into `buf` iff `buflen >= std::size(src)`
* - `buf` will also be zero terminated iff `buflen >= std::size(src) + 1`.
*/
size_t tr_strvToBuf(std::string_view src, char* buf, size_t buflen);
/***
****
***/
@ -247,8 +249,7 @@ std::string& tr_strvUtf8Clean(std::string_view cleanme, std::string& setme);
/**
* @brief Given a string like "1-4" or "1-4,6,9,14-51", this returns a
* newly-allocated array of all the integers in the set.
* @return a newly-allocated array of integers that must be freed with tr_free(),
* or nullptr if a fragment of the string can't be parsed.
* @return a vector of integers, which is empty if the string can't be parsed.
*
* For example, "5-8" will return [ 5, 6, 7, 8 ] and setmeCount will be 4.
*/

View file

@ -563,11 +563,10 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
tr_formatter_mem_init(1000, kbString.UTF8String, mbString.UTF8String, gbString.UTF8String, tbString.UTF8String);
char* const default_config_dir = tr_getDefaultConfigDir("Transmission");
_fLib = tr_sessionInit(default_config_dir, YES, &settings);
auto const default_config_dir = tr_getDefaultConfigDir("Transmission");
_fLib = tr_sessionInit(default_config_dir.c_str(), YES, &settings);
tr_variantFree(&settings);
_fConfigDirectory = @(default_config_dir);
tr_free(default_config_dir);
_fConfigDirectory = @(default_config_dir.c_str());
tr_sessionSetIdleLimitHitCallback(_fLib, onIdleLimitHit, (__bridge void*)(self));
tr_sessionSetQueueStartCallback(_fLib, onStartQueue, (__bridge void*)(self));

View file

@ -11,7 +11,7 @@
#include <libtransmission/error.h>
#include <libtransmission/log.h>
#include <libtransmission/utils.h> // tr_free()
#include <libtransmission/utils.h>
#import "Torrent.h"
#import "GroupsController.h"
@ -361,7 +361,7 @@ bool trashDataFile(char const* filename, tr_error** error)
- (NSString*)magnetLink
{
return @(tr_torrentGetMagnetLink(self.fHandle));
return @(tr_torrentGetMagnetLink(self.fHandle).c_str());
}
- (CGFloat)ratio
@ -682,10 +682,9 @@ bool trashDataFile(char const* filename, tr_error** error)
new_tracker = [@"http://" stringByAppendingString:new_tracker];
}
char* old_list = tr_torrentGetTrackerList(self.fHandle);
auto const old_list = tr_torrentGetTrackerList(self.fHandle);
auto const new_list = fmt::format(FMT_STRING("{:s}\n\n{:s}"), old_list, new_tracker.UTF8String);
BOOL const success = tr_torrentSetTrackerList(self.fHandle, new_list.c_str());
tr_free(old_list);
return success;
}
@ -759,10 +758,7 @@ bool trashDataFile(char const* filename, tr_error** error)
- (NSString*)torrentLocation
{
auto* const filename = tr_torrentFilename(self.fHandle);
NSString* ret = @(filename ? filename : "");
tr_free(filename);
return ret;
return @(tr_torrentFilename(self.fHandle).c_str());
}
- (NSString*)dataLocation
@ -785,16 +781,8 @@ bool trashDataFile(char const* filename, tr_error** error)
}
else
{
char* location = tr_torrentFindFile(self.fHandle, 0);
if (location == NULL)
{
return nil;
}
NSString* dataLocation = @(location);
free(location);
return dataLocation;
auto const location = tr_torrentFindFile(self.fHandle, 0);
return std::empty(location) ? nil : @(location.c_str());
}
}
@ -814,16 +802,8 @@ bool trashDataFile(char const* filename, tr_error** error)
}
else
{
char* location = tr_torrentFindFile(self.fHandle, node.indexes.firstIndex);
if (location == NULL)
{
return nil;
}
NSString* dataLocation = @(location);
free(location);
return dataLocation;
auto const location = tr_torrentFindFile(self.fHandle, node.indexes.firstIndex);
return std::empty(location) ? nil : @(location.c_str());
}
}

View file

@ -220,9 +220,7 @@ Application::Application(int& argc, char** argv)
// set the fallback config dir
if (config_dir.isNull())
{
auto* const default_config_dir = tr_getDefaultConfigDir("transmission");
config_dir = QString::fromUtf8(default_config_dir);
tr_free(default_config_dir);
config_dir = QString::fromStdString(tr_getDefaultConfigDir("transmission"));
}
// ensure our config directory exists

View file

@ -432,7 +432,7 @@ void Prefs::initDefaults(tr_variant* d) const
auto constexpr StatsMode = std::string_view{ "total-ratio" };
auto constexpr WindowLayout = std::string_view{ "menu,toolbar,filter,list,statusbar" };
auto* const download_dir = tr_getDefaultDownloadDir();
auto const download_dir = tr_getDefaultDownloadDir();
tr_variantDictReserve(d, 38);
dictAdd(d, TR_KEY_blocklist_updates_enabled, true);
@ -462,7 +462,7 @@ void Prefs::initDefaults(tr_variant* d) const
dictAdd(d, TR_KEY_main_window_x, 50);
dictAdd(d, TR_KEY_main_window_y, 50);
dictAdd(d, TR_KEY_remote_session_port, TR_DEFAULT_RPC_PORT);
dictAdd(d, TR_KEY_download_dir, std::string_view{ download_dir });
dictAdd(d, TR_KEY_download_dir, download_dir);
dictAdd(d, TR_KEY_filter_mode, FilterMode);
dictAdd(d, TR_KEY_main_window_layout_order, WindowLayout);
dictAdd(d, TR_KEY_open_dialog_dir, QDir::home().absolutePath());
@ -471,10 +471,8 @@ void Prefs::initDefaults(tr_variant* d) const
dictAdd(d, TR_KEY_remote_session_username, SessionUsername);
dictAdd(d, TR_KEY_sort_mode, SortMode);
dictAdd(d, TR_KEY_statusbar_stats, StatsMode);
dictAdd(d, TR_KEY_watch_dir, std::string_view{ download_dir });
dictAdd(d, TR_KEY_watch_dir, download_dir);
dictAdd(d, TR_KEY_read_clipboard, false);
tr_free(download_dir);
}
/***

View file

@ -60,9 +60,9 @@ TEST_P(IncompleteDirTest, incompleteDir)
auto path = tr_pathbuf{};
path.assign(incomplete_dir, '/', tr_torrentFile(tor, 0).name, tr_torrent_files::PartialFileSuffix);
EXPECT_EQ(path, makeString(tr_torrentFindFile(tor, 0)));
EXPECT_EQ(path, tr_torrentFindFile(tor, 0));
path.assign(incomplete_dir, '/', tr_torrentFile(tor, 1).name);
EXPECT_EQ(path, makeString(tr_torrentFindFile(tor, 1)));
EXPECT_EQ(path, tr_torrentFindFile(tor, 1));
EXPECT_EQ(tor->pieceSize(), tr_torrentStat(tor)->leftUntilDone);
// auto constexpr completeness_unset = tr_completeness { -1 };
@ -129,7 +129,7 @@ TEST_P(IncompleteDirTest, incompleteDir)
for (tr_file_index_t i = 0; i < n; ++i)
{
auto const expected = tr_pathbuf{ download_dir, '/', tr_torrentFile(tor, i).name };
EXPECT_EQ(expected, makeString(tr_torrentFindFile(tor, i)));
EXPECT_EQ(expected, tr_torrentFindFile(tor, i));
}
// cleanup
@ -183,7 +183,7 @@ TEST_F(MoveTest, setLocation)
for (tr_file_index_t i = 0; i < n; ++i)
{
auto const expected = tr_pathbuf{ target_dir, '/', tr_torrentFile(tor, i).name };
EXPECT_EQ(expected, makeString(tr_torrentFindFile(tor, i)));
EXPECT_EQ(expected, tr_torrentFindFile(tor, i));
}
// cleanup

View file

@ -15,7 +15,6 @@
using namespace std::literals;
using PlatformTest = ::libtransmission::test::SessionTest;
using ::libtransmission::test::makeString;
#ifdef _WIN32
#include <windows.h>
@ -28,8 +27,8 @@ TEST_F(PlatformTest, defaultDownloadDirXdg)
setenv("HOME", sandboxDir().c_str(), 1);
setenv("XDG_CONFIG_HOME", LIBTRANSMISSION_TEST_ASSETS_DIR, 1);
auto actual = makeString(tr_getDefaultDownloadDir());
auto expected = fmt::format("{:s}/UserDirsDownloads"sv, sandboxDir());
auto const expected = fmt::format("{:s}/UserDirsDownloads"sv, sandboxDir());
auto const actual = tr_getDefaultDownloadDir();
EXPECT_EQ(expected, actual);
unsetenv("XDG_CONFIG_HOME");
@ -41,8 +40,8 @@ TEST_F(PlatformTest, defaultDownloadDir)
{
setenv("HOME", sandboxDir().c_str(), 1);
auto expected = fmt::format("{:s}/Downloads"sv, sandboxDir());
auto actual = makeString(tr_getDefaultDownloadDir());
auto const expected = fmt::format("{:s}/Downloads"sv, sandboxDir());
auto const actual = tr_getDefaultDownloadDir();
EXPECT_EQ(expected, actual);
unsetenv("HOME");
@ -53,8 +52,8 @@ TEST_F(PlatformTest, defaultConfigDirEnv)
{
setenv("TRANSMISSION_HOME", sandboxDir().c_str(), 1);
auto actual = makeString(tr_getDefaultConfigDir("appname"));
auto expected = sandboxDir();
auto const expected = sandboxDir();
auto const actual = tr_getDefaultConfigDir("appname");
EXPECT_EQ(expected, actual);
unsetenv("TRANSMISSION_HOME");
@ -66,8 +65,8 @@ TEST_F(PlatformTest, defaultConfigDirXdgConfig)
{
setenv("XDG_CONFIG_HOME", sandboxDir().c_str(), 1);
auto expected = fmt::format("{:s}/appname", sandboxDir());
auto actual = makeString(tr_getDefaultConfigDir("appname"));
auto const expected = fmt::format("{:s}/appname", sandboxDir());
auto const actual = tr_getDefaultConfigDir("appname");
EXPECT_EQ(expected, actual);
unsetenv("XDG_CONFIG_HOME");
@ -78,8 +77,8 @@ TEST_F(PlatformTest, defaultConfigDirXdgConfigHome)
auto const home = tr_pathbuf{ sandboxDir(), "/home/user" };
setenv("HOME", home, 1);
auto expected = fmt::format("{:s}/.config/appname", home.sv());
auto actual = makeString(tr_getDefaultConfigDir("appname"));
auto const expected = fmt::format("{:s}/.config/appname", home.sv());
auto const actual = tr_getDefaultConfigDir("appname");
EXPECT_EQ(expected, actual);
unsetenv("HOME");

View file

@ -189,9 +189,8 @@ TEST_F(RenameTest, singleFilenameTorrent)
EXPECT_FALSE(tr_sys_path_exists(tmpstr)); // confirm the old filename can't be found
EXPECT_STREQ("foobar", tr_torrentName(tor)); // confirm the torrent's name is now 'foobar'
EXPECT_STREQ("foobar", tr_torrentFile(tor, 0).name); // confirm the file's name is now 'foobar'
char* const torrent_filename = tr_torrentFilename(tor);
EXPECT_STREQ(nullptr, strstr(torrent_filename, "foobar")); // confirm torrent file hasn't changed
tr_free(torrent_filename);
auto const torrent_filename = tr_torrentFilename(tor);
EXPECT_EQ(std::string::npos, torrent_filename.find("foobar")); // confirm torrent file hasn't changed
tmpstr.assign(tor->currentDir(), "/foobar");
EXPECT_TRUE(tr_sys_path_exists(tmpstr)); // confirm the file's name is now 'foobar' on the disk
EXPECT_TRUE(testFileExistsAndConsistsOfThisString(tor, 0, "hello, world!\n")); // confirm the contents are right
@ -228,7 +227,6 @@ TEST_F(RenameTest, singleFilenameTorrent)
TEST_F(RenameTest, multifileTorrent)
{
char* str;
auto constexpr TotalSize = size_t{ 67 };
auto constexpr ExpectedFiles = std::array<std::string_view, 4>{
"Felidae/Felinae/Acinonyx/Cheetah/Chester"sv,
@ -332,15 +330,13 @@ TEST_F(RenameTest, multifileTorrent)
***/
// remove the directory Felidae/Felinae/Felis/catus
str = tr_torrentFindFile(tor, 1);
EXPECT_NE(nullptr, str);
auto str = tr_torrentFindFile(tor, 1);
EXPECT_NE(""sv, str);
tr_sys_path_remove(str);
tr_free(str);
str = tr_torrentFindFile(tor, 2);
EXPECT_NE(nullptr, str);
EXPECT_NE(""sv, str);
tr_sys_path_remove(str);
tr_sys_path_remove(std::string{ tr_sys_path_dirname(str) });
tr_free(str);
sync();
blockingTorrentVerify(tor);
testFileExistsAndConsistsOfThisString(tor, 0, ExpectedContents[0]);
@ -348,8 +344,7 @@ TEST_F(RenameTest, multifileTorrent)
for (tr_file_index_t i = 1; i <= 2; ++i)
{
str = tr_torrentFindFile(tor, i);
EXPECT_STREQ(nullptr, str);
tr_free(str);
EXPECT_EQ(""sv, str);
}
testFileExistsAndConsistsOfThisString(tor, 3, ExpectedContents[3]);
@ -485,9 +480,8 @@ TEST_F(RenameTest, partialFile)
for (tr_file_index_t i = 0; i < 3; ++i)
{
auto const expected = tr_pathbuf{ tor->currentDir(), '/', strings[i] };
char* path = tr_torrentFindFile(tor, i);
EXPECT_EQ(expected, path);
tr_free(path);
auto const actual = tr_torrentFindFile(tor, i);
EXPECT_EQ(expected, actual);
}
torrentRemoveAndWait(tor, 0);

View file

@ -256,9 +256,11 @@ TEST_P(SubprocessTest, SpawnAsyncCwdExplicit)
auto buffer = std::array<char, 1024>{};
EXPECT_TRUE(tr_sys_file_read_line(fd, buffer.data(), buffer.size()));
EXPECT_EQ(
makeString(tr_sys_path_native_separators(tr_strdup(test_dir.c_str()))),
tr_sys_path_native_separators(&buffer.front()));
auto expected = std::string{ test_dir };
tr_sys_path_native_separators(std::data(expected));
auto actual = std::string{ std::data(buffer) };
tr_sys_path_native_separators(std::data(actual));
EXPECT_EQ(expected, actual);
EXPECT_FALSE(tr_sys_file_read_line(fd, buffer.data(), buffer.size()));

View file

@ -71,13 +71,6 @@ static void depthFirstWalk(char const* path, file_func_t func)
func(path);
}
inline std::string makeString(char*&& s)
{
auto const ret = std::string(s != nullptr ? s : "");
tr_free(s);
return ret;
}
inline bool waitFor(std::function<bool()> const& test, int msec)
{
auto const deadline = std::chrono::milliseconds{ msec };

View file

@ -2447,7 +2447,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
break;
case 'n': /* auth */
auth = tr_strdup(optarg);
auth = tr_strvDup(optarg);
break;
case 810: /* authenv */
@ -2464,7 +2464,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
break;
case 'N': /* netrc */
netrc = tr_strdup(optarg);
netrc = tr_strvDup(optarg);
break;
case 820: /* UseSSL */
@ -2543,7 +2543,7 @@ static int processArgs(char const* rpcurl, int argc, char const* const* argv)
switch (c)
{
case 'F':
filter = tr_strdup(optarg); /* Unnecessary dup? we will use it before optarg will be changed */
filter = tr_strvDup(optarg); /* Unnecessary dup? we will use it before optarg will be changed */
tr_variantDictAddInt(top, TR_KEY_tag, TAG_FILTER);
for (size_t i = 0; i < TR_N_ELEMENTS(details_keys); ++i)