protocol/ArgParser: add struct RangeArg

This commit is contained in:
Max Kellermann 2015-08-11 21:35:52 +02:00
parent 993df0fd28
commit cbdc3194cc
6 changed files with 60 additions and 51 deletions

View File

@ -67,15 +67,15 @@ handle_lsinfo2(Client &client, ConstBuffer<const char *> args)
static CommandResult static CommandResult
handle_match(Client &client, ConstBuffer<const char *> args, bool fold_case) handle_match(Client &client, ConstBuffer<const char *> args, bool fold_case)
{ {
unsigned window_start = 0, window_end = std::numeric_limits<int>::max(); RangeArg window;
if (args.size >= 2 && strcmp(args[args.size - 2], "window") == 0) { if (args.size >= 2 && strcmp(args[args.size - 2], "window") == 0) {
if (!check_range(client, &window_start, &window_end, if (!ParseCommandArg(client, window, args.back()))
args.back()))
return CommandResult::ERROR; return CommandResult::ERROR;
args.pop_back(); args.pop_back();
args.pop_back(); args.pop_back();
} } else
window.SetAll();
SongFilter filter; SongFilter filter;
if (!filter.Parse(args, fold_case)) { if (!filter.Parse(args, fold_case)) {
@ -87,7 +87,7 @@ handle_match(Client &client, ConstBuffer<const char *> args, bool fold_case)
Error error; Error error;
return db_selection_print(client, selection, true, false, return db_selection_print(client, selection, true, false,
window_start, window_end, error) window.start, window.end, error)
? CommandResult::OK ? CommandResult::OK
: print_error(client, error); : print_error(client, error);
} }

View File

@ -70,12 +70,10 @@ handle_save(Client &client, ConstBuffer<const char *> args)
CommandResult CommandResult
handle_load(Client &client, ConstBuffer<const char *> args) handle_load(Client &client, ConstBuffer<const char *> args)
{ {
unsigned start_index, end_index; RangeArg range;
if (args.size < 2)
if (args.size < 2) { range.SetAll();
start_index = 0; else if (!ParseCommandArg(client, range, args[1]))
end_index = unsigned(-1);
} else if (!check_range(client, &start_index, &end_index, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
const ScopeBulkEdit bulk_edit(client.partition); const ScopeBulkEdit bulk_edit(client.partition);
@ -83,7 +81,7 @@ handle_load(Client &client, ConstBuffer<const char *> args)
Error error; Error error;
const SongLoader loader(client); const SongLoader loader(client);
if (!playlist_open_into_queue(args.front(), if (!playlist_open_into_queue(args.front(),
start_index, end_index, range.start, range.end,
client.playlist, client.playlist,
client.player_control, loader, error)) client.player_control, loader, error))
return print_error(client, error); return print_error(client, error);

View File

@ -175,12 +175,11 @@ handle_rangeid(Client &client, ConstBuffer<const char *> args)
CommandResult CommandResult
handle_delete(Client &client, ConstBuffer<const char *> args) handle_delete(Client &client, ConstBuffer<const char *> args)
{ {
unsigned start, end; RangeArg range;
if (!ParseCommandArg(client, range, args.front()))
if (!check_range(client, &start, &end, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = client.partition.DeleteRange(start, end); auto result = client.partition.DeleteRange(range.start, range.end);
return print_playlist_result(client, result); return print_playlist_result(client, result);
} }
@ -206,11 +205,13 @@ handle_playlist(Client &client, gcc_unused ConstBuffer<const char *> args)
CommandResult CommandResult
handle_shuffle(gcc_unused Client &client, ConstBuffer<const char *> args) handle_shuffle(gcc_unused Client &client, ConstBuffer<const char *> args)
{ {
unsigned start = 0, end = client.playlist.queue.GetLength(); RangeArg range;
if (args.size == 1 && !check_range(client, &start, &end, args.front())) if (args.IsEmpty())
range.SetAll();
else if (!ParseCommandArg(client, range, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
client.partition.Shuffle(start, end); client.partition.Shuffle(range.start, range.end);
return CommandResult::OK; return CommandResult::OK;
} }
@ -248,12 +249,14 @@ handle_plchangesposid(Client &client, ConstBuffer<const char *> args)
CommandResult CommandResult
handle_playlistinfo(Client &client, ConstBuffer<const char *> args) handle_playlistinfo(Client &client, ConstBuffer<const char *> args)
{ {
unsigned start = 0, end = std::numeric_limits<unsigned>::max(); RangeArg range;
if (args.IsEmpty())
if (args.size == 1 && !check_range(client, &start, &end, args.front())) range.SetAll();
else if (!ParseCommandArg(client, range, args.front()))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!playlist_print_info(client, client.playlist, start, end)) if (!playlist_print_info(client, client.playlist,
range.start, range.end))
return print_playlist_result(client, return print_playlist_result(client,
PlaylistResult::BAD_RANGE); PlaylistResult::BAD_RANGE);
@ -322,14 +325,14 @@ handle_prio(Client &client, ConstBuffer<const char *> args)
} }
for (const char *i : args) { for (const char *i : args) {
unsigned start_position, end_position; RangeArg range;
if (!check_range(client, &start_position, &end_position, i)) if (!ParseCommandArg(client, range, i))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = PlaylistResult result =
client.partition.SetPriorityRange(start_position, client.partition.SetPriorityRange(range.start,
end_position, range.end,
priority); priority);
if (result != PlaylistResult::SUCCESS) if (result != PlaylistResult::SUCCESS)
return print_playlist_result(client, result); return print_playlist_result(client, result);
} }
@ -369,16 +372,16 @@ handle_prioid(Client &client, ConstBuffer<const char *> args)
CommandResult CommandResult
handle_move(Client &client, ConstBuffer<const char *> args) handle_move(Client &client, ConstBuffer<const char *> args)
{ {
unsigned start, end; RangeArg range;
int to; int to;
if (!check_range(client, &start, &end, args[0])) if (!ParseCommandArg(client, range, args[0]))
return CommandResult::ERROR; return CommandResult::ERROR;
if (!check_int(client, &to, args[1])) if (!check_int(client, &to, args[1]))
return CommandResult::ERROR; return CommandResult::ERROR;
PlaylistResult result = PlaylistResult result =
client.partition.MoveRange(start, end, to); client.partition.MoveRange(range.start, range.end, to);
return print_playlist_result(client, result); return print_playlist_result(client, result);
} }

View File

@ -65,8 +65,7 @@ check_int(Client &client, int *value_r, const char *s)
} }
bool bool
check_range(Client &client, unsigned *value_r1, unsigned *value_r2, ParseCommandArg(Client &client, RangeArg &value_r, const char *s)
const char *s)
{ {
char *test, *test2; char *test, *test2;
long value; long value;
@ -81,8 +80,8 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
if (value == -1 && *test == 0) { if (value == -1 && *test == 0) {
/* compatibility with older MPD versions: specifying /* compatibility with older MPD versions: specifying
"-1" makes MPD display the whole list */ "-1" makes MPD display the whole list */
*value_r1 = 0; value_r.start = 0;
*value_r2 = std::numeric_limits<int>::max(); value_r.end = std::numeric_limits<int>::max();
return true; return true;
} }
@ -98,7 +97,7 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
return false; return false;
} }
*value_r1 = (unsigned)value; value_r.start = (unsigned)value;
if (*test == ':') { if (*test == ':') {
value = strtol(++test, &test2, 10); value = strtol(++test, &test2, 10);
@ -123,9 +122,9 @@ check_range(Client &client, unsigned *value_r1, unsigned *value_r2,
return false; return false;
} }
*value_r2 = (unsigned)value; value_r.end = (unsigned)value;
} else { } else {
*value_r2 = (unsigned)value + 1; value_r.end = (unsigned)value + 1;
} }
return true; return true;

View File

@ -34,9 +34,17 @@ check_uint32(Client &client, uint32_t *dst, const char *s);
bool bool
check_int(Client &client, int *value_r, const char *s); check_int(Client &client, int *value_r, const char *s);
struct RangeArg {
unsigned start, end;
void SetAll() {
start = 0;
end = unsigned(-1);
}
};
bool bool
check_range(Client &client, unsigned *value_r1, unsigned *value_r2, ParseCommandArg(Client &client, RangeArg &value_r, const char *s);
const char *s);
bool bool
check_unsigned(Client &client, unsigned *value_r, const char *s); check_unsigned(Client &client, unsigned *value_r, const char *s);

View File

@ -32,21 +32,22 @@ void
ArgParserTest::TestRange() ArgParserTest::TestRange()
{ {
Client &client = *(Client *)nullptr; Client &client = *(Client *)nullptr;
unsigned a, b;
CPPUNIT_ASSERT(check_range(client, &a, &b, "1")); RangeArg range;
CPPUNIT_ASSERT_EQUAL(1u, a);
CPPUNIT_ASSERT_EQUAL(2u, b);
CPPUNIT_ASSERT(check_range(client, &a, &b, "1:5")); CPPUNIT_ASSERT(ParseCommandArg(client, range, "1"));
CPPUNIT_ASSERT_EQUAL(1u, a); CPPUNIT_ASSERT_EQUAL(1u, range.start);
CPPUNIT_ASSERT_EQUAL(5u, b); CPPUNIT_ASSERT_EQUAL(2u, range.end);
CPPUNIT_ASSERT(check_range(client, &a, &b, "1:")); CPPUNIT_ASSERT(ParseCommandArg(client, range, "1:5"));
CPPUNIT_ASSERT_EQUAL(1u, a); CPPUNIT_ASSERT_EQUAL(1u, range.start);
CPPUNIT_ASSERT(b >= 999999u); CPPUNIT_ASSERT_EQUAL(5u, range.end);
CPPUNIT_ASSERT(!check_range(client, &a, &b, "-2")); CPPUNIT_ASSERT(ParseCommandArg(client, range, "1:"));
CPPUNIT_ASSERT_EQUAL(1u, range.start);
CPPUNIT_ASSERT(range.end >= 999999u);
CPPUNIT_ASSERT(!ParseCommandArg(client, range, "-2"));
CPPUNIT_ASSERT_EQUAL(ACK_ERROR_ARG, last_error); CPPUNIT_ASSERT_EQUAL(ACK_ERROR_ARG, last_error);
} }