mirror of
https://github.com/transmission/transmission
synced 2025-02-20 13:16:53 +00:00
refactor: tr_parseNumberRange() takes a std::string_view (#1962)
* tr_parseNumberRange() now takes a std::string_view
This commit is contained in:
parent
d11ccf113c
commit
3e7b8eb7bb
5 changed files with 35 additions and 23 deletions
|
@ -2840,7 +2840,12 @@ void tr_rpc_request_exec_json(
|
|||
*/
|
||||
void tr_rpc_parse_list_str(tr_variant* setme, char const* str, size_t len)
|
||||
{
|
||||
auto const values = tr_parseNumberRange(str, len);
|
||||
if (len == TR_BAD_SIZE)
|
||||
{
|
||||
len = strlen(str);
|
||||
}
|
||||
|
||||
auto const values = tr_parseNumberRange(std::string_view{ str, len });
|
||||
auto const valueCount = std::size(values);
|
||||
|
||||
if (valueCount == 0)
|
||||
|
|
|
@ -1371,27 +1371,30 @@ 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(char const* str, char const* const end, number_range& range)
|
||||
static bool parseNumberSection(std::string_view str, number_range& range)
|
||||
{
|
||||
bool success;
|
||||
auto const error = errno;
|
||||
|
||||
#if defined(HAVE_CHARCONV)
|
||||
auto result = std::from_chars(str, end, range.low);
|
||||
// wants char*, so string_view::iterator don't work. make our own begin/end
|
||||
auto const* const begin_ch = std::data(str);
|
||||
auto const* const end_ch = begin_ch + std::size(str);
|
||||
auto result = std::from_chars(begin_ch, end_ch, range.low);
|
||||
success = result.ec == std::errc{};
|
||||
if (success)
|
||||
{
|
||||
range.high = range.low;
|
||||
if (result.ptr != end && *result.ptr == '-')
|
||||
if (result.ptr < end_ch && *result.ptr == '-')
|
||||
{
|
||||
result = std::from_chars(result.ptr + 1, end, range.high);
|
||||
result = std::from_chars(result.ptr + 1, end_ch, range.high);
|
||||
success = result.ec == std::errc{};
|
||||
}
|
||||
}
|
||||
#else
|
||||
try
|
||||
{
|
||||
auto tmp = std::string(str, end);
|
||||
auto tmp = std::string(str);
|
||||
auto pos = size_t{};
|
||||
range.low = range.high = std::stoi(tmp, &pos);
|
||||
if (pos != std::size(tmp) && tmp[pos] == '-')
|
||||
|
@ -1418,26 +1421,27 @@ static bool parseNumberSection(char const* str, char const* const end, number_ra
|
|||
* 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(char const* str, size_t len) // TODO: string_view
|
||||
std::vector<int> tr_parseNumberRange(std::string_view str)
|
||||
{
|
||||
auto values = std::set<int>{};
|
||||
|
||||
auto const* const end = str + (len != TR_BAD_SIZE ? len : strlen(str));
|
||||
for (auto const* walk = str; walk < end;)
|
||||
for (;;)
|
||||
{
|
||||
auto delim = std::find(walk, end, ',');
|
||||
auto const delim = str.find(',');
|
||||
auto range = number_range{};
|
||||
if (!parseNumberSection(walk, delim, range))
|
||||
if (!parseNumberSection(str.substr(0, delim), range))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto i = range.low; i <= range.high; ++i)
|
||||
{
|
||||
values.insert(i);
|
||||
}
|
||||
|
||||
walk = delim + 1;
|
||||
if (delim == std::string_view::npos)
|
||||
{
|
||||
break;
|
||||
}
|
||||
str.remove_prefix(delim + 1);
|
||||
}
|
||||
|
||||
return { std::begin(values), std::end(values) };
|
||||
|
|
|
@ -286,7 +286,7 @@ double tr_getRatio(uint64_t numerator, uint64_t denominator);
|
|||
*
|
||||
* For example, "5-8" will return [ 5, 6, 7, 8 ] and setmeCount will be 4.
|
||||
*/
|
||||
std::vector<int> tr_parseNumberRange(char const* str, size_t str_len) TR_GNUC_NONNULL(1);
|
||||
std::vector<int> tr_parseNumberRange(std::string_view str);
|
||||
|
||||
/**
|
||||
* @brief truncate a double value at a given number of decimal places.
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <string_view>
|
||||
#include <typeinfo>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define setenv(key, value, unused) SetEnvironmentVariableA(key, value)
|
||||
|
@ -30,8 +33,8 @@
|
|||
#include <string>
|
||||
|
||||
using ::libtransmission::test::makeString;
|
||||
|
||||
using UtilsTest = ::testing::Test;
|
||||
using namespace std::literals;
|
||||
|
||||
TEST_F(UtilsTest, trStripPositionalArgs)
|
||||
{
|
||||
|
@ -125,20 +128,20 @@ TEST_F(UtilsTest, numbers)
|
|||
return ss.str();
|
||||
};
|
||||
|
||||
auto numbers = tr_parseNumberRange("1-10,13,16-19", TR_BAD_SIZE);
|
||||
auto numbers = tr_parseNumberRange("1-10,13,16-19"sv);
|
||||
EXPECT_EQ(std::string("1 2 3 4 5 6 7 8 9 10 13 16 17 18 19 "), tostring(numbers));
|
||||
|
||||
numbers = tr_parseNumberRange("1-5,3-7,2-6", TR_BAD_SIZE);
|
||||
numbers = tr_parseNumberRange("1-5,3-7,2-6"sv);
|
||||
EXPECT_EQ(std::string("1 2 3 4 5 6 7 "), tostring(numbers));
|
||||
|
||||
numbers = tr_parseNumberRange("1-Hello", TR_BAD_SIZE);
|
||||
numbers = tr_parseNumberRange("1-Hello"sv);
|
||||
auto const empty_string = std::string{};
|
||||
EXPECT_EQ(empty_string, tostring(numbers));
|
||||
|
||||
numbers = tr_parseNumberRange("1-", TR_BAD_SIZE);
|
||||
numbers = tr_parseNumberRange("1-"sv);
|
||||
EXPECT_EQ(empty_string, tostring(numbers));
|
||||
|
||||
numbers = tr_parseNumberRange("Hello", TR_BAD_SIZE);
|
||||
numbers = tr_parseNumberRange("Hello"sv);
|
||||
EXPECT_EQ(empty_string, tostring(numbers));
|
||||
}
|
||||
|
||||
|
|
|
@ -645,7 +645,7 @@ static void addDays(tr_variant* args, tr_quark const key, char const* arg)
|
|||
|
||||
if (arg != nullptr)
|
||||
{
|
||||
for (int& day : tr_parseNumberRange(arg, TR_BAD_SIZE))
|
||||
for (int& day : tr_parseNumberRange(arg))
|
||||
{
|
||||
if (day < 0 || day > 7)
|
||||
{
|
||||
|
@ -706,7 +706,7 @@ static void addFiles(tr_variant* args, tr_quark const key, char const* arg)
|
|||
|
||||
if (strcmp(arg, "all") != 0)
|
||||
{
|
||||
for (auto const& idx : tr_parseNumberRange(arg, TR_BAD_SIZE))
|
||||
for (auto const& idx : tr_parseNumberRange(arg))
|
||||
{
|
||||
tr_variantListAddInt(files, idx);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue