mirror of
https://github.com/transmission/transmission
synced 2024-12-31 20:16:57 +00:00
refactor: avoid tr_new() in tr_main_win32() (#3664)
This commit is contained in:
parent
7fe2cf68b9
commit
36675d183a
1 changed files with 95 additions and 73 deletions
|
@ -3,7 +3,7 @@
|
|||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <algorithm> // std::sort
|
||||
#include <algorithm> // for std::sort, std::transform
|
||||
#include <array> // std::array
|
||||
#include <cerrno>
|
||||
#include <cfloat> // DBL_DIG
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include <cstring> /* strerror() */
|
||||
#include <ctime> // nanosleep()
|
||||
#include <iterator> // for std::back_inserter
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
@ -379,14 +380,18 @@ bool tr_utf8_validate(std::string_view sv, char const** good_end)
|
|||
return all_good;
|
||||
}
|
||||
|
||||
static std::string strip_non_utf8(std::string_view sv)
|
||||
namespace
|
||||
{
|
||||
namespace tr_strvUtf8Clean_impl
|
||||
{
|
||||
std::string strip_non_utf8(std::string_view sv)
|
||||
{
|
||||
auto out = std::string{};
|
||||
utf8::unchecked::replace_invalid(std::data(sv), std::data(sv) + std::size(sv), std::back_inserter(out), '?');
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::string to_utf8(std::string_view sv)
|
||||
std::string to_utf8(std::string_view sv)
|
||||
{
|
||||
#ifdef HAVE_ICONV
|
||||
size_t const buflen = std::size(sv) * 4 + 10;
|
||||
|
@ -423,8 +428,13 @@ static std::string to_utf8(std::string_view sv)
|
|||
return strip_non_utf8(sv);
|
||||
}
|
||||
|
||||
} // namespace tr_strvUtf8Clean_impl
|
||||
} // namespace
|
||||
|
||||
std::string tr_strvUtf8Clean(std::string_view cleanme)
|
||||
{
|
||||
using namespace tr_strvUtf8Clean_impl;
|
||||
|
||||
if (tr_utf8_validate(cleanme, nullptr))
|
||||
{
|
||||
return std::string{ cleanme };
|
||||
|
@ -445,21 +455,6 @@ std::string tr_win32_native_to_utf8(std::wstring_view in)
|
|||
return out;
|
||||
}
|
||||
|
||||
static char* tr_win32_native_to_utf8(wchar_t const* text, int text_size)
|
||||
{
|
||||
if (text == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (text_size < 0)
|
||||
{
|
||||
return tr_strvDup(tr_win32_native_to_utf8(text));
|
||||
}
|
||||
|
||||
return tr_strvDup(tr_win32_native_to_utf8({ text, static_cast<size_t>(text_size) }));
|
||||
}
|
||||
|
||||
std::wstring tr_win32_utf8_to_native(std::string_view in)
|
||||
{
|
||||
auto out = std::wstring{};
|
||||
|
@ -504,60 +499,68 @@ std::string tr_win32_format_message(uint32_t code)
|
|||
return text;
|
||||
}
|
||||
|
||||
static void tr_win32_make_args_utf8(int* argc, char*** argv)
|
||||
namespace
|
||||
{
|
||||
namespace tr_main_win32_impl
|
||||
{
|
||||
int my_argc;
|
||||
wchar_t** my_wide_argv;
|
||||
|
||||
my_wide_argv = CommandLineToArgvW(GetCommandLineW(), &my_argc);
|
||||
|
||||
if (my_wide_argv == nullptr)
|
||||
std::optional<std::vector<std::string>> win32MakeUtf8Argv()
|
||||
{
|
||||
int argc;
|
||||
auto argv = std::vector<std::string>{};
|
||||
if (wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc); wargv != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TR_ASSERT(*argc == my_argc);
|
||||
|
||||
char** my_argv = tr_new(char*, my_argc + 1);
|
||||
int processed_argc = 0;
|
||||
|
||||
for (int i = 0; i < my_argc; ++i, ++processed_argc)
|
||||
{
|
||||
my_argv[i] = tr_win32_native_to_utf8(my_wide_argv[i], -1);
|
||||
|
||||
if (my_argv[i] == nullptr)
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wargv[i] == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (processed_argc < my_argc)
|
||||
{
|
||||
for (int i = 0; i < processed_argc; ++i)
|
||||
{
|
||||
tr_free(my_argv[i]);
|
||||
auto str = tr_win32_native_to_utf8(wargv[i]);
|
||||
if (std::empty(str))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
argv.emplace_back(std::move(str));
|
||||
}
|
||||
|
||||
tr_free(my_argv);
|
||||
LocalFree(wargv);
|
||||
}
|
||||
else
|
||||
|
||||
if (static_cast<int>(std::size(argv)) == argc)
|
||||
{
|
||||
my_argv[my_argc] = nullptr;
|
||||
|
||||
*argc = my_argc;
|
||||
*argv = my_argv;
|
||||
|
||||
/* TODO: Add atexit handler to cleanup? */
|
||||
return argv;
|
||||
}
|
||||
|
||||
LocalFree(my_wide_argv);
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace tr_main_win32_impl
|
||||
} // namespace
|
||||
|
||||
int tr_main_win32(int argc, char** argv, int (*real_main)(int, char**))
|
||||
{
|
||||
tr_win32_make_args_utf8(&argc, &argv);
|
||||
using namespace tr_main_win32_impl;
|
||||
|
||||
SetConsoleCP(CP_UTF8);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
// build an argv from GetCommandLineW + CommandLineToArgvW
|
||||
if (auto argv_strs = win32MakeUtf8Argv(); argv_strs)
|
||||
{
|
||||
auto argv_cstrs = std::vector<char*>{};
|
||||
argv_cstrs.reserve(std::size(*argv_strs));
|
||||
std::transform(
|
||||
std::begin(*argv_strs),
|
||||
std::end(*argv_strs),
|
||||
std::back_inserter(argv_cstrs),
|
||||
[](auto& str) { return std::data(str); });
|
||||
argv_cstrs.push_back(nullptr); // argv is nullptr-terminated
|
||||
return (*real_main)(std::size(*argv_strs), std::data(argv_cstrs));
|
||||
}
|
||||
|
||||
return (*real_main)(argc, argv);
|
||||
}
|
||||
|
||||
|
@ -567,6 +570,11 @@ int tr_main_win32(int argc, char** argv, int (*real_main)(int, char**))
|
|||
****
|
||||
***/
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace tr_parseNumberRange_impl
|
||||
{
|
||||
|
||||
struct number_range
|
||||
{
|
||||
int low;
|
||||
|
@ -577,7 +585,7 @@ struct number_range
|
|||
* This should be a single number (ex. "6") or a range (ex. "6-9").
|
||||
* Anything else is an error and will return failure.
|
||||
*/
|
||||
static bool parseNumberSection(std::string_view str, number_range& range)
|
||||
bool parseNumberSection(std::string_view str, number_range& range)
|
||||
{
|
||||
auto constexpr Delimiter = "-"sv;
|
||||
|
||||
|
@ -609,6 +617,9 @@ static bool parseNumberSection(std::string_view str, number_range& range)
|
|||
return true;
|
||||
}
|
||||
|
||||
} // namespace tr_parseNumberRange_impl
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -617,6 +628,8 @@ static bool parseNumberSection(std::string_view str, number_range& range)
|
|||
*/
|
||||
std::vector<int> tr_parseNumberRange(std::string_view str)
|
||||
{
|
||||
using namespace tr_parseNumberRange_impl;
|
||||
|
||||
auto values = std::set<int>{};
|
||||
auto token = std::string_view{};
|
||||
auto range = number_range{};
|
||||
|
@ -785,10 +798,13 @@ uint64_t tr_ntohll(uint64_t x)
|
|||
|
||||
/***
|
||||
****
|
||||
****
|
||||
****
|
||||
***/
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace formatter_impl
|
||||
{
|
||||
|
||||
struct formatter_unit
|
||||
{
|
||||
std::array<char, 16> name;
|
||||
|
@ -805,13 +821,7 @@ enum
|
|||
TR_FMT_TB
|
||||
};
|
||||
|
||||
static void formatter_init(
|
||||
formatter_units& units,
|
||||
uint64_t kilo,
|
||||
char const* kb,
|
||||
char const* mb,
|
||||
char const* gb,
|
||||
char const* 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));
|
||||
|
@ -830,7 +840,7 @@ static void formatter_init(
|
|||
units[TR_FMT_TB].value = value;
|
||||
}
|
||||
|
||||
static char* formatter_get_size_str(formatter_units const& u, char* buf, uint64_t bytes, size_t buflen)
|
||||
char* formatter_get_size_str(formatter_units const& u, char* buf, uint64_t bytes, size_t buflen)
|
||||
{
|
||||
formatter_unit const* unit = nullptr;
|
||||
|
||||
|
@ -873,31 +883,39 @@ static char* formatter_get_size_str(formatter_units const& u, char* buf, uint64_
|
|||
return buf;
|
||||
}
|
||||
|
||||
static formatter_units size_units;
|
||||
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));
|
||||
}
|
||||
|
||||
static formatter_units speed_units;
|
||||
|
||||
size_t tr_speed_K = 0;
|
||||
|
||||
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 KBps)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
|
||||
auto speed = KBps;
|
||||
|
||||
if (speed <= 999.95) // 0.0 KB to 999.9 KB
|
||||
|
@ -921,24 +939,28 @@ std::string tr_formatter_speed_KBps(double KBps)
|
|||
return fmt::format("{:.1f} {:s}", speed / K, std::data(speed_units[TR_FMT_GB].name));
|
||||
}
|
||||
|
||||
static formatter_units mem_units;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void tr_formatter_get_units(void* vdict)
|
||||
{
|
||||
using namespace formatter_impl;
|
||||
|
||||
auto* dict = static_cast<tr_variant*>(vdict);
|
||||
|
||||
tr_variantDictReserve(dict, 6);
|
||||
|
|
Loading…
Reference in a new issue