Make FileRef::FileTypeResolver work properly.

This commit is contained in:
Tsuda Kageyu 2015-11-21 18:29:41 +09:00
parent ef3ce1e38a
commit f34d73d319
2 changed files with 66 additions and 12 deletions

View File

@ -56,7 +56,8 @@ using namespace TagLib;
namespace
{
List<const FileRef::FileTypeResolver *> fileTypeResolvers;
typedef List<const FileRef::FileTypeResolver *> ResolverList;
ResolverList fileTypeResolvers;
// Templatized internal functions. T should be String or IOStream*.
@ -79,8 +80,41 @@ namespace
}
template <typename T>
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 *>(IOStream *arg, bool readProperties,
AudioProperties::ReadStyle style)
{
return 0;
}
template <>
inline File *resolveFileType<FileName>(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 <typename T>
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<const FileTypeResolver *>::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);
}

View File

@ -4,6 +4,7 @@
#include <fileref.h>
#include <oggflacfile.h>
#include <vorbisfile.h>
#include <mpegfile.h>
#include <cppunit/extensions/HelperMacros.h>
#include "utils.h"
#include <tfilestream.h>
@ -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<MPEG::File *>(f->file()) != NULL);
delete f;
DummyResolver resolver;
FileRef::addFileTypeResolver(&resolver);
f = new FileRef(TEST_FILE_PATH_C("xing.mp3"));
CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File *>(f->file()) != NULL);
delete f;
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestFileRef);