mirror of
https://github.com/transmission/transmission
synced 2025-03-06 19:48:15 +00:00
refactor: add libtransmission::Values (#6215)
This commit is contained in:
parent
b413beab70
commit
2e32789193
15 changed files with 439 additions and 407 deletions
29
cli/cli.cc
29
cli/cli.cc
|
@ -26,32 +26,7 @@
|
|||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static auto constexpr MemK = size_t{ 1024 };
|
||||
static char constexpr MemKStr[] = "KiB";
|
||||
static char constexpr MemMStr[] = "MiB";
|
||||
static char constexpr MemGStr[] = "GiB";
|
||||
static char constexpr MemTStr[] = "TiB";
|
||||
|
||||
static auto constexpr DiskK = size_t{ 1000 };
|
||||
static char constexpr DiskKStr[] = "kB";
|
||||
static char constexpr DiskMStr[] = "MB";
|
||||
static char constexpr DiskGStr[] = "GB";
|
||||
static char constexpr DiskTStr[] = "TB";
|
||||
|
||||
static auto constexpr SpeedK = size_t{ 1000 };
|
||||
#define SPEED_K_STR "kB/s"
|
||||
static char constexpr SpeedKStr[] = SPEED_K_STR;
|
||||
static char constexpr SpeedMStr[] = "MB/s";
|
||||
static char constexpr SpeedGStr[] = "GB/s";
|
||||
static char constexpr SpeedTStr[] = "TB/s";
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static auto constexpr LineWidth = int{ 80 };
|
||||
|
||||
|
@ -204,10 +179,6 @@ int tr_main(int argc, char* argv[])
|
|||
|
||||
tr_locale_set_global("");
|
||||
|
||||
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);
|
||||
|
||||
printf("%s %s\n", MyReadableName, LONG_VERSION_STRING);
|
||||
|
||||
/* user needs to pass in at least one argument */
|
||||
|
|
|
@ -73,24 +73,6 @@ static char constexpr Usage[] = "Transmission " LONG_VERSION_STRING
|
|||
"\n"
|
||||
"Usage: transmission-daemon [options]";
|
||||
|
||||
static auto constexpr MemK = size_t{ 1024 };
|
||||
static char constexpr MemKStr[] = "KiB";
|
||||
static char constexpr MemMStr[] = "MiB";
|
||||
static char constexpr MemGStr[] = "GiB";
|
||||
static char constexpr MemTStr[] = "TiB";
|
||||
|
||||
static auto constexpr DiskK = size_t{ 1000 };
|
||||
static char constexpr DiskKStr[] = "kB";
|
||||
static char constexpr DiskMStr[] = "MB";
|
||||
static char constexpr DiskGStr[] = "GB";
|
||||
static char constexpr DiskTStr[] = "TB";
|
||||
|
||||
static auto constexpr SpeedK = size_t{ 1000 };
|
||||
static char constexpr SpeedKStr[] = "kB/s";
|
||||
static char constexpr SpeedMStr[] = "MB/s";
|
||||
static char constexpr SpeedGStr[] = "GB/s";
|
||||
static char constexpr SpeedTStr[] = "TB/s";
|
||||
|
||||
/***
|
||||
**** Config File
|
||||
***/
|
||||
|
@ -723,9 +705,6 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
|
|||
}
|
||||
|
||||
/* start the session */
|
||||
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(cdir, true, settings_);
|
||||
tr_sessionSetRPCCallback(session, on_rpc_callback, this);
|
||||
tr_logAddInfo(fmt::format(_("Loading settings from '{path}'"), fmt::arg("path", cdir)));
|
||||
|
|
|
@ -323,6 +323,7 @@ if(INSTALL_LIB)
|
|||
tr-strbuf.h
|
||||
transmission.h
|
||||
utils.h
|
||||
values.h
|
||||
variant.h
|
||||
watchdir.h
|
||||
web-utils.h
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "libtransmission/tr-assert.h"
|
||||
#include "libtransmission/tr-strbuf.h"
|
||||
#include "libtransmission/utils.h"
|
||||
#include "libtransmission/values.h"
|
||||
#include "libtransmission/variant.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
@ -664,242 +665,138 @@ uint64_t tr_ntohll(uint64_t netlonglong)
|
|||
#endif
|
||||
}
|
||||
|
||||
// ---
|
||||
// --- VALUES / FORMATTER
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace formatter_impl
|
||||
namespace libtransmission::Values
|
||||
{
|
||||
|
||||
struct formatter_unit
|
||||
{
|
||||
std::array<char, 16> name;
|
||||
uint64_t value;
|
||||
};
|
||||
// default values; can be overridden by client apps
|
||||
Config::Units<MemoryUnits> Config::Memory{ Config::Base::Kibi, "B"sv, "KiB"sv, "MiB"sv, "GiB"sv, "TiB"sv };
|
||||
Config::Units<SpeedUnits> Config::Speed{ Config::Base::Kilo, "B/s"sv, "kB/s"sv, "MB/s"sv, "GB/s"sv, "TB/s"sv };
|
||||
Config::Units<StorageUnits> Config::Storage{ Config::Base::Kilo, "B"sv, "kB"sv, "MB"sv, "GB"sv, "TB"sv };
|
||||
|
||||
using formatter_units = std::array<formatter_unit, 4>;
|
||||
|
||||
enum
|
||||
{
|
||||
TR_FMT_KB,
|
||||
TR_FMT_MB,
|
||||
TR_FMT_GB,
|
||||
TR_FMT_TB
|
||||
};
|
||||
|
||||
void formatter_init(formatter_units& units, uint64_t kilo, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
uint64_t value = kilo;
|
||||
tr_strlcpy(std::data(units[TR_FMT_KB].name), kb, std::size(units[TR_FMT_KB].name));
|
||||
units[TR_FMT_KB].value = value;
|
||||
|
||||
value *= kilo;
|
||||
tr_strlcpy(std::data(units[TR_FMT_MB].name), mb, std::size(units[TR_FMT_MB].name));
|
||||
units[TR_FMT_MB].value = value;
|
||||
|
||||
value *= kilo;
|
||||
tr_strlcpy(std::data(units[TR_FMT_GB].name), gb, std::size(units[TR_FMT_GB].name));
|
||||
units[TR_FMT_GB].value = value;
|
||||
|
||||
value *= kilo;
|
||||
tr_strlcpy(std::data(units[TR_FMT_TB].name), tb, std::size(units[TR_FMT_TB].name));
|
||||
units[TR_FMT_TB].value = value;
|
||||
}
|
||||
|
||||
char* formatter_get_size_str(formatter_units const& u, char* buf, uint64_t bytes, size_t buflen)
|
||||
{
|
||||
formatter_unit const* unit = nullptr;
|
||||
|
||||
if (bytes < u[1].value)
|
||||
{
|
||||
unit = std::data(u);
|
||||
}
|
||||
else if (bytes < u[2].value)
|
||||
{
|
||||
unit = &u[1];
|
||||
}
|
||||
else if (bytes < u[3].value)
|
||||
{
|
||||
unit = &u[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
unit = &u[3];
|
||||
}
|
||||
|
||||
double const value = static_cast<double>(bytes) / unit->value;
|
||||
auto const* const units = std::data(unit->name);
|
||||
|
||||
auto precision = int{};
|
||||
if (unit->value == 1)
|
||||
{
|
||||
precision = 0;
|
||||
}
|
||||
else if (value < 100)
|
||||
{
|
||||
precision = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
precision = 1;
|
||||
}
|
||||
|
||||
auto const [out, len] = fmt::format_to_n(buf, buflen - 1, "{:.{}Lf} {:s}", value, precision, units);
|
||||
*out = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
formatter_units size_units;
|
||||
formatter_units speed_units;
|
||||
formatter_units mem_units;
|
||||
|
||||
} // namespace formatter_impl
|
||||
} // namespace
|
||||
|
||||
size_t tr_speed_K = 0;
|
||||
|
||||
void tr_formatter_size_init(uint64_t kilo, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
formatter_init(size_units, kilo, kb, mb, gb, tb);
|
||||
}
|
||||
|
||||
std::string tr_formatter_size_B(uint64_t bytes)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
auto buf = std::array<char, 64>{};
|
||||
return formatter_get_size_str(size_units, std::data(buf), bytes, std::size(buf));
|
||||
}
|
||||
|
||||
void tr_formatter_speed_init(size_t kilo, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
tr_speed_K = kilo;
|
||||
formatter_init(speed_units, kilo, kb, mb, gb, tb);
|
||||
}
|
||||
|
||||
std::string tr_formatter_speed_KBps(double kilo_per_second)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
|
||||
auto speed = kilo_per_second;
|
||||
|
||||
if (speed < 999.95) // 0.0 KB to 999.9 KB (0.0 KiB to 999.9 KiB)
|
||||
{
|
||||
return fmt::format("{:.1Lf} {:s}", speed, std::data(speed_units[TR_FMT_KB].name));
|
||||
}
|
||||
|
||||
double const kilo = speed_units[TR_FMT_KB].value;
|
||||
speed /= kilo;
|
||||
|
||||
if (speed < 99.995) // 0.98 MB to 99.99 MB (1.00 MiB to 99.99 MiB)
|
||||
{
|
||||
return fmt::format("{:.2Lf} {:s}", speed, std::data(speed_units[TR_FMT_MB].name));
|
||||
}
|
||||
if (speed < 999.95) // 100.0 MB to 999.9 MB (100.0 MiB to 999.9 MiB)
|
||||
{
|
||||
return fmt::format("{:.1Lf} {:s}", speed, std::data(speed_units[TR_FMT_MB].name));
|
||||
}
|
||||
|
||||
speed /= kilo;
|
||||
|
||||
if (speed < 99.995) // 0.98 GB to 99.99 GB (1.00 GiB to 99.99 GiB)
|
||||
{
|
||||
return fmt::format("{:.2Lf} {:s}", speed, std::data(speed_units[TR_FMT_GB].name));
|
||||
}
|
||||
// 100.0 GB and above (100.0 GiB and above)
|
||||
return fmt::format("{:.1Lf} {:s}", speed, std::data(speed_units[TR_FMT_GB].name));
|
||||
}
|
||||
|
||||
std::string tr_formatter_speed_compact_KBps(double kilo_per_second)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
|
||||
auto speed = kilo_per_second;
|
||||
|
||||
if (speed < 99.95) // 0.0 KB to 99.9 KB (0.0 KiB to 99.9 KiB)
|
||||
{
|
||||
return fmt::format("{:.1Lf} {:s}", speed, std::data(speed_units[TR_FMT_KB].name));
|
||||
}
|
||||
if (speed < 999.5) // 100 KB to 999 KB (100 KiB to 999 KiB)
|
||||
{
|
||||
return fmt::format("{:.0Lf} {:s}", speed, std::data(speed_units[TR_FMT_KB].name));
|
||||
}
|
||||
|
||||
double const kilo = speed_units[TR_FMT_KB].value;
|
||||
speed /= kilo;
|
||||
|
||||
if (speed < 9.995) // 0.98 MB to 9.99 MB (1.00 MiB to 9.99 MiB)
|
||||
{
|
||||
return fmt::format("{:.2Lf} {:s}", speed, std::data(speed_units[TR_FMT_MB].name));
|
||||
}
|
||||
if (speed < 99.95) // 10.0 MB to 99.9 MB (10.0 MiB to 99.9 MiB)
|
||||
{
|
||||
return fmt::format("{:.1Lf} {:s}", speed, std::data(speed_units[TR_FMT_MB].name));
|
||||
}
|
||||
if (speed < 999.5) // 100 MB to 999 MB (100 MiB to 999 MiB)
|
||||
{
|
||||
return fmt::format("{:.0Lf} {:s}", speed, std::data(speed_units[TR_FMT_MB].name));
|
||||
}
|
||||
|
||||
speed /= kilo;
|
||||
|
||||
if (speed < 9.995) // 0.98 GB to 9.99 GB (1.00 GiB to 9.99 GiB)
|
||||
{
|
||||
return fmt::format("{:.2Lf} {:s}", speed, std::data(speed_units[TR_FMT_GB].name));
|
||||
}
|
||||
if (speed < 99.95) // 10.0 GB to 99.9 GB (10.0 GiB to 99.9 GiB)
|
||||
{
|
||||
return fmt::format("{:.1Lf} {:s}", speed, std::data(speed_units[TR_FMT_GB].name));
|
||||
}
|
||||
// 100 GB and above (100 GiB and above)
|
||||
return fmt::format("{:.0Lf} {:s}", speed, std::data(speed_units[TR_FMT_GB].name));
|
||||
}
|
||||
|
||||
size_t tr_mem_K = 0;
|
||||
|
||||
void tr_formatter_mem_init(size_t kilo, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
|
||||
tr_mem_K = kilo;
|
||||
formatter_init(mem_units, kilo, kb, mb, gb, tb);
|
||||
}
|
||||
|
||||
std::string tr_formatter_mem_B(size_t bytes_per_second)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
|
||||
auto buf = std::array<char, 64>{};
|
||||
return formatter_get_size_str(mem_units, std::data(buf), bytes_per_second, std::size(buf));
|
||||
}
|
||||
} // namespace libtransmission::Values
|
||||
|
||||
tr_variant tr_formatter_get_units()
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
using namespace libtransmission::Values;
|
||||
|
||||
auto const make_units_vec = [](formatter_units const& units)
|
||||
auto const make_units_vec = [](auto const& units)
|
||||
{
|
||||
auto units_vec = tr_variant::Vector{};
|
||||
units_vec.reserve(std::size(units));
|
||||
std::transform(
|
||||
std::begin(units),
|
||||
std::end(units),
|
||||
std::back_inserter(units_vec),
|
||||
[](auto const& unit) { return std::data(unit.name); });
|
||||
for (size_t i = 0;; ++i)
|
||||
{
|
||||
auto const display_name = units.display_name(i);
|
||||
if (std::empty(display_name))
|
||||
{
|
||||
break;
|
||||
}
|
||||
units_vec.emplace_back(display_name);
|
||||
}
|
||||
return units_vec;
|
||||
};
|
||||
|
||||
auto units_map = tr_variant::Map{ 6U };
|
||||
units_map.try_emplace(TR_KEY_memory_bytes, mem_units[TR_FMT_KB].value);
|
||||
units_map.try_emplace(TR_KEY_memory_units, make_units_vec(mem_units));
|
||||
units_map.try_emplace(TR_KEY_size_bytes, size_units[TR_FMT_KB].value);
|
||||
units_map.try_emplace(TR_KEY_size_units, make_units_vec(size_units));
|
||||
units_map.try_emplace(TR_KEY_speed_bytes, speed_units[TR_FMT_KB].value);
|
||||
units_map.try_emplace(TR_KEY_speed_units, make_units_vec(speed_units));
|
||||
units_map.try_emplace(TR_KEY_memory_bytes, Memory::units().base());
|
||||
units_map.try_emplace(TR_KEY_memory_units, make_units_vec(Memory::units()));
|
||||
units_map.try_emplace(TR_KEY_size_bytes, Storage::units().base());
|
||||
units_map.try_emplace(TR_KEY_size_units, make_units_vec(Storage::units()));
|
||||
units_map.try_emplace(TR_KEY_speed_bytes, Speed::units().base());
|
||||
units_map.try_emplace(TR_KEY_speed_units, make_units_vec(Speed::units()));
|
||||
return tr_variant{ std::move(units_map) };
|
||||
}
|
||||
|
||||
// --- formatters: storage
|
||||
|
||||
void tr_formatter_size_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
namespace Values = libtransmission::Values;
|
||||
|
||||
auto const kval = base == 1000U ? Values::Config::Base::Kilo : Values::Config::Base::Kibi;
|
||||
Values::Config::Storage = { kval, "B", kb, mb, gb, tb };
|
||||
}
|
||||
|
||||
std::string tr_formatter_size_B(uint64_t bytes)
|
||||
{
|
||||
using Storage = libtransmission::Values::Storage;
|
||||
|
||||
return Storage{ bytes, Storage::Units::Bytes }.to_string();
|
||||
}
|
||||
|
||||
// --- formatters: speed
|
||||
|
||||
size_t tr_speed_K = 0;
|
||||
|
||||
void tr_formatter_speed_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
namespace Values = libtransmission::Values;
|
||||
|
||||
auto const kval = base == 1000U ? Values::Config::Base::Kilo : Values::Config::Base::Kibi;
|
||||
Values::Config::Speed = { kval, "B/s", kb, mb, gb, tb };
|
||||
tr_speed_K = base;
|
||||
}
|
||||
|
||||
std::string tr_formatter_speed_KBps(double kbyps)
|
||||
{
|
||||
using Speed = libtransmission::Values::Speed;
|
||||
|
||||
return Speed{ kbyps, Speed::Units::KByps }.to_string();
|
||||
}
|
||||
uint64_t tr_toSpeedBytes(size_t kbyps)
|
||||
{
|
||||
using Speed = libtransmission::Values::Speed;
|
||||
|
||||
return Speed{ kbyps, Speed::Units::KByps }.base_quantity();
|
||||
}
|
||||
|
||||
double tr_toSpeedKBps(size_t byps)
|
||||
{
|
||||
using Speed = libtransmission::Values::Speed;
|
||||
|
||||
return Speed{ byps, Speed::Units::Byps }.count(Speed::Units::KByps);
|
||||
}
|
||||
|
||||
// --- formatters: memory
|
||||
|
||||
size_t tr_mem_K = 0;
|
||||
|
||||
void tr_formatter_mem_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb)
|
||||
{
|
||||
namespace Values = libtransmission::Values;
|
||||
|
||||
auto const kval = base == 1000U ? Values::Config::Base::Kilo : Values::Config::Base::Kibi;
|
||||
Values::Config::Memory = { kval, "B", kb, mb, gb, tb };
|
||||
tr_mem_K = base;
|
||||
}
|
||||
|
||||
std::string tr_formatter_mem_B(uint64_t bytes)
|
||||
{
|
||||
using Memory = libtransmission::Values::Memory;
|
||||
|
||||
return Memory{ bytes, Memory::Units::Bytes }.to_string();
|
||||
}
|
||||
|
||||
std::string tr_formatter_mem_MB(double mbytes)
|
||||
{
|
||||
using Memory = libtransmission::Values::Memory;
|
||||
|
||||
return Memory{ mbytes, Memory::Units::MBytes }.to_string();
|
||||
}
|
||||
|
||||
uint64_t tr_toMemBytes(size_t mbytes)
|
||||
{
|
||||
using Memory = libtransmission::Values::Memory;
|
||||
|
||||
return Memory{ mbytes, Memory::Units::MBytes }.base_quantity();
|
||||
}
|
||||
|
||||
double tr_toMemMB(uint64_t bytes)
|
||||
{
|
||||
using Memory = libtransmission::Values::Memory;
|
||||
|
||||
return Memory{ bytes, Memory::Units::Bytes }.count(Memory::Units::MBytes);
|
||||
}
|
||||
|
||||
// --- ENVIRONMENT
|
||||
|
||||
bool tr_env_key_exists(char const* key)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "libtransmission/tr-macros.h"
|
||||
#include "libtransmission/variant.h"
|
||||
#include "libtransmission/values.h"
|
||||
|
||||
struct tr_error;
|
||||
|
||||
|
@ -300,55 +301,24 @@ constexpr void tr_timeUpdate(time_t now) noexcept
|
|||
// ---
|
||||
|
||||
/* example: tr_formatter_size_init(1024, _("KiB"), _("MiB"), _("GiB"), _("TiB")); */
|
||||
|
||||
void tr_formatter_size_init(uint64_t kilo, char const* kb, char const* mb, char const* gb, char const* tb);
|
||||
|
||||
void tr_formatter_speed_init(size_t kilo, char const* kb, char const* mb, char const* gb, char const* tb);
|
||||
|
||||
void tr_formatter_mem_init(size_t kilo, char const* kb, char const* mb, char const* gb, char const* tb);
|
||||
void tr_formatter_size_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb);
|
||||
void tr_formatter_speed_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb);
|
||||
void tr_formatter_mem_init(size_t base, char const* kb, char const* mb, char const* gb, char const* tb);
|
||||
|
||||
extern size_t tr_speed_K;
|
||||
extern size_t tr_mem_K;
|
||||
extern uint64_t tr_size_K; /* unused? */
|
||||
|
||||
/** @brief Format a speed from KBps into a user-readable string of at most 4 significant digits. */
|
||||
[[nodiscard]] std::string tr_formatter_speed_KBps(double kilo_per_second);
|
||||
/** @brief Format a speed from KBps into a user-readable string of at most 3 significant digits. */
|
||||
[[nodiscard]] std::string tr_formatter_speed_compact_KBps(double kilo_per_second);
|
||||
[[nodiscard]] double tr_toMemMB(uint64_t bytes);
|
||||
[[nodiscard]] double tr_toSpeedKBps(size_t byps);
|
||||
[[nodiscard]] uint64_t tr_toMemBytes(size_t mbytes);
|
||||
[[nodiscard]] uint64_t tr_toSpeedBytes(size_t kbyps);
|
||||
|
||||
/** @brief Format a memory size from bytes into a user-readable string. */
|
||||
[[nodiscard]] std::string tr_formatter_mem_B(size_t bytes);
|
||||
|
||||
/** @brief Format a memory size from MB into a user-readable string. */
|
||||
[[nodiscard]] static inline std::string tr_formatter_mem_MB(double MBps)
|
||||
{
|
||||
return tr_formatter_mem_B((size_t)(MBps * tr_mem_K * tr_mem_K));
|
||||
}
|
||||
|
||||
/** @brief Format a file size from bytes into a user-readable string. */
|
||||
[[nodiscard]] std::string tr_formatter_mem_B(uint64_t bytes);
|
||||
[[nodiscard]] std::string tr_formatter_mem_MB(double mbytes);
|
||||
[[nodiscard]] std::string tr_formatter_size_B(uint64_t bytes);
|
||||
[[nodiscard]] std::string tr_formatter_speed_KBps(double kbyps);
|
||||
|
||||
struct tr_variant tr_formatter_get_units();
|
||||
|
||||
[[nodiscard]] static inline size_t tr_toSpeedBytes(size_t KBps)
|
||||
{
|
||||
return KBps * tr_speed_K;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline auto tr_toSpeedKBps(size_t Bps)
|
||||
{
|
||||
return Bps / double(tr_speed_K);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline auto tr_toMemBytes(size_t MB)
|
||||
{
|
||||
return uint64_t(tr_mem_K) * tr_mem_K * MB;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline auto tr_toMemMB(uint64_t B)
|
||||
{
|
||||
return size_t(B / (tr_mem_K * tr_mem_K));
|
||||
}
|
||||
[[nodiscard]] struct tr_variant tr_formatter_get_units();
|
||||
|
||||
// ---
|
||||
|
||||
|
|
259
libtransmission/values.h
Normal file
259
libtransmission/values.h
Normal file
|
@ -0,0 +1,259 @@
|
|||
// This file Copyright © Mnemosyne LLC.
|
||||
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint> // for uint64_t
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
namespace libtransmission::Values
|
||||
{
|
||||
enum class MemoryUnits
|
||||
{
|
||||
Bytes,
|
||||
KBytes,
|
||||
MBytes,
|
||||
GBytes,
|
||||
TBytes
|
||||
};
|
||||
|
||||
using StorageUnits = MemoryUnits;
|
||||
|
||||
enum class SpeedUnits
|
||||
{
|
||||
Byps,
|
||||
KByps,
|
||||
MByps,
|
||||
GByps,
|
||||
TByps
|
||||
};
|
||||
|
||||
struct Config
|
||||
{
|
||||
enum class Base
|
||||
{
|
||||
Kilo = 1000U,
|
||||
Kibi = 1024U
|
||||
};
|
||||
|
||||
template<typename UnitsEnum>
|
||||
struct Units
|
||||
{
|
||||
template<typename... Names>
|
||||
Units(Base base, Names... names)
|
||||
{
|
||||
set_base(base);
|
||||
|
||||
auto idx = size_t{ 0U };
|
||||
(set_name(idx++, names), ...);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto base() const noexcept
|
||||
{
|
||||
return static_cast<size_t>(base_);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto display_name(size_t units) const noexcept
|
||||
{
|
||||
return std::string_view{ units < std::size(display_names_) ? std::data(display_names_[units]) : "" };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto multiplier(UnitsEnum multiplier) const noexcept
|
||||
{
|
||||
return multipliers_[static_cast<int>(multiplier)];
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr void set_base(Base base)
|
||||
{
|
||||
base_ = base;
|
||||
|
||||
auto val = uint64_t{ 1U };
|
||||
for (auto& multiplier : multipliers_)
|
||||
{
|
||||
multiplier = val;
|
||||
val *= static_cast<size_t>(base);
|
||||
}
|
||||
}
|
||||
|
||||
void set_name(size_t idx, std::string_view name)
|
||||
{
|
||||
*fmt::format_to_n(std::data(display_names_[idx]), std::size(display_names_[idx]) - 1, "{:s}", name).out = '\0';
|
||||
}
|
||||
|
||||
std::array<std::array<char, 32>, 5> display_names_ = {};
|
||||
std::array<uint64_t, 5> multipliers_;
|
||||
Base base_;
|
||||
};
|
||||
|
||||
static Units<MemoryUnits> Memory;
|
||||
static Units<SpeedUnits> Speed;
|
||||
static Units<StorageUnits> Storage;
|
||||
};
|
||||
|
||||
template<typename UnitsEnum, Config::Units<UnitsEnum> const& units_>
|
||||
class Value
|
||||
{
|
||||
public:
|
||||
using Units = UnitsEnum;
|
||||
|
||||
constexpr Value() = default;
|
||||
|
||||
constexpr Value(uint64_t value, Units multiple)
|
||||
: base_quantity_{ value * units_.multiplier(multiple) }
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Number>
|
||||
Value(Number value, Units multiple)
|
||||
: base_quantity_{ static_cast<uint64_t>(value * units_.multiplier(multiple)) }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr auto& operator+=(Value const& that) noexcept
|
||||
{
|
||||
base_quantity_ += that.base_quantity_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto base_quantity() const noexcept
|
||||
{
|
||||
return base_quantity_;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto count(Units tgt) const noexcept
|
||||
{
|
||||
return base_quantity_ / (1.0 * units_.multiplier(tgt));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator+(Value const& that) noexcept
|
||||
{
|
||||
auto ret = *this;
|
||||
return ret += that;
|
||||
}
|
||||
|
||||
constexpr auto& operator*=(uint64_t mult) noexcept
|
||||
{
|
||||
base_quantity_ *= mult;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator*(uint64_t mult) noexcept
|
||||
{
|
||||
auto ret = *this;
|
||||
return ret *= mult;
|
||||
}
|
||||
|
||||
constexpr auto& operator/=(uint64_t mult) noexcept
|
||||
{
|
||||
base_quantity_ /= mult;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator/(uint64_t mult) noexcept
|
||||
{
|
||||
auto ret = *this;
|
||||
return ret /= mult;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator<(Value const& that) const noexcept
|
||||
{
|
||||
return compare(that) < 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator<=(Value const& that) const noexcept
|
||||
{
|
||||
return compare(that) <= 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator==(Value const& that) const noexcept
|
||||
{
|
||||
return compare(that) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator!=(Value const& that) const noexcept
|
||||
{
|
||||
return compare(that) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator>(Value const& that) const noexcept
|
||||
{
|
||||
return compare(that) > 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto operator>=(Value const& that) const noexcept
|
||||
{
|
||||
return compare(that) >= 0;
|
||||
}
|
||||
|
||||
std::string_view to_string(char* buf, size_t buflen) const noexcept
|
||||
{
|
||||
auto idx = size_t{ 0 };
|
||||
|
||||
if (base_quantity_ < 1000) // 0 to 999
|
||||
{
|
||||
*fmt::format_to_n(buf, buflen - 1, "{:d} {:s}", base_quantity_, units_.display_name(idx)).out = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
auto val = 1.0 * base_quantity_;
|
||||
for (;;)
|
||||
{
|
||||
++idx;
|
||||
val /= units_.base();
|
||||
|
||||
if (val < 99.995) // 0.98 to 99.99
|
||||
{
|
||||
*fmt::format_to_n(buf, buflen - 1, "{:.2Lf} {:s}", val, units_.display_name(idx)).out = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (val < 999.95 || std::empty(units_.display_name(idx + 1))) // 100.0 to 999.9
|
||||
{
|
||||
*fmt::format_to_n(buf, buflen - 1, "{:.1Lf} {:s}", val, units_.display_name(idx)).out = '\0';
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string to_string() const
|
||||
{
|
||||
auto buf = std::array<char, 64>{};
|
||||
return std::string{ to_string(std::data(buf), std::size(buf)) };
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr auto const& units() noexcept
|
||||
{
|
||||
return units_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t base_quantity_ = {};
|
||||
|
||||
[[nodiscard]] constexpr int compare(Value const& that) const noexcept // <=>
|
||||
{
|
||||
if (base_quantity_ < that.base_quantity_)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (base_quantity_ > that.base_quantity_)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
using Memory = Value<MemoryUnits, Config::Memory>;
|
||||
using Storage = Value<StorageUnits, Config::Storage>;
|
||||
using Speed = Value<SpeedUnits, Config::Speed>;
|
||||
|
||||
} // namespace libtransmission::Values
|
|
@ -54,6 +54,7 @@ target_sources(libtransmission-test
|
|||
torrents-test.cc
|
||||
tr-peer-info-test.cc
|
||||
utils-test.cc
|
||||
values-test.cc
|
||||
variant-test.cc
|
||||
watchdir-test.cc
|
||||
web-utils-test.cc)
|
||||
|
|
|
@ -305,38 +305,6 @@ private:
|
|||
Sandbox sandbox_;
|
||||
};
|
||||
|
||||
inline void ensureFormattersInited()
|
||||
{
|
||||
static constexpr int MEM_K = 1024;
|
||||
static char constexpr const* const MEM_K_STR = "KiB";
|
||||
static char constexpr const* const MEM_M_STR = "MiB";
|
||||
static char constexpr const* const MEM_G_STR = "GiB";
|
||||
static char constexpr const* const MEM_T_STR = "TiB";
|
||||
|
||||
static constexpr int DISK_K = 1000;
|
||||
static char constexpr const* const DISK_K_STR = "kB";
|
||||
static char constexpr const* const DISK_M_STR = "MB";
|
||||
static char constexpr const* const DISK_G_STR = "GB";
|
||||
static char constexpr const* const DISK_T_STR = "TB";
|
||||
|
||||
static constexpr int SPEED_K = 1000;
|
||||
static char constexpr const* const SPEED_K_STR = "kB/s";
|
||||
static char constexpr const* const SPEED_M_STR = "MB/s";
|
||||
static char constexpr const* const SPEED_G_STR = "GB/s";
|
||||
static char constexpr const* const SPEED_T_STR = "TB/s";
|
||||
|
||||
static std::once_flag flag;
|
||||
|
||||
std::call_once(
|
||||
flag,
|
||||
[]()
|
||||
{
|
||||
tr_formatter_mem_init(MEM_K, MEM_K_STR, MEM_M_STR, MEM_G_STR, MEM_T_STR);
|
||||
tr_formatter_size_init(DISK_K, DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR);
|
||||
tr_formatter_speed_init(SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR);
|
||||
});
|
||||
}
|
||||
|
||||
class SessionTest : public SandboxedTest
|
||||
{
|
||||
private:
|
||||
|
@ -344,8 +312,6 @@ private:
|
|||
|
||||
tr_session* sessionInit(tr_variant& settings)
|
||||
{
|
||||
ensureFormattersInited();
|
||||
|
||||
auto* const settings_map = settings.get_if<tr_variant::Map>();
|
||||
EXPECT_NE(settings_map, nullptr);
|
||||
|
||||
|
|
46
tests/libtransmission/values-test.cc
Normal file
46
tests/libtransmission/values-test.cc
Normal file
|
@ -0,0 +1,46 @@
|
|||
// This file Copyright © Mnemosyne LLC.
|
||||
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/values.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using ValuesTest = ::testing::Test;
|
||||
|
||||
TEST_F(ValuesTest, value)
|
||||
{
|
||||
using Speed = libtransmission::Values::Speed;
|
||||
|
||||
auto val = Speed{ 1, Speed::Units::MByps };
|
||||
EXPECT_EQ("1.00 MB/s", val.to_string());
|
||||
EXPECT_EQ(1000000UL, val.base_quantity());
|
||||
EXPECT_NEAR(1000U, val.count(Speed::Units::KByps), 0.0001);
|
||||
EXPECT_NEAR(1U, val.count(Speed::Units::MByps), 0.0001);
|
||||
EXPECT_NEAR(0.001, val.count(Speed::Units::GByps), 0.0001);
|
||||
|
||||
val = Speed{ 1, Speed::Units::Byps };
|
||||
EXPECT_EQ(1U, val.base_quantity());
|
||||
EXPECT_EQ("1 B/s", val.to_string());
|
||||
|
||||
val = Speed{ 10, Speed::Units::KByps };
|
||||
EXPECT_EQ("10.00 kB/s", val.to_string());
|
||||
|
||||
val = Speed{ 999, Speed::Units::KByps };
|
||||
EXPECT_EQ("999.0 kB/s", val.to_string());
|
||||
}
|
||||
|
||||
TEST_F(ValuesTest, valueHonorsFormatterInit)
|
||||
{
|
||||
using Speed = libtransmission::Values::Speed;
|
||||
|
||||
tr_formatter_speed_init(1024, "KayBeePerEss", "EmmBeePerEss", "GeeBeePerEss", "TeeBeePerEss");
|
||||
|
||||
auto const val = Speed{ 1, Speed::Units::MByps };
|
||||
EXPECT_EQ("1.00 EmmBeePerEss", val.to_string());
|
||||
EXPECT_EQ(1048576U, val.base_quantity());
|
||||
}
|
|
@ -11,7 +11,7 @@ GENERAL
|
|||
Source: 私たちの世界
|
||||
Piece Count: 1
|
||||
Piece Size: 1.00 MiB
|
||||
Total Size: 0.01 kB
|
||||
Total Size: 13 B
|
||||
Privacy: Public torrent
|
||||
|
||||
TRACKERS
|
||||
|
@ -21,6 +21,6 @@ TRACKERS
|
|||
|
||||
FILES
|
||||
|
||||
modified test-utf8/別の世界f1.txt (0.01 kB)
|
||||
modified test-utf8/別の世界f2.txt (0.01 kB)
|
||||
modified test-utf8/別の世界f1.txt (6 B)
|
||||
modified test-utf8/別の世界f2.txt (7 B)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ FILES
|
|||
bittorrent-v1-v2-hybrid-test/eld-dust.mkv (61.64 MB)
|
||||
bittorrent-v1-v2-hybrid-test/fairlight_cncd-agenda_circling_forth-1080p30lq.mp4 (277.9 MB)
|
||||
bittorrent-v1-v2-hybrid-test/meet the deadline - Still _ Evoke 2014.mp4 (44.58 MB)
|
||||
bittorrent-v1-v2-hybrid-test/readme.txt (0.06 kB)
|
||||
bittorrent-v1-v2-hybrid-test/readme.txt (61 B)
|
||||
bittorrent-v1-v2-hybrid-test/tbl-goa.avi (26.30 MB)
|
||||
bittorrent-v1-v2-hybrid-test/tbl-tint.mpg (115.9 MB)
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/version.h>
|
||||
|
||||
#include "units.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace
|
||||
|
@ -139,9 +137,6 @@ int tr_main(int argc, char* argv[])
|
|||
tr_locale_set_global("");
|
||||
|
||||
tr_logSetLevel(TR_LOG_ERROR);
|
||||
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);
|
||||
|
||||
auto options = app_options{};
|
||||
if (parseCommandLine(options, argc, (char const* const*)argv) != 0)
|
||||
|
|
|
@ -61,24 +61,6 @@ static char constexpr Usage[] = "transmission-remote " LONG_VERSION_STRING
|
|||
|
||||
static auto constexpr Arguments = TR_KEY_arguments;
|
||||
|
||||
static auto constexpr MemK = size_t{ 1024 };
|
||||
static char constexpr MemKStr[] = "KiB";
|
||||
static char constexpr MemMStr[] = MEM_M_STR;
|
||||
static char constexpr MemGStr[] = "GiB";
|
||||
static char constexpr MemTStr[] = "TiB";
|
||||
|
||||
static auto constexpr DiskK = size_t{ 1000 };
|
||||
static char constexpr DiskKStr[] = "kB";
|
||||
static char constexpr DiskMStr[] = "MB";
|
||||
static char constexpr DiskGStr[] = "GB";
|
||||
static char constexpr DiskTStr[] = "TB";
|
||||
|
||||
static auto constexpr SpeedK = size_t{ 1000 };
|
||||
static auto constexpr SpeedKStr = SPEED_K_STR;
|
||||
static char constexpr SpeedMStr[] = "MB/s";
|
||||
static char constexpr SpeedGStr[] = "GB/s";
|
||||
static char constexpr SpeedTStr[] = "TB/s";
|
||||
|
||||
struct Config
|
||||
{
|
||||
std::string auth;
|
||||
|
@ -3329,10 +3311,6 @@ int tr_main(int argc, char* argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
getHostAndPortAndRpcUrl(&argc, argv, &host, &port, &rpcurl, config);
|
||||
|
||||
if (std::empty(host))
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
#include <libtransmission/web.h>
|
||||
#include <libtransmission/web-utils.h>
|
||||
|
||||
#include "units.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace
|
||||
|
@ -409,9 +407,6 @@ int tr_main(int argc, char* argv[])
|
|||
|
||||
tr_logSetQueueEnabled(false);
|
||||
tr_logSetLevel(TR_LOG_ERROR);
|
||||
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);
|
||||
|
||||
auto opts = app_opts{};
|
||||
if (parseCommandLine(opts, argc, (char const* const*)argv) != 0)
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// This file Copyright © Mnemosyne LLC.
|
||||
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
static auto constexpr MemK = size_t{ 1024 };
|
||||
static char constexpr MemKStr[] = "KiB";
|
||||
static char constexpr MemMStr[] = "MiB";
|
||||
static char constexpr MemGStr[] = "GiB";
|
||||
static char constexpr MemTStr[] = "TiB";
|
||||
|
||||
static auto constexpr DiskK = size_t{ 1000 };
|
||||
static char constexpr DiskKStr[] = "kB";
|
||||
static char constexpr DiskMStr[] = "MB";
|
||||
static char constexpr DiskGStr[] = "GB";
|
||||
static char constexpr DiskTStr[] = "TB";
|
||||
|
||||
static auto constexpr SpeedK = size_t{ 1000 };
|
||||
static char constexpr SpeedKStr[] = "kB/s";
|
||||
static char constexpr SpeedMStr[] = "MB/s";
|
||||
static char constexpr SpeedGStr[] = "GB/s";
|
||||
static char constexpr SpeedTStr[] = "TB/s";
|
Loading…
Add table
Reference in a new issue