From 36675d183a1ac744449bd08ce8a222c0e190d4fe Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 17 Aug 2022 18:26:52 -0500 Subject: [PATCH] refactor: avoid tr_new() in tr_main_win32() (#3664) --- libtransmission/utils.cc | 168 ++++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 73 deletions(-) diff --git a/libtransmission/utils.cc b/libtransmission/utils.cc index b360ec6b9..289d37094 100644 --- a/libtransmission/utils.cc +++ b/libtransmission/utils.cc @@ -3,7 +3,7 @@ // or any future license endorsed by Mnemosyne LLC. // License text can be found in the licenses/ folder. -#include // std::sort +#include // for std::sort, std::transform #include // std::array #include #include // DBL_DIG @@ -14,6 +14,7 @@ #include /* strerror() */ #include // nanosleep() #include // for std::back_inserter +#include #include #include #include @@ -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(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> win32MakeUtf8Argv() +{ + int argc; + auto argv = std::vector{}; + 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(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{}; + 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 tr_parseNumberRange(std::string_view str) { + using namespace tr_parseNumberRange_impl; + auto values = std::set{}; 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 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{}; 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{}; 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(vdict); tr_variantDictReserve(dict, 6);