From 7a55ab6acc307d1023c3f1b87f2c0b28ab6c37fb Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 18 Dec 2017 21:50:14 +0100 Subject: [PATCH] db/DatabasePrint: support descending sort --- doc/protocol.xml | 4 +++- src/command/DatabaseCommands.cxx | 11 +++++++++-- src/db/DatabasePrint.cxx | 17 ++++++++++++----- src/db/DatabasePrint.hxx | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/doc/protocol.xml b/doc/protocol.xml index 1f0ab7eb9..480fbf90a 100644 --- a/doc/protocol.xml +++ b/doc/protocol.xml @@ -1693,7 +1693,9 @@ OK sort sorts the result by the - specified tag. Without sort, the + specified tag. The sort is descending if the tag is + prefixed with a minus ('-'). + Without sort, the order is undefined. Only the first tag value will be used, if multiple of the same type exist. To sort by "Artist", "Album" or "AlbumArtist", you should specify diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx index aad7d3a4c..a6e56dfc6 100644 --- a/src/command/DatabaseCommands.cxx +++ b/src/command/DatabaseCommands.cxx @@ -68,8 +68,15 @@ handle_match(Client &client, Request args, Response &r, bool fold_case) window.SetAll(); TagType sort = TAG_NUM_OF_ITEM_TYPES; + bool descending = false; 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) 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(), selection, true, false, - sort, + sort, descending, window.start, window.end); return CommandResult::OK; } diff --git a/src/db/DatabasePrint.cxx b/src/db/DatabasePrint.cxx index fd8f72e18..a8f32aeb1 100644 --- a/src/db/DatabasePrint.cxx +++ b/src/db/DatabasePrint.cxx @@ -149,11 +149,16 @@ CompareNumeric(const char *a, const char *b) } 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 *b_value = b.GetSortValue(type); + if (descending) { + using std::swap; + swap(a_value, b_value); + } + switch (type) { case TAG_DISC: case TAG_TRACK: @@ -168,7 +173,7 @@ void db_selection_print(Response &r, Partition &partition, const DatabaseSelection &selection, bool full, bool base, - TagType sort, + TagType sort, bool descending, unsigned window_start, unsigned window_end) { const Database &db = partition.GetDatabaseOrThrow(); @@ -216,8 +221,10 @@ db_selection_print(Response &r, Partition &partition, } std::stable_sort(songs.begin(), songs.end(), - [sort](const DetachedSong &a, const DetachedSong &b){ - return CompareTags(sort, a.GetTag(), + [sort, descending](const DetachedSong &a, + const DetachedSong &b){ + return CompareTags(sort, descending, + a.GetTag(), b.GetTag()); }); @@ -242,7 +249,7 @@ db_selection_print(Response &r, Partition &partition, bool full, bool base) { db_selection_print(r, partition, selection, full, base, - TAG_NUM_OF_ITEM_TYPES, + TAG_NUM_OF_ITEM_TYPES, false, 0, std::numeric_limits::max()); } diff --git a/src/db/DatabasePrint.hxx b/src/db/DatabasePrint.hxx index e0a27674d..7612b9319 100644 --- a/src/db/DatabasePrint.hxx +++ b/src/db/DatabasePrint.hxx @@ -42,7 +42,7 @@ void db_selection_print(Response &r, Partition &partition, const DatabaseSelection &selection, bool full, bool base, - TagType sort, + TagType sort, bool descending, unsigned window_start, unsigned window_end); void