Merge branch 'v0.20.x'

This commit is contained in:
Max Kellermann
2018-01-20 00:04:35 +01:00
10 changed files with 98 additions and 35 deletions

View File

@@ -25,6 +25,8 @@
#include "util/ChronoUtil.hxx"
#include "util/ConstBuffer.hxx"
#include "util/StringAPI.hxx"
#include "util/StringCompare.hxx"
#include "util/StringView.hxx"
#include "util/ASCII.hxx"
#include "util/TimeParser.hxx"
#include "util/UriUtil.hxx"
@@ -60,7 +62,7 @@ locate_parse_type(const char *str) noexcept
SongFilter::Item::Item(unsigned _tag, const char *_value, bool _fold_case)
:tag(_tag),
value(AllocatedString<>::Duplicate(_value)),
value(_value),
fold_case(_fold_case ? IcuCompare(value.c_str()) : IcuCompare())
{
}
@@ -275,3 +277,33 @@ SongFilter::GetBase() const noexcept
return nullptr;
}
SongFilter
SongFilter::WithoutBasePrefix(const char *_prefix) const noexcept
{
const StringView prefix(_prefix);
SongFilter result;
for (const auto &i : items) {
if (i.GetTag() == LOCATE_TAG_BASE_TYPE) {
const char *s = StringAfterPrefix(i.GetValue(), prefix);
if (s != nullptr) {
if (*s == 0)
continue;
if (*s == '/') {
++s;
if (*s != 0)
result.items.emplace_back(LOCATE_TAG_BASE_TYPE, s);
continue;
}
}
}
result.items.emplace_back(i);
}
return result;
}

View File

@@ -21,9 +21,9 @@
#define MPD_SONG_FILTER_HXX
#include "lib/icu/Compare.hxx"
#include "util/AllocatedString.hxx"
#include "Compiler.h"
#include <string>
#include <list>
#include <chrono>
@@ -54,7 +54,7 @@ public:
class Item {
uint8_t tag;
AllocatedString<> value;
std::string value;
/**
* This value is only set if case folding is enabled.
@@ -71,11 +71,6 @@ public:
Item(unsigned tag, const char *value, bool fold_case=false);
Item(unsigned tag, std::chrono::system_clock::time_point time);
Item(const Item &other) = delete;
Item(Item &&) = default;
Item &operator=(const Item &other) = delete;
unsigned GetTag() const {
return tag;
}
@@ -162,6 +157,13 @@ public:
*/
gcc_pure
const char *GetBase() const noexcept;
/**
* Create a copy of the filter with the given prefix stripped
* from all #LOCATE_TAG_BASE_TYPE items. This is used to
* filter songs in mounted databases.
*/
SongFilter WithoutBasePrefix(const char *prefix) const noexcept;
};
/**

View File

@@ -20,18 +20,12 @@
#include "config.h"
#include "Mount.hxx"
#include "PrefixedLightSong.hxx"
#include "SongFilter.hxx"
#include "db/Selection.hxx"
#include "db/LightDirectory.hxx"
#include "db/Interface.hxx"
#include "fs/Traits.hxx"
#ifdef _LIBCPP_VERSION
/* workaround for "error: incomplete type 'PlaylistInfo' used in type
trait expression" with libc++ version 3900 (from Android NDK
r13b) */
#include "db/PlaylistInfo.hxx"
#endif
#include <string>
struct PrefixedLightDirectory : LightDirectory {
@@ -93,5 +87,16 @@ WalkMount(const char *base, const Database &db,
vp = std::bind(PrefixVisitPlaylist,
base, std::ref(visit_playlist), _1, _2);
SongFilter prefix_filter;
if (base != nullptr && filter != nullptr) {
/* if the SongFilter contains a LOCATE_TAG_BASE_TYPE
item, copy the SongFilter and drop the mount point
from the filter, because the mounted database
doesn't know its own location within MPD's VFS */
prefix_filter = filter->WithoutBasePrefix(base);
filter = &prefix_filter;
}
db.Visit(DatabaseSelection(uri, recursive, filter), vd, vs, vp);
}

View File

@@ -37,6 +37,18 @@ public:
explicit IcuCompare(const char *needle) noexcept;
IcuCompare(const IcuCompare &src) noexcept
:needle(src
? AllocatedString<>::Duplicate(src.needle.c_str())
: nullptr) {}
IcuCompare &operator=(const IcuCompare &src) noexcept {
needle = src
? AllocatedString<>::Duplicate(src.needle.c_str())
: nullptr;
return *this;
}
IcuCompare(IcuCompare &&) = default;
IcuCompare &operator=(IcuCompare &&) = default;