Merge pull request #211 from TsudaKageyu/tagunion

RIFF::WAV::Tag() returns TagUnion
This commit is contained in:
Tsuda Kageyu 2013-05-20 20:29:43 -07:00
commit d982b846c4
12 changed files with 196 additions and 179 deletions

View File

@ -57,7 +57,6 @@ public:
APELocation(-1),
APESize(0),
ID3v1Location(-1),
tag(2),
properties(0),
hasAPE(false),
hasID3v1(false) {}
@ -72,7 +71,7 @@ public:
offset_t ID3v1Location;
TagUnion tag;
DoubleTagUnion tag;
AudioProperties *properties;

View File

@ -57,7 +57,6 @@ public:
ID3v2Location(-1),
ID3v2OriginalSize(0),
ID3v1Location(-1),
tag(3),
properties(0),
flacStart(0),
streamStart(0),
@ -84,7 +83,7 @@ public:
offset_t ID3v1Location;
TagUnion tag;
TripleTagUnion tag;
AudioProperties *properties;
ByteVector streamInfoData;
@ -245,11 +244,7 @@ bool FLAC::File::save()
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
{
if(!create || d->tag[FlacID3v2Index])
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
d->tag.set(FlacID3v2Index, new ID3v2::Tag);
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, create);
}
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)

View File

@ -52,7 +52,6 @@ public:
ID3v2Header(0),
ID3v2Location(-1),
ID3v2Size(0),
tag(2),
properties(0),
scanned(false),
hasAPE(false),
@ -74,7 +73,7 @@ public:
offset_t ID3v2Location;
uint ID3v2Size;
TagUnion tag;
DoubleTagUnion tag;
AudioProperties *properties;
bool scanned;

View File

@ -55,7 +55,6 @@ public:
APEFooterLocation(-1),
APEOriginalSize(0),
ID3v1Location(-1),
tag(3),
hasID3v2(false),
hasID3v1(false),
hasAPE(false),
@ -80,7 +79,7 @@ public:
offset_t ID3v1Location;
TagUnion tag;
TripleTagUnion tag;
// These indicate whether the file *on disk* has these tags, not if
// this data structure does. This is used in computing offsets.

View File

@ -1,6 +1,6 @@
/***************************************************************************
copyright : (C) 2012 by Tsuda Kageyu
email : wheeler@kde.org
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
@ -31,14 +31,15 @@
using namespace TagLib;
using namespace RIFF::Info;
namespace {
static bool isValidChunkID(const ByteVector &name)
namespace
{
bool isValidChunkID(const ByteVector &name)
{
if(name.size() != 4)
return false;
for(int i = 0; i < 4; i++) {
if(name[i] < 32 || name[i] > 127)
if(name[i] < 32 || 127 < name[i])
return false;
}
@ -86,7 +87,9 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::Info::Tag::Tag(const ByteVector &data) : TagLib::Tag()
RIFF::Info::Tag::Tag(const ByteVector &data)
: TagLib::Tag()
, d(new TagPrivate())
{
parse(data);
}
@ -193,7 +196,7 @@ String RIFF::Info::Tag::fieldText(const ByteVector &id) const
void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s)
{
// id must be four-byte long pure ascii string.
// id must be four-byte long pure ASCII string.
if(!isValidChunkID(id))
return;

View File

@ -45,8 +45,7 @@ class RIFF::WAV::File::FilePrivate
public:
FilePrivate() :
properties(0),
tagChunkID("ID3 "),
tag(2)
tagChunkID("ID3 ")
{
}
@ -59,7 +58,7 @@ public:
ByteVector tagChunkID;
TagUnion tag;
DoubleTagUnion tag;
};
////////////////////////////////////////////////////////////////////////////////
@ -87,9 +86,9 @@ RIFF::WAV::File::~File()
delete d;
}
ID3v2::Tag *RIFF::WAV::File::tag() const
TagLib::Tag *RIFF::WAV::File::tag() const
{
return ID3v2Tag();
return &d->tag;
}
ID3v2::Tag *RIFF::WAV::File::ID3v2Tag() const

View File

@ -94,12 +94,10 @@ namespace TagLib {
virtual ~File();
/*!
* Returns the ID3v2 Tag for this file.
*
* \note This method does not return all the tags for this file for
* backward compatibility. Will be fixed in TagLib 2.0.
* Returns the Tag for this file. This will be an ID3v2 tag, an INFO tag
* or a combination of the two.
*/
ID3v2::Tag *tag() const;
virtual TagLib::Tag *tag() const;
/*!
* Returns the ID3v2 Tag for this file.

View File

@ -27,168 +27,184 @@
#include "tstringlist.h"
#include "tpropertymap.h"
using namespace TagLib;
namespace
{
typedef std::vector<RefCountPtr<Tag> > TagVector;
typedef TagVector::iterator TagIterator;
typedef TagVector::const_iterator TagConstIterator;
}
#define stringUnion(method) \
for(TagConstIterator it = d->tags.begin(); it != d->tags.end(); ++it) { \
String val = (*it) ? (*it)->method() : String::null; \
for(size_t j = 0; j < COUNT; ++j) { \
String val = d->tags[j] ? d->tags[j]->method() : String::null; \
if(!val.isEmpty()) \
return val; \
} \
return String::null;
#define numberUnion(method) \
for(TagConstIterator it = d->tags.begin(); it != d->tags.end(); ++it) { \
uint val = (*it) ? (*it)->method() : 0; \
for(size_t j = 0; j < COUNT; ++j) { \
uint val = d->tags[j] ? d->tags[j]->method() : 0; \
if(val > 0) \
return val; \
} \
return 0;
#define setUnion(method, value) \
for(TagIterator it = d->tags.begin(); it != d->tags.end(); ++it) { \
if(*it) \
(*it)->set##method(value); \
for(size_t j = 0; j < COUNT; ++j) { \
if(d->tags[j]) \
d->tags[j]->set##method(value); \
}
class TagUnion::TagUnionPrivate
namespace TagLib
{
public:
TagUnionPrivate(size_t count)
: tags(count)
template <size_t COUNT>
class TagUnion<COUNT>::TagUnionPrivate
{
public:
NonRefCountPtr<Tag> tags[COUNT];
};
template <size_t COUNT>
TagUnion<COUNT>::TagUnion()
: d(new TagUnionPrivate())
{
}
TagVector tags;
};
TagUnion::TagUnion(size_t count)
: d(new TagUnionPrivate(count))
{
}
TagUnion::~TagUnion()
{
}
Tag *TagUnion::operator[](size_t index) const
{
return tag(index);
}
Tag *TagUnion::tag(size_t index) const
{
return d->tags[index].get();
}
void TagUnion::set(size_t index, Tag *tag)
{
d->tags[index].reset(tag);
}
PropertyMap TagUnion::properties() const
{
for(TagConstIterator it = d->tags.begin(); it != d->tags.end(); ++it) {
if(*it)
return (*it)->properties();
template <size_t COUNT>
TagUnion<COUNT>::~TagUnion()
{
}
return PropertyMap();
}
void TagUnion::removeUnsupportedProperties(const StringList &unsupported)
{
for(TagIterator it = d->tags.begin(); it != d->tags.end(); ++it) {
if(*it)
(*it)->removeUnsupportedProperties(unsupported);
}
}
String TagUnion::title() const
{
stringUnion(title);
}
String TagUnion::artist() const
{
stringUnion(artist);
}
String TagUnion::album() const
{
stringUnion(album);
}
String TagUnion::comment() const
{
stringUnion(comment);
}
String TagUnion::genre() const
{
stringUnion(genre);
}
TagLib::uint TagUnion::year() const
{
numberUnion(year);
}
TagLib::uint TagUnion::track() const
{
numberUnion(track);
}
void TagUnion::setTitle(const String &s)
{
setUnion(Title, s);
}
void TagUnion::setArtist(const String &s)
{
setUnion(Artist, s);
}
void TagUnion::setAlbum(const String &s)
{
setUnion(Album, s);
}
void TagUnion::setComment(const String &s)
{
setUnion(Comment, s);
}
void TagUnion::setGenre(const String &s)
{
setUnion(Genre, s);
}
void TagUnion::setYear(uint i)
{
setUnion(Year, i);
}
void TagUnion::setTrack(uint i)
{
setUnion(Track, i);
}
bool TagUnion::isEmpty() const
{
for(TagIterator it = d->tags.begin(); it != d->tags.end(); ++it) {
if(*it && !(*it)->isEmpty())
return false;
template <size_t COUNT>
Tag *TagUnion<COUNT>::operator[](size_t index) const
{
return tag(index);
}
return true;
}
template <size_t COUNT>
Tag *TagUnion<COUNT>::tag(size_t index) const
{
return d->tags[index].get();
}
template <size_t COUNT>
void TagUnion<COUNT>::set(size_t index, Tag *tag)
{
d->tags[index].reset(tag);
}
template <size_t COUNT>
PropertyMap TagUnion<COUNT>::properties() const
{
for(size_t i = 0; i < COUNT; ++i) {
if(d->tags[i])
return d->tags[i]->properties();
}
return PropertyMap();
}
template <size_t COUNT>
void TagUnion<COUNT>::removeUnsupportedProperties(const StringList &unsupported)
{
for(size_t i = 0; i < COUNT; ++i) {
if(d->tags[i])
d->tags[i]->removeUnsupportedProperties(unsupported);
}
}
template <size_t COUNT>
String TagUnion<COUNT>::title() const
{
stringUnion(title);
}
template <size_t COUNT>
String TagUnion<COUNT>::artist() const
{
stringUnion(artist);
}
template <size_t COUNT>
String TagUnion<COUNT>::album() const
{
stringUnion(album);
}
template <size_t COUNT>
String TagUnion<COUNT>::comment() const
{
stringUnion(comment);
}
template <size_t COUNT>
String TagUnion<COUNT>::genre() const
{
stringUnion(genre);
}
template <size_t COUNT>
TagLib::uint TagUnion<COUNT>::year() const
{
numberUnion(year);
}
template <size_t COUNT>
TagLib::uint TagUnion<COUNT>::track() const
{
numberUnion(track);
}
template <size_t COUNT>
void TagUnion<COUNT>::setTitle(const String &s)
{
setUnion(Title, s);
}
template <size_t COUNT>
void TagUnion<COUNT>::setArtist(const String &s)
{
setUnion(Artist, s);
}
template <size_t COUNT>
void TagUnion<COUNT>::setAlbum(const String &s)
{
setUnion(Album, s);
}
template <size_t COUNT>
void TagUnion<COUNT>::setComment(const String &s)
{
setUnion(Comment, s);
}
template <size_t COUNT>
void TagUnion<COUNT>::setGenre(const String &s)
{
setUnion(Genre, s);
}
template <size_t COUNT>
void TagUnion<COUNT>::setYear(uint i)
{
setUnion(Year, i);
}
template <size_t COUNT>
void TagUnion<COUNT>::setTrack(uint i)
{
setUnion(Track, i);
}
template <size_t COUNT>
bool TagUnion<COUNT>::isEmpty() const
{
for(size_t i = 0; i < COUNT; ++i) {
if(d->tags[i] && !d->tags[i]->isEmpty())
return false;
}
return true;
}
// All the versions of TagUnion should be explicitly instantiated here.
template class TagUnion<2>;
template class TagUnion<3>;
}

View File

@ -36,6 +36,7 @@ namespace TagLib {
* \internal
*/
template <size_t COUNT>
class TagUnion : public Tag
{
public:
@ -45,7 +46,7 @@ namespace TagLib {
/*!
* Creates a TagLib::Tag that is the union of \a count tags.
*/
TagUnion(size_t count);
TagUnion();
virtual ~TagUnion();
@ -85,12 +86,15 @@ namespace TagLib {
}
private:
TagUnion(const Tag &);
TagUnion &operator=(const Tag &);
class TagUnionPrivate;
NonRefCountPtr<TagUnionPrivate> d;
};
// If you add a new typedef here, add a corresponding explicit instantiation
// at the end of tagunion.cpp as well.
typedef TagUnion<2> DoubleTagUnion;
typedef TagUnion<3> TripleTagUnion;
}
#endif

View File

@ -312,7 +312,8 @@ inline T toNumber(const ByteVector &v, size_t offset)
static const bool swap = (ENDIAN == LittleEndian);
#endif
if(LENGTH >= sizeof(T) && offset + LENGTH <= v.size()) {
if(LENGTH >= sizeof(T) && offset + LENGTH <= v.size())
{
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
T tmp;
::memcpy(&tmp, v.data() + offset, sizeof(T));
@ -322,7 +323,8 @@ inline T toNumber(const ByteVector &v, size_t offset)
else
return tmp;
}
else {
else if(offset < v.size())
{
const size_t length = std::min(LENGTH, v.size() - offset);
T sum = 0;
for(size_t i = 0; i < length; i++) {
@ -332,6 +334,11 @@ inline T toNumber(const ByteVector &v, size_t offset)
return sum;
}
else
{
debug("toNumber<T>() - offset is out of range. Returning 0.");
return 0;
}
}
template <typename T, Endianness ENDIAN>

View File

@ -54,7 +54,6 @@ public:
ID3v2Location(-1),
ID3v2OriginalSize(0),
ID3v1Location(-1),
tag(2),
properties(0),
hasID3v1(false),
hasID3v2(false) {}
@ -70,7 +69,7 @@ public:
offset_t ID3v1Location;
TagUnion tag;
DoubleTagUnion tag;
AudioProperties *properties;

View File

@ -53,7 +53,6 @@ public:
APELocation(-1),
APESize(0),
ID3v1Location(-1),
tag(2),
properties(0),
hasAPE(false),
hasID3v1(false) {}
@ -68,7 +67,7 @@ public:
offset_t ID3v1Location;
TagUnion tag;
DoubleTagUnion tag;
AudioProperties *properties;