db/Interface: CollectUniqueTags() allows multiple "groups"

Instead of passing tag and group, pass an array of tags.  To support a
nested return value, return a nested std::map of std::maps.  Each key
specifies the tag value, and each value may be another nesting level.

Closes https://github.com/MusicPlayerDaemon/MPD/issues/408
This commit is contained in:
Max Kellermann
2018-11-19 11:17:25 +01:00
committed by Max Kellermann
parent 923c1b6220
commit 1eae9339f2
12 changed files with 166 additions and 123 deletions

View File

@@ -266,7 +266,7 @@ handle_list(Client &client, Request args, Response &r)
}
std::unique_ptr<SongFilter> filter;
TagType group = TAG_NUM_OF_ITEM_TYPES;
std::vector<TagType> tag_types;
if (args.size == 1 &&
/* parantheses are the syntax for filter expressions: no
@@ -284,20 +284,31 @@ handle_list(Client &client, Request args, Response &r)
args.shift()));
}
if (args.size >= 2 &&
StringIsEqual(args[args.size - 2], "group")) {
while (args.size >= 2 &&
StringIsEqual(args[args.size - 2], "group")) {
const char *s = args[args.size - 1];
group = tag_name_parse_i(s);
const auto group = tag_name_parse_i(s);
if (group == TAG_NUM_OF_ITEM_TYPES) {
r.FormatError(ACK_ERROR_ARG,
"Unknown tag type: %s", s);
return CommandResult::ERROR;
}
if (group == tagType ||
std::find(tag_types.begin(), tag_types.end(),
group) != tag_types.end()) {
r.Error(ACK_ERROR_ARG, "Conflicting group");
return CommandResult::ERROR;
}
tag_types.emplace_back(group);
args.pop_back();
args.pop_back();
}
tag_types.emplace_back(tagType);
if (!args.empty()) {
filter.reset(new SongFilter());
try {
@@ -310,13 +321,9 @@ handle_list(Client &client, Request args, Response &r)
filter->Optimize();
}
if (tagType < TAG_NUM_OF_ITEM_TYPES && tagType == group) {
r.Error(ACK_ERROR_ARG, "Conflicting group");
return CommandResult::ERROR;
}
PrintUniqueTags(r, client.GetPartition(),
tagType, group, filter.get());
{&tag_types.front(), tag_types.size()},
filter.get());
return CommandResult::OK;
}