db/DatabasePrint: support descending sort

This commit is contained in:
Max Kellermann 2017-12-18 21:50:14 +01:00
parent 6246d36fe6
commit 7a55ab6acc
4 changed files with 25 additions and 9 deletions

View File

@ -1693,7 +1693,9 @@ OK
<para> <para>
<varname>sort</varname> sorts the result by the <varname>sort</varname> sorts the result by the
specified tag. Without <varname>sort</varname>, the specified tag. The sort is descending if the tag is
prefixed with a minus ('-').
Without <varname>sort</varname>, the
order is undefined. Only the first tag value will be order is undefined. Only the first tag value will be
used, if multiple of the same type exist. To sort by used, if multiple of the same type exist. To sort by
"Artist", "Album" or "AlbumArtist", you should specify "Artist", "Album" or "AlbumArtist", you should specify

View File

@ -68,8 +68,15 @@ handle_match(Client &client, Request args, Response &r, bool fold_case)
window.SetAll(); window.SetAll();
TagType sort = TAG_NUM_OF_ITEM_TYPES; TagType sort = TAG_NUM_OF_ITEM_TYPES;
bool descending = false;
if (args.size >= 2 && StringIsEqual(args[args.size - 2], "sort")) { if (args.size >= 2 && StringIsEqual(args[args.size - 2], "sort")) {
sort = tag_name_parse_i(args.back()); const char *s = args.back();
if (*s == '-') {
descending = true;
++s;
}
sort = tag_name_parse_i(s);
if (sort == TAG_NUM_OF_ITEM_TYPES) if (sort == TAG_NUM_OF_ITEM_TYPES)
throw ProtocolError(ACK_ERROR_ARG, "Unknown sort tag"); throw ProtocolError(ACK_ERROR_ARG, "Unknown sort tag");
@ -87,7 +94,7 @@ handle_match(Client &client, Request args, Response &r, bool fold_case)
db_selection_print(r, client.GetPartition(), db_selection_print(r, client.GetPartition(),
selection, true, false, selection, true, false,
sort, sort, descending,
window.start, window.end); window.start, window.end);
return CommandResult::OK; return CommandResult::OK;
} }

View File

@ -149,11 +149,16 @@ CompareNumeric(const char *a, const char *b)
} }
static bool static bool
CompareTags(TagType type, const Tag &a, const Tag &b) CompareTags(TagType type, bool descending, const Tag &a, const Tag &b)
{ {
const char *a_value = a.GetSortValue(type); const char *a_value = a.GetSortValue(type);
const char *b_value = b.GetSortValue(type); const char *b_value = b.GetSortValue(type);
if (descending) {
using std::swap;
swap(a_value, b_value);
}
switch (type) { switch (type) {
case TAG_DISC: case TAG_DISC:
case TAG_TRACK: case TAG_TRACK:
@ -168,7 +173,7 @@ void
db_selection_print(Response &r, Partition &partition, db_selection_print(Response &r, Partition &partition,
const DatabaseSelection &selection, const DatabaseSelection &selection,
bool full, bool base, bool full, bool base,
TagType sort, TagType sort, bool descending,
unsigned window_start, unsigned window_end) unsigned window_start, unsigned window_end)
{ {
const Database &db = partition.GetDatabaseOrThrow(); const Database &db = partition.GetDatabaseOrThrow();
@ -216,8 +221,10 @@ db_selection_print(Response &r, Partition &partition,
} }
std::stable_sort(songs.begin(), songs.end(), std::stable_sort(songs.begin(), songs.end(),
[sort](const DetachedSong &a, const DetachedSong &b){ [sort, descending](const DetachedSong &a,
return CompareTags(sort, a.GetTag(), const DetachedSong &b){
return CompareTags(sort, descending,
a.GetTag(),
b.GetTag()); b.GetTag());
}); });
@ -242,7 +249,7 @@ db_selection_print(Response &r, Partition &partition,
bool full, bool base) bool full, bool base)
{ {
db_selection_print(r, partition, selection, full, base, db_selection_print(r, partition, selection, full, base,
TAG_NUM_OF_ITEM_TYPES, TAG_NUM_OF_ITEM_TYPES, false,
0, std::numeric_limits<int>::max()); 0, std::numeric_limits<int>::max());
} }

View File

@ -42,7 +42,7 @@ void
db_selection_print(Response &r, Partition &partition, db_selection_print(Response &r, Partition &partition,
const DatabaseSelection &selection, const DatabaseSelection &selection,
bool full, bool base, bool full, bool base,
TagType sort, TagType sort, bool descending,
unsigned window_start, unsigned window_end); unsigned window_start, unsigned window_end);
void void