From f34d73d319ceb4d9baccf8b626dcd185f4a631e0 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Sat, 21 Nov 2015 18:29:41 +0900 Subject: [PATCH] Make FileRef::FileTypeResolver work properly. --- taglib/fileref.cpp | 47 ++++++++++++++++++++++++++++++++---------- tests/test_fileref.cpp | 31 +++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index 0be65603..7cf78803 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -56,7 +56,8 @@ using namespace TagLib; namespace { - List fileTypeResolvers; + typedef List ResolverList; + ResolverList fileTypeResolvers; // Templatized internal functions. T should be String or IOStream*. @@ -79,8 +80,41 @@ namespace } template - File* createInternal(T arg, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) + inline File *resolveFileType(T arg, bool readProperties, + AudioProperties::ReadStyle style) { + // Should never be called. + } + + template <> + inline File *resolveFileType(IOStream *arg, bool readProperties, + AudioProperties::ReadStyle style) + { + return 0; + } + + template <> + inline File *resolveFileType(FileName arg, bool readProperties, + AudioProperties::ReadStyle style) + { + ResolverList::ConstIterator it = fileTypeResolvers.begin(); + for(; it != fileTypeResolvers.end(); ++it) { + File *file = (*it)->createFile(arg, readProperties, style); + if(file) + return file; + } + + return 0; + } + + template + File* createInternal(T arg, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) + { + File *file = resolveFileType(arg, readAudioProperties, audioPropertiesStyle); + if(file) + return file; + #ifdef _WIN32 const String s = toFileName(arg).toString(); #else @@ -302,14 +336,5 @@ bool FileRef::operator!=(const FileRef &ref) const File *FileRef::create(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) // static { - - List::ConstIterator it = fileTypeResolvers.begin(); - - for(; it != fileTypeResolvers.end(); ++it) { - File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle); - if(file) - return file; - } - return createInternal(fileName, readAudioProperties, audioPropertiesStyle); } diff --git a/tests/test_fileref.cpp b/tests/test_fileref.cpp index a51b868c..a389cfd3 100644 --- a/tests/test_fileref.cpp +++ b/tests/test_fileref.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "utils.h" #include @@ -11,6 +12,18 @@ using namespace std; using namespace TagLib; +namespace +{ + class DummyResolver : public FileRef::FileTypeResolver + { + public: + virtual File *createFile(FileName fileName, bool, AudioProperties::ReadStyle) const + { + return new Ogg::Vorbis::File(fileName); + } + }; +} + class TestFileRef : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TestFileRef); @@ -29,6 +42,7 @@ class TestFileRef : public CppUnit::TestFixture CPPUNIT_TEST(testAPE); CPPUNIT_TEST(testWav); CPPUNIT_TEST(testUnsupported); + CPPUNIT_TEST(testFileResolver); CPPUNIT_TEST_SUITE_END(); public: @@ -168,10 +182,25 @@ public: { FileRef f1(TEST_FILE_PATH_C("no-extension")); CPPUNIT_ASSERT(f1.isNull()); - + FileRef f2(TEST_FILE_PATH_C("unsupported-extension.xxx")); CPPUNIT_ASSERT(f2.isNull()); } + + void testFileResolver() + { + FileRef *f = new FileRef(TEST_FILE_PATH_C("xing.mp3")); + CPPUNIT_ASSERT(dynamic_cast(f->file()) != NULL); + delete f; + + DummyResolver resolver; + FileRef::addFileTypeResolver(&resolver); + + f = new FileRef(TEST_FILE_PATH_C("xing.mp3")); + CPPUNIT_ASSERT(dynamic_cast(f->file()) != NULL); + delete f; + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestFileRef);