summaryrefslogtreecommitdiff
path: root/src/tag
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-10-22 18:19:04 +0200
committerMax Kellermann <max@musicpd.org>2018-10-22 18:20:29 +0200
commit66ab2de5785755594b300b933083a0e5892d05fc (patch)
treea0e1dfa192d357a3749acf53dfc04876fcfcf4ef /src/tag
parente28d1e0f65fb47f452934bc5d70fdb40bdc4c62e (diff)
parentdb27bb76e280c69d70bc14f0b0161e89d496a3c8 (diff)
Merge branch 'v0.20.x'
Diffstat (limited to 'src/tag')
-rw-r--r--src/tag/Builder.cxx29
-rw-r--r--src/tag/Builder.hxx6
-rw-r--r--src/tag/Fallback.hxx53
-rw-r--r--src/tag/Set.cxx114
-rw-r--r--src/tag/Set.hxx74
-rw-r--r--src/tag/VisitFallback.hxx60
-rw-r--r--src/tag/meson.build1
7 files changed, 134 insertions, 203 deletions
diff --git a/src/tag/Builder.cxx b/src/tag/Builder.cxx
index 1bcdb5bda..85a77131b 100644
--- a/src/tag/Builder.cxx
+++ b/src/tag/Builder.cxx
@@ -186,6 +186,19 @@ TagBuilder::Complement(const Tag &other) noexcept
}
}
+void
+TagBuilder::AddItemUnchecked(TagType type, StringView value) noexcept
+{
+ TagItem *i;
+
+ {
+ const std::lock_guard<Mutex> protect(tag_pool_lock);
+ i = tag_pool_get_item(type, value);
+ }
+
+ items.push_back(i);
+}
+
inline void
TagBuilder::AddItemInternal(TagType type, StringView value) noexcept
{
@@ -195,15 +208,9 @@ TagBuilder::AddItemInternal(TagType type, StringView value) noexcept
if (!f.IsNull())
value = { f.data, f.size };
- TagItem *i;
- {
- const std::lock_guard<Mutex> protect(tag_pool_lock);
- i = tag_pool_get_item(type, value);
- }
+ AddItemUnchecked(type, value);
free(f.data);
-
- items.push_back(i);
}
void
@@ -229,13 +236,7 @@ TagBuilder::AddItem(TagType type, const char *value) noexcept
void
TagBuilder::AddEmptyItem(TagType type) noexcept
{
- TagItem *i;
- {
- const std::lock_guard<Mutex> protect(tag_pool_lock);
- i = tag_pool_get_item(type, "");
- }
-
- items.push_back(i);
+ AddItemUnchecked(type, "");
}
void
diff --git a/src/tag/Builder.hxx b/src/tag/Builder.hxx
index 136e0e745..dbf4cddb8 100644
--- a/src/tag/Builder.hxx
+++ b/src/tag/Builder.hxx
@@ -133,6 +133,12 @@ public:
void Complement(const Tag &other) noexcept;
/**
+ * A variant of AddItem() which does not attempt to fix up the
+ * value and does not check whether the tag type is disabled.
+ */
+ void AddItemUnchecked(TagType type, StringView value) noexcept;
+
+ /**
* Appends a new tag item.
*
* @param type the type of the new tag item
diff --git a/src/tag/Fallback.hxx b/src/tag/Fallback.hxx
new file mode 100644
index 000000000..08e4dc80a
--- /dev/null
+++ b/src/tag/Fallback.hxx
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2003-2018 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_TAG_FALLBACK_HXX
+#define MPD_TAG_FALLBACK_HXX
+
+#include <utility>
+
+template<typename F>
+bool
+ApplyTagFallback(TagType type, F &&f) noexcept
+{
+ if (type == TAG_ALBUM_ARTIST_SORT) {
+ /* fall back to "AlbumArtist", "ArtistSort" and
+ "Artist" if no "AlbumArtistSort" was found */
+ if (f(TAG_ALBUM_ARTIST))
+ return true;
+
+ return ApplyTagFallback(TAG_ARTIST_SORT, std::forward<F>(f));
+ }
+
+ if (type == TAG_ALBUM_ARTIST || type == TAG_ARTIST_SORT)
+ /* fall back to "Artist" if no
+ "AlbumArtist"/"ArtistSort" was found */
+ return f(TAG_ARTIST);
+
+ return false;
+}
+
+template<typename F>
+bool
+ApplyTagWithFallback(TagType type, F &&f) noexcept
+{
+ return f(type) || ApplyTagFallback(type, std::forward<F>(f));
+}
+
+#endif
diff --git a/src/tag/Set.cxx b/src/tag/Set.cxx
deleted file mode 100644
index 0009173bb..000000000
--- a/src/tag/Set.cxx
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2003-2017 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "Set.hxx"
-#include "Builder.hxx"
-#include "Mask.hxx"
-#include "Settings.hxx"
-
-#include <assert.h>
-
-/**
- * Copy all tag items of the specified type.
- */
-static bool
-CopyTagItem(TagBuilder &dest, TagType dest_type,
- const Tag &src, TagType src_type)
-{
- bool found = false;
-
- for (const auto &item : src) {
- if (item.type == src_type) {
- dest.AddItem(dest_type, item.value);
- found = true;
- }
- }
-
- return found;
-}
-
-/**
- * Copy all tag items of the specified type. Fall back to "Artist" if
- * there is no "AlbumArtist".
- */
-static void
-CopyTagItem(TagBuilder &dest, const Tag &src, TagType type)
-{
- if (!CopyTagItem(dest, type, src, type) &&
- type == TAG_ALBUM_ARTIST)
- CopyTagItem(dest, type, src, TAG_ARTIST);
-}
-
-/**
- * Copy all tag items of the types in the mask.
- */
-static void
-CopyTagMask(TagBuilder &dest, const Tag &src, TagMask mask)
-{
- for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i)
- if (mask.Test(TagType(i)))
- CopyTagItem(dest, src, TagType(i));
-}
-
-void
-TagSet::InsertUnique(const Tag &src, TagType type, const char *value,
- TagMask group_mask) noexcept
-{
- TagBuilder builder;
- if (value == nullptr)
- builder.AddEmptyItem(type);
- else
- builder.AddItem(type, value);
- CopyTagMask(builder, src, group_mask);
- emplace(builder.Commit());
-}
-
-bool
-TagSet::CheckUnique(TagType dest_type,
- const Tag &tag, TagType src_type,
- TagMask group_mask) noexcept
-{
- bool found = false;
-
- for (const auto &item : tag) {
- if (item.type == src_type) {
- InsertUnique(tag, dest_type, item.value, group_mask);
- found = true;
- }
- }
-
- return found;
-}
-
-void
-TagSet::InsertUnique(const Tag &tag,
- TagType type, TagMask group_mask) noexcept
-{
- static_assert(sizeof(group_mask) * 8 >= TAG_NUM_OF_ITEM_TYPES,
- "Mask is too small");
-
- assert(!group_mask.Test(type));
-
- if (!CheckUnique(type, tag, type, group_mask) &&
- (type != TAG_ALBUM_ARTIST ||
- !IsTagEnabled(TAG_ALBUM_ARTIST) ||
- /* fall back to "Artist" if no "AlbumArtist" was found */
- !CheckUnique(type, tag, TAG_ARTIST, group_mask)))
- InsertUnique(tag, type, nullptr, group_mask);
-}
diff --git a/src/tag/Set.hxx b/src/tag/Set.hxx
deleted file mode 100644
index e74d145f4..000000000
--- a/src/tag/Set.hxx
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2003-2017 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPD_TAG_SET_HXX
-#define MPD_TAG_SET_HXX
-
-#include "util/Compiler.h"
-#include "Tag.hxx"
-
-#include <set>
-
-#include <string.h>
-
-class TagMask;
-
-/**
- * Helper class for #TagSet which compares two #Tag objects.
- */
-struct TagLess {
- gcc_pure
- bool operator()(const Tag &a, const Tag &b) const noexcept {
- if (a.num_items != b.num_items)
- return a.num_items < b.num_items;
-
- const unsigned n = a.num_items;
- for (unsigned i = 0; i < n; ++i) {
- const TagItem &ai = *a.items[i];
- const TagItem &bi = *b.items[i];
- if (ai.type != bi.type)
- return unsigned(ai.type) < unsigned(bi.type);
-
- const int cmp = strcmp(ai.value, bi.value);
- if (cmp != 0)
- return cmp < 0;
- }
-
- return false;
- }
-};
-
-/**
- * A set of #Tag objects.
- */
-class TagSet : public std::set<Tag, TagLess> {
-public:
- void InsertUnique(const Tag &tag,
- TagType type, TagMask group_mask) noexcept;
-
-private:
- void InsertUnique(const Tag &src, TagType type, const char *value,
- TagMask group_mask) noexcept;
-
- bool CheckUnique(TagType dest_type,
- const Tag &tag, TagType src_type,
- TagMask group_mask) noexcept;
-};
-
-#endif
diff --git a/src/tag/VisitFallback.hxx b/src/tag/VisitFallback.hxx
new file mode 100644
index 000000000..23992d44b
--- /dev/null
+++ b/src/tag/VisitFallback.hxx
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2003-2018 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_TAG_VISIT_FALLBACK_HXX
+#define MPD_TAG_VISIT_FALLBACK_HXX
+
+#include "Fallback.hxx"
+#include "Tag.hxx"
+
+template<typename F>
+bool
+VisitTagType(const Tag &tag, TagType type, F &&f) noexcept
+{
+ bool found = false;
+
+ for (const auto &item : tag) {
+ if (item.type == type) {
+ found = true;
+ f(item.value);
+ }
+ }
+
+ return found;
+}
+
+template<typename F>
+bool
+VisitTagWithFallback(const Tag &tag, TagType type, F &&f) noexcept
+{
+ return ApplyTagWithFallback(type,
+ [&](TagType type2) {
+ return VisitTagType(tag, type2, f);
+ });
+}
+
+template<typename F>
+void
+VisitTagWithFallbackOrEmpty(const Tag &tag, TagType type, F &&f) noexcept
+{
+ if (!VisitTagWithFallback(tag, type, f))
+ f("");
+}
+
+#endif
diff --git a/src/tag/meson.build b/src/tag/meson.build
index b0121a71d..c423417d1 100644
--- a/src/tag/meson.build
+++ b/src/tag/meson.build
@@ -9,7 +9,6 @@ tag_sources = [
'FixString.cxx',
'Pool.cxx',
'Table.cxx',
- 'Set.cxx',
'Format.cxx',
'VorbisComment.cxx',
'ReplayGain.cxx',