From 3d3a1232b1d2b58d2cc05b2dd5c37f2256832693 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 5 Jul 2018 19:07:05 +0200 Subject: tag/Handler: convert to class with virtual methods --- src/tag/Handler.hxx | 105 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 39 deletions(-) (limited to 'src/tag/Handler.hxx') 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 +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 -- cgit v1.2.3