From 2f3f075e4fc14e361179905cb15e366d366a4786 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 7 Feb 2017 16:57:16 +0100 Subject: [PATCH] tag/Mask: wrap in class --- src/command/DatabaseCommands.cxx | 7 +- src/db/DatabasePrint.cxx | 3 +- src/db/DatabasePrint.hxx | 5 +- src/db/Interface.hxx | 4 +- src/db/UniqueTags.cxx | 5 +- src/db/UniqueTags.hxx | 4 +- src/db/plugins/ProxyDatabasePlugin.cxx | 5 +- .../plugins/simple/SimpleDatabasePlugin.cxx | 3 +- .../plugins/simple/SimpleDatabasePlugin.hxx | 2 +- src/db/plugins/upnp/UpnpDatabasePlugin.cxx | 5 +- src/tag/Config.cxx | 4 +- src/tag/Mask.hxx | 67 ++++++++++++++++++- src/tag/Set.cxx | 13 ++-- src/tag/Set.hxx | 9 +-- src/tag/Settings.cxx | 2 +- src/tag/Settings.hxx | 18 ++--- 16 files changed, 114 insertions(+), 42 deletions(-) diff --git a/src/command/DatabaseCommands.cxx b/src/command/DatabaseCommands.cxx index 7647ac5d3..d8a9393b7 100644 --- a/src/command/DatabaseCommands.cxx +++ b/src/command/DatabaseCommands.cxx @@ -29,6 +29,7 @@ #include "client/Client.hxx" #include "client/Response.hxx" #include "tag/ParseName.hxx" +#include "tag/Mask.hxx" #include "util/ConstBuffer.hxx" #include "util/StringAPI.hxx" #include "SongFilter.hxx" @@ -191,7 +192,7 @@ handle_list(Client &client, Request args, Response &r) } std::unique_ptr filter; - tag_mask_t group_mask = 0; + TagMask group_mask = TagMask::None(); if (args.size == 1) { /* for compatibility with < 0.12.0 */ @@ -216,7 +217,7 @@ handle_list(Client &client, Request args, Response &r) return CommandResult::ERROR; } - group_mask |= tag_mask_t(1) << unsigned(gt); + group_mask |= gt; args.pop_back(); args.pop_back(); @@ -231,7 +232,7 @@ handle_list(Client &client, Request args, Response &r) } if (tagType < TAG_NUM_OF_ITEM_TYPES && - group_mask & (tag_mask_t(1) << tagType)) { + group_mask.Test(TagType(tagType))) { r.Error(ACK_ERROR_ARG, "Conflicting group"); return CommandResult::ERROR; } diff --git a/src/db/DatabasePrint.cxx b/src/db/DatabasePrint.cxx index a98553237..b5e0b69f7 100644 --- a/src/db/DatabasePrint.cxx +++ b/src/db/DatabasePrint.cxx @@ -27,6 +27,7 @@ #include "client/Response.hxx" #include "Partition.hxx" #include "tag/Tag.hxx" +#include "tag/Mask.hxx" #include "LightSong.hxx" #include "LightDirectory.hxx" #include "PlaylistInfo.hxx" @@ -202,7 +203,7 @@ PrintUniqueTag(Response &r, TagType tag_type, void PrintUniqueTags(Response &r, Partition &partition, - unsigned type, tag_mask_t group_mask, + unsigned type, TagMask group_mask, const SongFilter *filter) { const Database &db = partition.GetDatabaseOrThrow(); diff --git a/src/db/DatabasePrint.hxx b/src/db/DatabasePrint.hxx index 51b9a92cd..60f3e5a10 100644 --- a/src/db/DatabasePrint.hxx +++ b/src/db/DatabasePrint.hxx @@ -20,8 +20,7 @@ #ifndef MPD_DB_PRINT_H #define MPD_DB_PRINT_H -#include "tag/Mask.hxx" - +class TagMask; class SongFilter; struct DatabaseSelection; struct Partition; @@ -44,7 +43,7 @@ db_selection_print(Response &r, Partition &partition, void PrintUniqueTags(Response &r, Partition &partition, - unsigned type, tag_mask_t group_mask, + unsigned type, TagMask group_mask, const SongFilter *filter); #endif diff --git a/src/db/Interface.hxx b/src/db/Interface.hxx index 9f8f5837b..5a27fa5de 100644 --- a/src/db/Interface.hxx +++ b/src/db/Interface.hxx @@ -22,7 +22,6 @@ #include "Visitor.hxx" #include "tag/Type.h" -#include "tag/Mask.hxx" #include "Compiler.h" #include @@ -31,6 +30,7 @@ struct DatabasePlugin; struct DatabaseStats; struct DatabaseSelection; struct LightSong; +class TagMask; class Database { const DatabasePlugin &plugin; @@ -103,7 +103,7 @@ public: * Visit all unique tag values. */ virtual void VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag) const = 0; gcc_pure diff --git a/src/db/UniqueTags.cxx b/src/db/UniqueTags.cxx index c888fe7b4..e755ac12c 100644 --- a/src/db/UniqueTags.cxx +++ b/src/db/UniqueTags.cxx @@ -21,13 +21,14 @@ #include "Interface.hxx" #include "LightSong.hxx" #include "tag/Set.hxx" +#include "tag/Mask.hxx" #include #include static void -CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask, +CollectTags(TagSet &set, TagType tag_type, TagMask group_mask, const LightSong &song) { assert(song.tag != nullptr); @@ -38,7 +39,7 @@ CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask, void VisitUniqueTags(const Database &db, const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag) { TagSet set; diff --git a/src/db/UniqueTags.hxx b/src/db/UniqueTags.hxx index d50be564f..0790acb3d 100644 --- a/src/db/UniqueTags.hxx +++ b/src/db/UniqueTags.hxx @@ -22,14 +22,14 @@ #include "Visitor.hxx" #include "tag/Type.h" -#include "tag/Mask.hxx" +class TagMask; class Database; struct DatabaseSelection; void VisitUniqueTags(const Database &db, const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag); #endif diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx index 50c092fa8..ba3818e76 100644 --- a/src/db/plugins/ProxyDatabasePlugin.cxx +++ b/src/db/plugins/ProxyDatabasePlugin.cxx @@ -33,6 +33,7 @@ #include "config/Block.hxx" #include "tag/Builder.hxx" #include "tag/Tag.hxx" +#include "tag/Mask.hxx" #include "util/ScopeExit.hxx" #include "util/RuntimeError.hxx" #include "protocol/Ack.hxx" @@ -120,7 +121,7 @@ public: VisitPlaylist visit_playlist) const override; void VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag) const override; DatabaseStats GetStats(const DatabaseSelection &selection) const override; @@ -756,7 +757,7 @@ ProxyDatabase::Visit(const DatabaseSelection &selection, void ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection, TagType tag_type, - gcc_unused tag_mask_t group_mask, + gcc_unused TagMask group_mask, VisitTag visit_tag) const { // TODO: eliminate the const_cast diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx index a0b4c3aa0..cfa335416 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx @@ -31,6 +31,7 @@ #include "DatabaseSave.hxx" #include "db/DatabaseLock.hxx" #include "db/DatabaseError.hxx" +#include "tag/Mask.hxx" #include "fs/io/TextFile.hxx" #include "fs/io/BufferedOutputStream.hxx" #include "fs/io/FileOutputStream.hxx" @@ -301,7 +302,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, void SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag) const { ::VisitUniqueTags(*this, selection, tag_type, group_mask, visit_tag); diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.hxx b/src/db/plugins/simple/SimpleDatabasePlugin.hxx index 474c2ea21..306e590f4 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.hxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.hxx @@ -120,7 +120,7 @@ public: VisitPlaylist visit_playlist) const override; void VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag) const override; DatabaseStats GetStats(const DatabaseSelection &selection) const override; diff --git a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx index 5c31e5cf3..90b80c8cb 100644 --- a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx +++ b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx @@ -35,6 +35,7 @@ #include "config/Block.hxx" #include "tag/Builder.hxx" #include "tag/Table.hxx" +#include "tag/Mask.hxx" #include "fs/Traits.hxx" #include "Log.hxx" #include "SongFilter.hxx" @@ -88,7 +89,7 @@ public: VisitPlaylist visit_playlist) const override; void VisitUniqueTags(const DatabaseSelection &selection, - TagType tag_type, tag_mask_t group_mask, + TagType tag_type, TagMask group_mask, VisitTag visit_tag) const override; DatabaseStats GetStats(const DatabaseSelection &selection) const override; @@ -605,7 +606,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection, void UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection, - TagType tag, gcc_unused tag_mask_t group_mask, + TagType tag, gcc_unused TagMask group_mask, VisitTag visit_tag) const { // TODO: use group_mask diff --git a/src/tag/Config.cxx b/src/tag/Config.cxx index 6135cbed8..4f2711e6d 100644 --- a/src/tag/Config.cxx +++ b/src/tag/Config.cxx @@ -37,7 +37,7 @@ TagLoadConfig() if (value == nullptr) return; - global_tag_mask = 0; + global_tag_mask = TagMask::None(); if (StringEqualsCaseASCII(value, "none")) return; @@ -60,7 +60,7 @@ TagLoadConfig() FormatFatalError("error parsing metadata item \"%s\"", c); - global_tag_mask |= tag_mask_t(1) << unsigned(type); + global_tag_mask |= type; s++; c = s; diff --git a/src/tag/Mask.hxx b/src/tag/Mask.hxx index 09645906a..fdc71d9bb 100644 --- a/src/tag/Mask.hxx +++ b/src/tag/Mask.hxx @@ -20,8 +20,73 @@ #ifndef MPD_TAG_MASK_HXX #define MPD_TAG_MASK_HXX +#include "Type.h" + #include -typedef uint_least32_t tag_mask_t; +class TagMask { + typedef uint_least32_t mask_t; + mask_t value; + + explicit constexpr TagMask(uint_least32_t _value) + :value(_value) {} + +public: + TagMask() = default; + + constexpr TagMask(TagType tag) + :value(mask_t(1) << mask_t(tag)) {} + + static constexpr TagMask None() { + return TagMask(mask_t(0)); + } + + static constexpr TagMask All() { + return ~None(); + } + + constexpr TagMask operator~() const { + return TagMask(~value); + } + + constexpr TagMask operator&(TagMask other) const { + return TagMask(value & other.value); + } + + constexpr TagMask operator|(TagMask other) const { + return TagMask(value | other.value); + } + + constexpr TagMask operator^(TagMask other) const { + return TagMask(value ^ other.value); + } + + TagMask &operator&=(TagMask other) { + value |= other.value; + return *this; + } + + TagMask &operator|=(TagMask other) { + value |= other.value; + return *this; + } + + TagMask &operator^=(TagMask other) { + value |= other.value; + return *this; + } + + constexpr bool TestAny() const { + return value != 0; + } + + constexpr bool Test(TagType tag) const { + return (*this & tag).TestAny(); + } + + void Set(TagType tag) { + *this |= tag; + } +}; #endif diff --git a/src/tag/Set.cxx b/src/tag/Set.cxx index 97aabef08..1ad54be09 100644 --- a/src/tag/Set.cxx +++ b/src/tag/Set.cxx @@ -19,6 +19,7 @@ #include "Set.hxx" #include "Builder.hxx" +#include "Mask.hxx" #include "Settings.hxx" #include @@ -58,16 +59,16 @@ CopyTagItem(TagBuilder &dest, const Tag &src, TagType type) * Copy all tag items of the types in the mask. */ static void -CopyTagMask(TagBuilder &dest, const Tag &src, tag_mask_t mask) +CopyTagMask(TagBuilder &dest, const Tag &src, TagMask mask) { for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) - if ((mask & (tag_mask_t(1) << i)) != 0) + if (mask.Test(TagType(i))) CopyTagItem(dest, src, TagType(i)); } void TagSet::InsertUnique(const Tag &src, TagType type, const char *value, - tag_mask_t group_mask) + TagMask group_mask) { TagBuilder builder; if (value == nullptr) @@ -85,7 +86,7 @@ TagSet::InsertUnique(const Tag &src, TagType type, const char *value, bool TagSet::CheckUnique(TagType dest_type, const Tag &tag, TagType src_type, - tag_mask_t group_mask) + TagMask group_mask) { bool found = false; @@ -101,12 +102,12 @@ TagSet::CheckUnique(TagType dest_type, void TagSet::InsertUnique(const Tag &tag, - TagType type, tag_mask_t group_mask) + TagType type, TagMask group_mask) { static_assert(sizeof(group_mask) * 8 >= TAG_NUM_OF_ITEM_TYPES, "Mask is too small"); - assert((group_mask & (tag_mask_t(1) << unsigned(type))) == 0); + assert(!group_mask.Test(type)); if (!CheckUnique(type, tag, type, group_mask) && (type != TAG_ALBUM_ARTIST || diff --git a/src/tag/Set.hxx b/src/tag/Set.hxx index c07c736e7..25df4b848 100644 --- a/src/tag/Set.hxx +++ b/src/tag/Set.hxx @@ -22,12 +22,13 @@ #include "Compiler.h" #include "Tag.hxx" -#include "Mask.hxx" #include #include +class TagMask; + /** * Helper class for #TagSet which compares two #Tag objects. */ @@ -59,15 +60,15 @@ struct TagLess { class TagSet : public std::set { public: void InsertUnique(const Tag &tag, - TagType type, tag_mask_t group_mask); + TagType type, TagMask group_mask); private: void InsertUnique(const Tag &src, TagType type, const char *value, - tag_mask_t group_mask); + TagMask group_mask); bool CheckUnique(TagType dest_type, const Tag &tag, TagType src_type, - tag_mask_t group_mask); + TagMask group_mask); }; #endif diff --git a/src/tag/Settings.cxx b/src/tag/Settings.cxx index a27198aab..c10411bc5 100644 --- a/src/tag/Settings.cxx +++ b/src/tag/Settings.cxx @@ -19,4 +19,4 @@ #include "Settings.hxx" -tag_mask_t global_tag_mask = (tag_mask_t)-1 & ~(1 << TAG_COMMENT); +TagMask global_tag_mask = TagMask::All() & ~TagMask(TAG_COMMENT); diff --git a/src/tag/Settings.hxx b/src/tag/Settings.hxx index 01cd6af4e..77e754c6e 100644 --- a/src/tag/Settings.hxx +++ b/src/tag/Settings.hxx @@ -24,20 +24,20 @@ #include "Type.h" #include "Compiler.h" -extern tag_mask_t global_tag_mask; - -gcc_const -static inline bool -IsTagEnabled(unsigned tag) -{ - return global_tag_mask & (1u << tag); -} +extern TagMask global_tag_mask; gcc_const static inline bool IsTagEnabled(TagType tag) { - return IsTagEnabled(unsigned(tag)); + return global_tag_mask.Test(tag); +} + +gcc_const +static inline bool +IsTagEnabled(unsigned tag) +{ + return IsTagEnabled(TagType(tag)); } #endif