summaryrefslogtreecommitdiff
path: root/src/tag
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-07-05 19:07:05 +0200
committerMax Kellermann <max@musicpd.org>2018-07-05 19:07:05 +0200
commit3d3a1232b1d2b58d2cc05b2dd5c37f2256832693 (patch)
tree250933da4d5dc29145ce18e5a05a7f8da30396fd /src/tag
parent09d4176210d66cf9e2d258b563a7811892c560f4 (diff)
tag/Handler: convert to class with virtual methods
Diffstat (limited to 'src/tag')
-rw-r--r--src/tag/ApeTag.cxx23
-rw-r--r--src/tag/ApeTag.hxx7
-rw-r--r--src/tag/Generic.cxx10
-rw-r--r--src/tag/Generic.hxx6
-rw-r--r--src/tag/Handler.cxx30
-rw-r--r--src/tag/Handler.hxx105
-rw-r--r--src/tag/Id3Scan.cxx80
-rw-r--r--src/tag/Id3Scan.hxx8
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