diff options
author | Max Kellermann <max@musicpd.org> | 2018-07-05 19:07:05 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2018-07-05 19:07:05 +0200 |
commit | 3d3a1232b1d2b58d2cc05b2dd5c37f2256832693 (patch) | |
tree | 250933da4d5dc29145ce18e5a05a7f8da30396fd /src/tag | |
parent | 09d4176210d66cf9e2d258b563a7811892c560f4 (diff) |
tag/Handler: convert to class with virtual methods
Diffstat (limited to 'src/tag')
-rw-r--r-- | src/tag/ApeTag.cxx | 23 | ||||
-rw-r--r-- | src/tag/ApeTag.hxx | 7 | ||||
-rw-r--r-- | src/tag/Generic.cxx | 10 | ||||
-rw-r--r-- | src/tag/Generic.hxx | 6 | ||||
-rw-r--r-- | src/tag/Handler.cxx | 30 | ||||
-rw-r--r-- | src/tag/Handler.hxx | 105 | ||||
-rw-r--r-- | src/tag/Id3Scan.cxx | 80 | ||||
-rw-r--r-- | src/tag/Id3Scan.hxx | 8 |
8 files changed, 130 insertions, 139 deletions
diff --git a/src/tag/ApeTag.cxx b/src/tag/ApeTag.cxx index ff143e7cd..6d8203dc2 100644 --- a/src/tag/ApeTag.cxx +++ b/src/tag/ApeTag.cxx @@ -76,7 +76,7 @@ ForEachValue(const char *value, const char *end, C &&callback) static bool tag_ape_import_item(unsigned long flags, const char *key, StringView value, - const TagHandler &handler, void *handler_ctx) + TagHandler &handler) noexcept { /* we only care about utf-8 text tags */ if ((flags & (0x3 << 1)) != 0) @@ -85,36 +85,31 @@ tag_ape_import_item(unsigned long flags, const auto begin = value.begin(); const auto end = value.end(); - if (handler.pair != nullptr) - ForEachValue(begin, end, [handler, handler_ctx, - key](const char *_value) { - handler.pair(key, _value, handler_ctx); + if (handler.WantPair()) + ForEachValue(begin, end, [&handler, key](const char *_value) { + handler.OnPair(key, _value); }); TagType type = tag_ape_name_parse(key); if (type == TAG_NUM_OF_ITEM_TYPES) return false; - ForEachValue(begin, end, [handler, handler_ctx, - type](const char *_value) { - tag_handler_invoke_tag(handler, handler_ctx, - type, _value); + ForEachValue(begin, end, [&handler, type](const char *_value) { + handler.OnTag(type, _value); }); return true; } bool -tag_ape_scan2(InputStream &is, - const TagHandler &handler, void *handler_ctx) +tag_ape_scan2(InputStream &is, TagHandler &handler) noexcept { bool recognized = false; - auto callback = [handler, handler_ctx, &recognized] + auto callback = [&handler, &recognized] (unsigned long flags, const char *key, StringView value) { - recognized |= tag_ape_import_item(flags, key, value, - handler, handler_ctx); + recognized |= tag_ape_import_item(flags, key, value, handler); return true; }; diff --git a/src/tag/ApeTag.hxx b/src/tag/ApeTag.hxx index 93b8ba126..9d467608d 100644 --- a/src/tag/ApeTag.hxx +++ b/src/tag/ApeTag.hxx @@ -20,10 +20,8 @@ #ifndef MPD_APE_TAG_HXX #define MPD_APE_TAG_HXX -#include "Table.hxx" - class InputStream; -struct TagHandler; +class TagHandler; /** * Scan the APE tags of a stream. @@ -31,7 +29,6 @@ struct TagHandler; * @param path_fs the path of the file in filesystem encoding */ bool -tag_ape_scan2(InputStream &is, - const TagHandler &handler, void *handler_ctx); +tag_ape_scan2(InputStream &is, TagHandler &handler) noexcept; #endif diff --git a/src/tag/Generic.cxx b/src/tag/Generic.cxx index 3aff10c79..1ce736505 100644 --- a/src/tag/Generic.cxx +++ b/src/tag/Generic.cxx @@ -30,9 +30,9 @@ #include <exception> bool -ScanGenericTags(InputStream &is, const TagHandler &handler, void *ctx) +ScanGenericTags(InputStream &is, TagHandler &handler) noexcept { - if (tag_ape_scan2(is, handler, ctx)) + if (tag_ape_scan2(is, handler)) return true; #ifdef ENABLE_ID3TAG @@ -42,19 +42,19 @@ ScanGenericTags(InputStream &is, const TagHandler &handler, void *ctx) return false; } - return tag_id3_scan(is, handler, ctx); + return tag_id3_scan(is, handler); #else return false; #endif } bool -ScanGenericTags(Path path, const TagHandler &handler, void *ctx) +ScanGenericTags(Path path, TagHandler &handler) noexcept try { Mutex mutex; auto is = OpenLocalInputStream(path, mutex); - return ScanGenericTags(*is, handler, ctx); + return ScanGenericTags(*is, handler); } catch (...) { LogError(std::current_exception()); return false; diff --git a/src/tag/Generic.hxx b/src/tag/Generic.hxx index 568b0b733..415cd2325 100644 --- a/src/tag/Generic.hxx +++ b/src/tag/Generic.hxx @@ -22,7 +22,7 @@ #include "check.h" -struct TagHandler; +class TagHandler; class InputStream; class Path; @@ -31,12 +31,12 @@ class Path; * stream does not need to be rewound. */ bool -ScanGenericTags(InputStream &is, const TagHandler &handler, void *ctx); +ScanGenericTags(InputStream &is, TagHandler &handler) noexcept; /** * Attempts to scan APE or ID3 tags from the specified file. */ bool -ScanGenericTags(Path path, const TagHandler &handler, void *ctx); +ScanGenericTags(Path path, TagHandler &handler) noexcept; #endif diff --git a/src/tag/Handler.cxx b/src/tag/Handler.cxx index 7c4210f7d..ad8404161 100644 --- a/src/tag/Handler.cxx +++ b/src/tag/Handler.cxx @@ -25,19 +25,15 @@ #include <stdlib.h> -static void -add_tag_duration(SongTime duration, void *ctx) +void +AddTagHandler::OnDuration(SongTime duration) noexcept { - TagBuilder &tag = *(TagBuilder *)ctx; - tag.SetDuration(duration); } -static void -add_tag_tag(TagType type, const char *value, void *ctx) +void +AddTagHandler::OnTag(TagType type, const char *value) noexcept { - TagBuilder &tag = *(TagBuilder *)ctx; - if (type == TAG_TRACK || type == TAG_DISC) { /* filter out this extra data and leading zeroes */ char *end; @@ -48,24 +44,10 @@ add_tag_tag(TagType type, const char *value, void *ctx) tag.AddItem(type, value); } -const TagHandler add_tag_handler = { - add_tag_duration, - add_tag_tag, - nullptr, -}; - -static void -full_tag_pair(const char *name, gcc_unused const char *value, void *ctx) +void +FullTagHandler::OnPair(const char *name, gcc_unused const char *value) noexcept { - TagBuilder &tag = *(TagBuilder *)ctx; - if (StringEqualsCaseASCII(name, "cuesheet")) tag.SetHasPlaylist(true); } -const TagHandler full_tag_handler = { - add_tag_duration, - add_tag_tag, - full_tag_pair, -}; - diff --git a/src/tag/Handler.hxx b/src/tag/Handler.hxx index cec04e91d..944c73114 100644 --- a/src/tag/Handler.hxx +++ b/src/tag/Handler.hxx @@ -23,19 +23,45 @@ #include "check.h" #include "Type.h" #include "Chrono.hxx" +#include "Compiler.h" -#include <assert.h> +class TagBuilder; /** - * A callback table for receiving metadata of a song. + * An interface for receiving metadata of a song. */ -struct TagHandler { +class TagHandler { + const unsigned want_mask; + +public: + static constexpr unsigned WANT_DURATION = 0x1; + static constexpr unsigned WANT_TAG = 0x2; + static constexpr unsigned WANT_PAIR = 0x4; + + explicit TagHandler(unsigned _want_mask) noexcept + :want_mask(_want_mask) {} + + TagHandler(const TagHandler &) = delete; + TagHandler &operator=(const TagHandler &) = delete; + + bool WantDuration() const noexcept { + return want_mask & WANT_DURATION; + } + + bool WantTag() const noexcept { + return want_mask & WANT_TAG; + } + + bool WantPair() const noexcept { + return want_mask & WANT_PAIR; + } + /** * Declare the duration of a song. Do not call * this when the duration could not be determined, because * there is no magic value for "unknown duration". */ - void (*duration)(SongTime duration, void *ctx); + virtual void OnDuration(SongTime duration) noexcept = 0; /** * A tag has been read. @@ -43,56 +69,57 @@ struct TagHandler { * @param the value of the tag; the pointer will become * invalid after returning */ - void (*tag)(TagType type, const char *value, void *ctx); + virtual void OnTag(TagType type, const char *value) noexcept = 0; /** * A name-value pair has been read. It is the codec specific * representation of tags. */ - void (*pair)(const char *key, const char *value, void *ctx); + virtual void OnPair(const char *key, const char *value) noexcept = 0; }; -static inline void -tag_handler_invoke_duration(const TagHandler &handler, void *ctx, - SongTime duration) noexcept -{ - if (handler.duration != nullptr) - handler.duration(duration, ctx); -} - -static inline void -tag_handler_invoke_tag(const TagHandler &handler, void *ctx, - TagType type, const char *value) noexcept -{ - assert((unsigned)type < TAG_NUM_OF_ITEM_TYPES); - assert(value != nullptr); - - if (handler.tag != nullptr) - handler.tag(type, value, ctx); -} - -static inline void -tag_handler_invoke_pair(const TagHandler &handler, void *ctx, - const char *name, const char *value) noexcept -{ - assert(name != nullptr); - assert(value != nullptr); - - if (handler.pair != nullptr) - handler.pair(name, value, ctx); -} +class NullTagHandler : public TagHandler { +public: + explicit NullTagHandler(unsigned _want_mask) noexcept + :TagHandler(_want_mask) {} + + void OnDuration(gcc_unused SongTime duration) noexcept override {} + void OnTag(gcc_unused TagType type, + gcc_unused const char *value) noexcept override {} + void OnPair(gcc_unused const char *key, + gcc_unused const char *value) noexcept override {} +}; /** - * This #TagHandler implementation adds tag values to a #TagBuilder object - * (casted from the context pointer). + * This #TagHandler implementation adds tag values to a #TagBuilder + * object. */ -extern const TagHandler add_tag_handler; +class AddTagHandler : public NullTagHandler { +protected: + TagBuilder &tag; + + AddTagHandler(unsigned _want_mask, TagBuilder &_builder) noexcept + :NullTagHandler(_want_mask), tag(_builder) {} + +public: + explicit AddTagHandler(TagBuilder &_builder) noexcept + :AddTagHandler(WANT_DURATION|WANT_TAG, _builder) {} + + void OnDuration(SongTime duration) noexcept override; + void OnTag(TagType type, const char *value) noexcept override; +}; /** * This #TagHandler implementation adds tag values to a #TagBuilder object * (casted from the context pointer), and supports the has_playlist * attribute. */ -extern const TagHandler full_tag_handler; +class FullTagHandler : public AddTagHandler { +public: + explicit FullTagHandler(TagBuilder &_builder) noexcept + :AddTagHandler(WANT_DURATION|WANT_TAG|WANT_PAIR, _builder) {} + + void OnPair(const char *key, const char *value) noexcept override; +}; #endif diff --git a/src/tag/Id3Scan.cxx b/src/tag/Id3Scan.cxx index cd35386e4..aa1caba69 100644 --- a/src/tag/Id3Scan.cxx +++ b/src/tag/Id3Scan.cxx @@ -100,7 +100,7 @@ import_id3_string(const id3_ucs4_t *ucs4) static void tag_id3_import_text_frame(const struct id3_frame *frame, TagType type, - const TagHandler &handler, void *handler_ctx) + TagHandler &handler) noexcept { if (frame->nfields != 2) return; @@ -133,8 +133,7 @@ tag_id3_import_text_frame(const struct id3_frame *frame, AtScopeExit(utf8) { free(utf8); }; - tag_handler_invoke_tag(handler, handler_ctx, - type, (const char *)utf8); + handler.OnTag(type, (const char *)utf8); } } @@ -144,13 +143,13 @@ tag_id3_import_text_frame(const struct id3_frame *frame, */ static void tag_id3_import_text(struct id3_tag *tag, const char *id, TagType type, - const TagHandler &handler, void *handler_ctx) + TagHandler &handler) noexcept { const struct id3_frame *frame; for (unsigned i = 0; (frame = id3_tag_findframe(tag, id, i)) != nullptr; ++i) tag_id3_import_text_frame(frame, type, - handler, handler_ctx); + handler); } /** @@ -164,8 +163,7 @@ tag_id3_import_text(struct id3_tag *tag, const char *id, TagType type, */ static void tag_id3_import_comment_frame(const struct id3_frame *frame, TagType type, - const TagHandler &handler, - void *handler_ctx) + TagHandler &handler) noexcept { if (frame->nfields != 4) return; @@ -185,7 +183,7 @@ tag_id3_import_comment_frame(const struct id3_frame *frame, TagType type, AtScopeExit(utf8) { free(utf8); }; - tag_handler_invoke_tag(handler, handler_ctx, type, (const char *)utf8); + handler.OnTag(type, (const char *)utf8); } /** @@ -194,13 +192,13 @@ tag_id3_import_comment_frame(const struct id3_frame *frame, TagType type, */ static void tag_id3_import_comment(struct id3_tag *tag, const char *id, TagType type, - const TagHandler &handler, void *handler_ctx) + TagHandler &handler) noexcept { const struct id3_frame *frame; for (unsigned i = 0; (frame = id3_tag_findframe(tag, id, i)) != nullptr; ++i) tag_id3_import_comment_frame(frame, type, - handler, handler_ctx); + handler); } /** @@ -220,8 +218,7 @@ tag_id3_parse_txxx_name(const char *name) noexcept */ static void tag_id3_import_musicbrainz(struct id3_tag *id3_tag, - const TagHandler &handler, - void *handler_ctx) + TagHandler &handler) noexcept { for (unsigned i = 0;; ++i) { const id3_frame *frame = id3_tag_findframe(id3_tag, "TXXX", i); @@ -240,15 +237,12 @@ tag_id3_import_musicbrainz(struct id3_tag *id3_tag, AtScopeExit(value) { free(value); }; - tag_handler_invoke_pair(handler, handler_ctx, - (const char *)name, - (const char *)value); + handler.OnPair((const char *)name, (const char *)value); TagType type = tag_id3_parse_txxx_name((const char*)name); if (type != TAG_NUM_OF_ITEM_TYPES) - tag_handler_invoke_tag(handler, handler_ctx, - type, (const char*)value); + handler.OnTag(type, (const char*)value); } } @@ -257,7 +251,7 @@ tag_id3_import_musicbrainz(struct id3_tag *id3_tag, */ static void tag_id3_import_ufid(struct id3_tag *id3_tag, - const TagHandler &handler, void *handler_ctx) + TagHandler &handler) noexcept { for (unsigned i = 0;; ++i) { const id3_frame *frame = id3_tag_findframe(id3_tag, "UFID", i); @@ -284,65 +278,63 @@ tag_id3_import_ufid(struct id3_tag *id3_tag, continue; std::string p((const char *)value, length); - tag_handler_invoke_tag(handler, handler_ctx, - TAG_MUSICBRAINZ_TRACKID, p.c_str()); + handler.OnTag(TAG_MUSICBRAINZ_TRACKID, p.c_str()); } } void -scan_id3_tag(struct id3_tag *tag, - const TagHandler &handler, void *handler_ctx) +scan_id3_tag(struct id3_tag *tag, TagHandler &handler) noexcept { tag_id3_import_text(tag, ID3_FRAME_ARTIST, TAG_ARTIST, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_ALBUM_ARTIST, - TAG_ALBUM_ARTIST, handler, handler_ctx); + TAG_ALBUM_ARTIST, handler); tag_id3_import_text(tag, ID3_FRAME_ARTIST_SORT, - TAG_ARTIST_SORT, handler, handler_ctx); + TAG_ARTIST_SORT, handler); - tag_id3_import_text(tag, "TSOA", TAG_ALBUM_SORT, handler, handler_ctx); + tag_id3_import_text(tag, "TSOA", TAG_ALBUM_SORT, handler); tag_id3_import_text(tag, ID3_FRAME_ALBUM_ARTIST_SORT, - TAG_ALBUM_ARTIST_SORT, handler, handler_ctx); + TAG_ALBUM_ARTIST_SORT, handler); tag_id3_import_text(tag, ID3_FRAME_TITLE, TAG_TITLE, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_ALBUM, TAG_ALBUM, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_TRACK, TAG_TRACK, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_YEAR, TAG_DATE, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_ORIGINAL_RELEASE_DATE, TAG_ORIGINAL_DATE, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_GENRE, TAG_GENRE, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_COMPOSER, TAG_COMPOSER, - handler, handler_ctx); + handler); tag_id3_import_text(tag, "TPE3", TAG_PERFORMER, - handler, handler_ctx); - tag_id3_import_text(tag, "TPE4", TAG_PERFORMER, handler, handler_ctx); + handler); + tag_id3_import_text(tag, "TPE4", TAG_PERFORMER, handler); tag_id3_import_comment(tag, ID3_FRAME_COMMENT, TAG_COMMENT, - handler, handler_ctx); + handler); tag_id3_import_text(tag, ID3_FRAME_DISC, TAG_DISC, - handler, handler_ctx); + handler); - tag_id3_import_musicbrainz(tag, handler, handler_ctx); - tag_id3_import_ufid(tag, handler, handler_ctx); + tag_id3_import_musicbrainz(tag, handler); + tag_id3_import_ufid(tag, handler); } std::unique_ptr<Tag> tag_id3_import(struct id3_tag *tag) { TagBuilder tag_builder; - scan_id3_tag(tag, add_tag_handler, &tag_builder); + AddTagHandler h(tag_builder); + scan_id3_tag(tag, h); return tag_builder.empty() ? nullptr : tag_builder.CommitNew(); } bool -tag_id3_scan(InputStream &is, - const TagHandler &handler, void *handler_ctx) +tag_id3_scan(InputStream &is, TagHandler &handler) noexcept { UniqueId3Tag tag; @@ -355,6 +347,6 @@ tag_id3_scan(InputStream &is, return false; } - scan_id3_tag(tag.get(), handler, handler_ctx); + scan_id3_tag(tag.get(), handler); return true; } diff --git a/src/tag/Id3Scan.hxx b/src/tag/Id3Scan.hxx index d81e154a5..8ce23ad46 100644 --- a/src/tag/Id3Scan.hxx +++ b/src/tag/Id3Scan.hxx @@ -25,13 +25,12 @@ #include <memory> class InputStream; -struct TagHandler; +class TagHandler; struct Tag; struct id3_tag; bool -tag_id3_scan(InputStream &is, - const TagHandler &handler, void *handler_ctx); +tag_id3_scan(InputStream &is, TagHandler &handler) noexcept; std::unique_ptr<Tag> tag_id3_import(id3_tag *); @@ -41,7 +40,6 @@ tag_id3_import(id3_tag *); * */ void -scan_id3_tag(id3_tag *tag, - const TagHandler &handler, void *handler_ctx); +scan_id3_tag(id3_tag *tag, TagHandler &handler) noexcept; #endif |