]> granicus.if.org Git - taglib/commitdiff
Ok, think I've got this all sorted out a bit. Code is much simpler now,
authorScott Wheeler <wheeler@kde.org>
Thu, 31 Jan 2008 05:46:13 +0000 (05:46 +0000)
committerScott Wheeler <wheeler@kde.org>
Thu, 31 Jan 2008 05:46:13 +0000 (05:46 +0000)
though much of this could be moved into the base class as there's a lot
of copy-paste action going on.

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@768992 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

taglib/flac/flacfile.cpp
taglib/mpc/combinedtag.h [deleted file]
taglib/mpc/mpcfile.cpp
taglib/mpeg/mpegfile.cpp
taglib/tagunion.cpp
taglib/tagunion.h
taglib/trueaudio/trueaudiofile.cpp
taglib/wavpack/wavpackfile.cpp

index 6d3d6cf2b5b12c159f6d813ce2dd4b854703c88e..2cf35ad246590cb4a6c6d74b547fca4e9d35ec37 100644 (file)
@@ -227,26 +227,18 @@ ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
   if(!create || d->tag[ID3v2Index])
     return static_cast<ID3v2::Tag *>(d->tag[ID3v2Index]);
 
-  d->tag.setTag(ID3v2Index, new ID3v2::Tag);
+  d->tag.set(ID3v2Index, new ID3v2::Tag);
   return static_cast<ID3v2::Tag *>(d->tag[ID3v2Index]);
 }
 
 ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
 {
-  if(!create || d->tag[ID3v1Index])
-    return static_cast<ID3v1::Tag *>(d->tag[ID3v1Index]);
-
-  d->tag.setTag(ID3v1Index, new ID3v1::Tag);
-  return static_cast<ID3v1::Tag *>(d->tag[ID3v1Index]);
+  return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
 }
 
 Ogg::XiphComment *FLAC::File::xiphComment(bool create)
 {
-  if(!create || d->tag[XiphIndex])
-    return static_cast<Ogg::XiphComment *>(d->tag[XiphIndex]);
-
-  d->tag.setTag(XiphIndex, new Ogg::XiphComment);
-  return static_cast<Ogg::XiphComment *>(d->tag[XiphIndex]);
+  return d->tag.access<Ogg::XiphComment>(XiphIndex, create);
 }
 
 void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
@@ -267,12 +259,12 @@ void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
 
   if(d->ID3v2Location >= 0) {
 
-    d->tag.setTag(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
+    d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
 
     d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
 
     if(ID3v2Tag()->header()->tagSize() <= 0)
-      d->tag.setTag(ID3v2Index, 0);
+      d->tag.set(ID3v2Index, 0);
     else
       d->hasID3v2 = true;
   }
@@ -282,7 +274,7 @@ void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
   d->ID3v1Location = findID3v1();
 
   if(d->ID3v1Location >= 0) {
-    d->tag.setTag(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
+    d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
     d->hasID3v1 = true;
   }
 
@@ -294,9 +286,9 @@ void FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
     return;
 
   if(d->hasXiphComment)
-    d->tag.setTag(XiphIndex, new Ogg::XiphComment(xiphCommentData()));
+    d->tag.set(XiphIndex, new Ogg::XiphComment(xiphCommentData()));
   else
-    d->tag.setTag(XiphIndex, new Ogg::XiphComment);
+    d->tag.set(XiphIndex, new Ogg::XiphComment);
 
   if(readProperties)
     d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
diff --git a/taglib/mpc/combinedtag.h b/taglib/mpc/combinedtag.h
deleted file mode 100644 (file)
index 03df615..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/***************************************************************************
-    copyright            : (C) 2004 by Allan Sandfeld Jensen
-    email                : kde@carewolf.org
- ***************************************************************************/
-
-/***************************************************************************
- *   This library is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU Lesser General Public License version   *
- *   2.1 as published by the Free Software Foundation.                     *
- *                                                                         *
- *   This library is distributed in the hope that it will be useful, but   *
- *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
- *   Lesser General Public License for more details.                       *
- *                                                                         *
- *   You should have received a copy of the GNU Lesser General Public      *
- *   License along with this library; if not, write to the Free Software   *
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
- *   USA                                                                   *
- *                                                                         *
- *   Alternatively, this file is available under the Mozilla Public        *
- *   License Version 1.1.  You may obtain a copy of the License at         *
- *   http://www.mozilla.org/MPL/                                           *
- ***************************************************************************/
-
-#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header
-
-#ifndef TAGLIB_COMBINEDTAG_H
-#define TAGLIB_COMBINEDTAG_H
-
-////////////////////////////////////////////////////////////////////////////////
-// Note that this header is not installed.
-////////////////////////////////////////////////////////////////////////////////
-
-#include <tag.h>
-
-namespace TagLib {
-
-  /*!
-   * A union of two TagLib::Tags.
-   */
-  class CombinedTag : public TagLib::Tag
-  {
-  public:
-    CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0)
-               : TagLib::Tag(),
-                 tag1(tag1), tag2(tag2) {}
-
-    virtual String title() const {
-      if(tag1 && !tag1->title().isEmpty())
-          return tag1->title();
-
-      if(tag2)
-          return tag2->title();
-
-      return String::null;
-    }
-
-    virtual String artist() const {
-      if(tag1 && !tag1->artist().isEmpty())
-          return tag1->artist();
-
-      if(tag2)
-          return tag2->artist();
-
-      return String::null;
-    }
-
-    virtual String album() const {
-      if(tag1 && !tag1->album().isEmpty())
-          return tag1->album();
-
-      if(tag2)
-          return tag2->album();
-
-      return String::null;
-    }
-
-    virtual String comment() const {
-      if(tag1 && !tag1->comment().isEmpty())
-          return tag1->comment();
-
-      if(tag2)
-          return tag2->comment();
-
-      return String::null;
-    }
-
-    virtual String genre() const {
-      if(tag1 && !tag1->genre().isEmpty())
-          return tag1->genre();
-
-      if(tag2)
-          return tag2->genre();
-
-      return String::null;
-    }
-
-    virtual uint year() const {
-      if(tag1 && tag1->year() > 0)
-          return tag1->year();
-
-      if(tag2)
-          return tag2->year();
-
-      return 0;
-    }
-
-    virtual uint track() const {
-      if(tag1 && tag1->track() > 0)
-          return tag1->track();
-
-      if(tag2)
-          return tag2->track();
-
-      return 0;
-    }
-
-    virtual void setTitle(const String &s) {
-      if(tag1)
-          tag1->setTitle(s);
-      if(tag2)
-          tag2->setTitle(s);
-    }
-
-    virtual void setArtist(const String &s) {
-      if(tag1)
-          tag1->setArtist(s);
-      if(tag2)
-          tag2->setArtist(s);
-    }
-
-    virtual void setAlbum(const String &s) {
-      if(tag1)
-          tag1->setAlbum(s);
-      if(tag2)
-          tag2->setAlbum(s);
-    }
-
-    virtual void setComment(const String &s) {
-      if(tag1)
-          tag1->setComment(s);
-      if(tag2)
-          tag2->setComment(s);
-    }
-
-    virtual void setGenre(const String &s) {
-      if(tag1)
-          tag1->setGenre(s);
-      if(tag2)
-          tag2->setGenre(s);
-    }
-
-    virtual void setYear(uint i) {
-      if(tag1)
-          tag1->setYear(i);
-      if(tag2)
-          tag2->setYear(i);
-    }
-
-    virtual void setTrack(uint i) {
-      if(tag1)
-          tag1->setTrack(i);
-      if(tag2)
-          tag2->setTrack(i);
-    }
-
-  private:
-      Tag *tag1;
-      Tag *tag2;
-  };
-}
-
-#endif
-#endif
index 0d9fe636ecc41ee8ceb2ebbbca35a8f04eb77118..922bf838446d5e4728a11e1e7c0be37c7be22ff7 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <tbytevector.h>
 #include <tstring.h>
+#include <tagunion.h>
 #include <tdebug.h>
 
 #include "mpcfile.h"
 #include "id3v2header.h"
 #include "apetag.h"
 #include "apefooter.h"
-#include "combinedtag.h"
 
 using namespace TagLib;
 
+namespace
+{
+  enum { APEIndex, ID3v1Index };
+}
+
 class MPC::File::FilePrivate
 {
 public:
   FilePrivate() :
-    APETag(0),
     APELocation(-1),
     APESize(0),
-    ID3v1Tag(0),
     ID3v1Location(-1),
     ID3v2Header(0),
     ID3v2Location(-1),
     ID3v2Size(0),
-    tag(0),
     properties(0),
     scanned(false),
     hasAPE(false),
@@ -57,26 +59,20 @@ public:
 
   ~FilePrivate()
   {
-    if (tag != ID3v1Tag && tag != APETag) delete tag;
-    delete ID3v1Tag;
-    delete APETag;
     delete ID3v2Header;
     delete properties;
   }
 
-  APE::Tag *APETag;
-  // long APEFooter;
   long APELocation;
   uint APESize;
 
-  ID3v1::Tag *ID3v1Tag;
   long ID3v1Location;
 
   ID3v2::Header *ID3v2Header;
   long ID3v2Location;
   uint ID3v2Size;
 
-  Tag *tag;
+  TagUnion tag;
 
   Properties *properties;
   bool scanned;
@@ -107,7 +103,7 @@ MPC::File::~File()
 
 TagLib::Tag *MPC::File::tag() const
 {
-  return d->tag;
+  return &d->tag;
 }
 
 MPC::Properties *MPC::File::audioProperties() const
@@ -135,15 +131,15 @@ bool MPC::File::save()
 
   // Update ID3v1 tag
 
-  if(d->ID3v1Tag) {
+  if(ID3v1Tag()) {
     if(d->hasID3v1) {
       seek(d->ID3v1Location);
-      writeBlock(d->ID3v1Tag->render());
+      writeBlock(ID3v1Tag()->render());
     }
     else {
       seek(0, End);
       d->ID3v1Location = tell();
-      writeBlock(d->ID3v1Tag->render());
+      writeBlock(ID3v1Tag()->render());
       d->hasID3v1 = true;
     }
   } else
@@ -158,13 +154,13 @@ bool MPC::File::save()
 
   // Update APE tag
 
-  if(d->APETag) {
+  if(APETag()) {
     if(d->hasAPE)
-      insert(d->APETag->render(), d->APELocation, d->APESize);
+      insert(APETag()->render(), d->APELocation, d->APESize);
     else {
       if(d->hasID3v1)  {
-        insert(d->APETag->render(), d->ID3v1Location, 0);
-        d->APESize = d->APETag->footer()->completeTagSize();
+        insert(APETag()->render(), d->ID3v1Location, 0);
+        d->APESize = APETag()->footer()->completeTagSize();
         d->hasAPE = true;
         d->APELocation = d->ID3v1Location;
         d->ID3v1Location += d->APESize;
@@ -172,8 +168,8 @@ bool MPC::File::save()
       else {
         seek(0, End);
         d->APELocation = tell();
-        writeBlock(d->APETag->render());
-        d->APESize = d->APETag->footer()->completeTagSize();
+        writeBlock(APETag()->render());
+        d->APESize = APETag()->footer()->completeTagSize();
         d->hasAPE = true;
       }
     }
@@ -183,7 +179,7 @@ bool MPC::File::save()
       removeBlock(d->APELocation, d->APESize);
       d->hasAPE = false;
       if(d->hasID3v1) {
-        if (d->ID3v1Location > d->APELocation)
+        if(d->ID3v1Location > d->APELocation)
           d->ID3v1Location -= d->APESize;
       }
     }
@@ -193,48 +189,19 @@ bool MPC::File::save()
 
 ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
 {
-  if(!create || d->ID3v1Tag)
-    return d->ID3v1Tag;
-
-  // no ID3v1 tag exists and we've been asked to create one
-
-  d->ID3v1Tag = new ID3v1::Tag;
-
-  if(d->APETag)
-    d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
-  else
-    d->tag = d->ID3v1Tag;
-
-  return d->ID3v1Tag;
+  return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
 }
 
 APE::Tag *MPC::File::APETag(bool create)
 {
-  if(!create || d->APETag)
-    return d->APETag;
-
-  // no APE tag exists and we've been asked to create one
-
-  d->APETag = new APE::Tag;
-
-  if(d->ID3v1Tag)
-    d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
-  else
-    d->tag = d->APETag;
-
-  return d->APETag;
+  return d->tag.access<APE::Tag>(APEIndex, create);
 }
 
 void MPC::File::strip(int tags)
 {
   if(tags & ID3v1) {
-    delete d->ID3v1Tag;
-    d->ID3v1Tag = 0;
-
-    if(d->APETag)
-      d->tag = d->APETag;
-    else
-      d->tag = d->APETag = new APE::Tag;
+    d->tag.set(ID3v1Index, 0);
+    APETag(true);
   }
 
   if(tags & ID3v2) {
@@ -243,13 +210,10 @@ void MPC::File::strip(int tags)
   }
 
   if(tags & APE) {
-    delete d->APETag;
-    d->APETag = 0;
+    d->tag.set(APEIndex, 0);
 
-    if(d->ID3v1Tag)
-      d->tag = d->ID3v1Tag;
-    else
-      d->tag = d->APETag = new APE::Tag;
+    if(!ID3v1Tag())
+      APETag(true);
   }
 }
 
@@ -270,7 +234,7 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty
   d->ID3v1Location = findID3v1();
 
   if(d->ID3v1Location >= 0) {
-    d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location);
+    d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
     d->hasID3v1 = true;
   }
 
@@ -281,24 +245,15 @@ void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty
   d->APELocation = findAPE();
 
   if(d->APELocation >= 0) {
-    d->APETag = new APE::Tag(this, d->APELocation);
-    d->APESize = d->APETag->footer()->completeTagSize();
-    d->APELocation = d->APELocation + d->APETag->footer()->size() - d->APESize;
+    d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
+
+    d->APESize = APETag()->footer()->completeTagSize();
+    d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
     d->hasAPE = true;
   }
 
-  if(d->hasID3v1 && d->hasAPE)
-    d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
-  else {
-    if(d->hasID3v1)
-      d->tag = d->ID3v1Tag;
-    else {
-      if(d->hasAPE)
-        d->tag = d->APETag;
-      else
-        d->tag = d->APETag = new APE::Tag;
-    }
-  }
+  if(!d->hasID3v1)
+    APETag(true);
 
   // Look for and skip an ID3v2 tag
 
index 58622d622954a4fff920c8a8190130b76bf5e1db..18dc75c0a875d25e710447b70d63adae1ea67a26 100644 (file)
@@ -41,27 +41,6 @@ using namespace TagLib;
 namespace
 {
   enum { ID3v2Index = 0, APEIndex = 1, ID3v1Index = 2 };
-
-  class MPEGTag : public TagUnion
-  {
-  public:
-    virtual Tag *tag(int index, AccessType type) const
-    {
-      if(type == Write)
-      {
-       if(index == ID3v2Index && !(*this)[ID3v2Index])
-       {
-         const_cast<MPEGTag *>(this)->setTag(ID3v2Index, new ID3v2::Tag);
-       }
-       else if(index == ID3v1Index && !(*this)[ID3v1Index])
-       {
-         const_cast<MPEGTag *>(this)->setTag(ID3v1Index, new ID3v1::Tag);
-       }
-      }
-
-      return TagUnion::tag(index);
-    }
-  };
 }
 
 class MPEG::File::FilePrivate
@@ -97,7 +76,7 @@ public:
 
   long ID3v1Location;
 
-  MPEGTag tag;
+  TagUnion tag;
 
   // These indicate whether the file *on disk* has these tags, not if
   // this data structure does.  This is used in computing offsets.
@@ -257,25 +236,17 @@ bool MPEG::File::save(int tags, bool stripOthers)
 
 ID3v2::Tag *MPEG::File::ID3v2Tag(bool create)
 {
-  return static_cast<ID3v2::Tag *>(
-    d->tag.tag(ID3v2Index, create ? MPEGTag::Write : MPEGTag::Read));
+  return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
 }
 
 ID3v1::Tag *MPEG::File::ID3v1Tag(bool create)
 {
-  return static_cast<ID3v1::Tag *>(
-    d->tag.tag(ID3v1Index, create ? MPEGTag::Write : MPEGTag::Read));
+  return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
 }
 
 APE::Tag *MPEG::File::APETag(bool create)
 {
-  if(!create || d->tag[APEIndex])
-    return static_cast<APE::Tag *>(d->tag[APEIndex]);
-
-  debug("Creating APE Tag.");
-
-  d->tag.setTag(APEIndex, new APE::Tag);
-  return static_cast<APE::Tag *>(d->tag[APEIndex]);
+  return d->tag.access<APE::Tag>(APEIndex, create);
 }
 
 bool MPEG::File::strip(int tags)
@@ -297,7 +268,7 @@ bool MPEG::File::strip(int tags, bool freeMemory)
     d->hasID3v2 = false;
 
     if(freeMemory)
-      d->tag.setTag(ID3v2Index, 0);
+      d->tag.set(ID3v2Index, 0);
 
     // v1 tag location has changed, update if it exists
 
@@ -316,7 +287,7 @@ bool MPEG::File::strip(int tags, bool freeMemory)
     d->hasID3v1 = false;
 
     if(freeMemory)
-      d->tag.setTag(ID3v1Index, 0);
+      d->tag.set(ID3v1Index, 0);
   }
 
   if((tags & APE) && d->hasAPE) {
@@ -329,7 +300,7 @@ bool MPEG::File::strip(int tags, bool freeMemory)
     }
 
     if(freeMemory)
-      d->tag.setTag(APEIndex, 0);
+      d->tag.set(APEIndex, 0);
   }
 
   return true;
@@ -411,12 +382,12 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
 
   if(d->ID3v2Location >= 0) {
 
-    d->tag.setTag(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
+    d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
 
     d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
 
     if(ID3v2Tag()->header()->tagSize() <= 0)
-      d->tag.setTag(ID3v2Index, 0);
+      d->tag.set(ID3v2Index, 0);
     else
       d->hasID3v2 = true;
   }
@@ -426,7 +397,7 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
   d->ID3v1Location = findID3v1();
 
   if(d->ID3v1Location >= 0) {
-    d->tag.setTag(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
+    d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
     d->hasID3v1 = true;
   }
 
@@ -436,9 +407,7 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
 
   if(d->APELocation >= 0) {
 
-    debug("Found APE");
-
-    d->tag.setTag(APEIndex, new APE::Tag(this, d->APELocation));
+    d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
 
     d->APEOriginalSize = APETag()->footer()->completeTagSize();
 
@@ -449,6 +418,11 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle
 
   if(readProperties)
     d->properties = new Properties(this, propertiesStyle);
+
+  // Make sure that we have our default tag types available.
+
+  ID3v2Tag(true);
+  ID3v1Tag(true);
 }
 
 long MPEG::File::findID3v2()
index b29bb1f02a9b5930f42dbf46755ad36e064c894e..ae181eb8690d9347d152635df9f0a415be7af5f4 100644 (file)
 using namespace TagLib;
 
 #define stringUnion(method)                                      \
-  if(tag(0, Read) && !tag(0, Read)->method().isEmpty())          \
-    return tag(0, Read)->method();                               \
-  if(tag(1, Read) && !tag(1, Read)->method().isEmpty())          \
-    return tag(1, Read)->method();                               \
-  if(tag(2, Read) && !tag(2, Read)->method().isEmpty())          \
-    return tag(2, Read)->method();                               \
+  if(tag(0) && !tag(0)->method().isEmpty())                     \
+    return tag(0)->method();                                    \
+  if(tag(1) && !tag(1)->method().isEmpty())                     \
+    return tag(1)->method();                                    \
+  if(tag(2) && !tag(2)->method().isEmpty())                     \
+    return tag(2)->method();                                    \
   return String::null                                            \
 
 #define numberUnion(method)                                      \
-  if(tag(0, Read) && tag(0, Read)->method() > 0)                 \
-    return tag(0, Read)->method();                               \
-  if(tag(1, Read) && tag(1, Read)->method() > 0)                 \
-    return tag(1, Read)->method();                               \
-  if(tag(2, Read) && tag(2, Read)->method() > 0)                 \
-    return tag(2, Read)->method();                               \
+  if(tag(0) && tag(0)->method() > 0)                            \
+    return tag(0)->method();                                    \
+  if(tag(1) && tag(1)->method() > 0)                            \
+    return tag(1)->method();                                    \
+  if(tag(2) && tag(2)->method() > 0)                            \
+    return tag(2)->method();                                    \
   return 0
 
 #define setUnion(method, value)                                  \
-  if(tag(0, Write))                                              \
-    tag(0, Write)->set##method(value);                           \
-  if(tag(1, Write))                                              \
-    tag(1, Write)->set##method(value);                           \
-  if(tag(2, Write))                                              \
-    tag(2, Write)->set##method(value);                           \
+  if(tag(0))                                                    \
+    tag(0)->set##method(value);                                         \
+  if(tag(1))                                                    \
+    tag(1)->set##method(value);                                         \
+  if(tag(2))                                                    \
+    tag(2)->set##method(value);                                         \
 
 class TagUnion::TagUnionPrivate
 {
@@ -87,15 +87,15 @@ TagUnion::~TagUnion()
 
 Tag *TagUnion::operator[](int index) const
 {
-  return d->tags[index];
+  return tag(index);
 }
 
-Tag *TagUnion::tag(int index, AccessType) const
+Tag *TagUnion::tag(int index) const
 {
-  return (*this)[index];
+  return d->tags[index];
 }
 
-void TagUnion::setTag(int index, Tag *tag)
+void TagUnion::set(int index, Tag *tag)
 {
   delete d->tags[index];
   d->tags[index] = tag;
index 7ccf5fb32dfacd5a3a25bde594061c72c283b4d5..80d996db6594e31a4fbd52353f4d8d7ecd046a8d 100644 (file)
@@ -49,22 +49,10 @@ namespace TagLib {
 
     virtual ~TagUnion();
 
-    /*!
-     * Simply returns the value for the the tag at \a index.
-     *
-     * \note This does not call tag()
-     *
-     * \see tag()
-     */
     Tag *operator[](int index) const;
+    Tag *tag(int index) const;
 
-    /*!
-     * By default just a call to operator[], but may be overridden if, for
-     * instance, it is desirable to create frames on write.
-     */
-    virtual Tag *tag(int index, AccessType type = Read) const;
-
-    void setTag(int index, Tag *tag);
+    void set(int index, Tag *tag);
 
     virtual String title() const;
     virtual String artist() const;
@@ -83,6 +71,15 @@ namespace TagLib {
     virtual void setTrack(uint i);
     virtual bool isEmpty() const;
 
+    template <class T> T *access(int index, bool create)
+    {
+      if(!create || tag(index))
+       return static_cast<T *>(tag(index));
+
+      set(index, new T);
+      return static_cast<T *>(tag(index));
+    }
+    
   private:
     TagUnion(const Tag &);
     TagUnion &operator=(const Tag &);
index c5bee76bcb1356a99bdbb591b719c764f7d4e06f..c5979ecfbbe6cd186686d955e3ffe52f3bae71a8 100644 (file)
 #include <tbytevector.h>
 #include <tstring.h>
 #include <tdebug.h>
+#include <tagunion.h>
 
 #include "trueaudiofile.h"
 #include "id3v1tag.h"
 #include "id3v2tag.h"
 #include "id3v2header.h"
-#include "combinedtag.h"
 
 using namespace TagLib;
 
+namespace
+{
+  enum { ID3v2Index = 0, ID3v1Index = 1 };
+}
+
 class TrueAudio::File::FilePrivate
 {
 public:
   FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
     ID3v2FrameFactory(frameFactory),
-    ID3v2Tag(0),
     ID3v2Location(-1),
     ID3v2OriginalSize(0),
-    ID3v1Tag(0),
     ID3v1Location(-1),
-    tag(0),
     properties(0),
     scanned(false),
     hasID3v1(false),
@@ -57,21 +59,16 @@ public:
 
   ~FilePrivate()
   {
-    if (tag != ID3v1Tag && tag != ID3v2Tag) delete tag;
-    delete ID3v1Tag;
-    delete ID3v2Tag;
     delete properties;
   }
 
   const ID3v2::FrameFactory *ID3v2FrameFactory;
-  ID3v2::Tag *ID3v2Tag;
   long ID3v2Location;
   uint ID3v2OriginalSize;
 
-  ID3v1::Tag *ID3v1Tag;
   long ID3v1Location;
 
-  Tag *tag;
+  TagUnion tag;
 
   Properties *properties;
   bool scanned;
@@ -111,7 +108,7 @@ TrueAudio::File::~File()
 
 TagLib::Tag *TrueAudio::File::tag() const
 {
-  return d->tag;
+  return &d->tag;
 }
 
 TrueAudio::Properties *TrueAudio::File::audioProperties() const
@@ -133,12 +130,12 @@ bool TrueAudio::File::save()
 
   // Update ID3v2 tag
 
-  if(d->ID3v2Tag && !d->ID3v2Tag->isEmpty()) {
+  if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
     if(!d->hasID3v2) {
       d->ID3v2Location = 0;
       d->ID3v2OriginalSize = 0;
     }
-    ByteVector data = d->ID3v2Tag->render();
+    ByteVector data = ID3v2Tag()->render();
     insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
     d->ID3v1Location -= d->ID3v2OriginalSize - data.size();
     d->ID3v2OriginalSize = data.size();
@@ -154,14 +151,14 @@ bool TrueAudio::File::save()
 
   // Update ID3v1 tag
 
-  if(d->ID3v1Tag && !d->ID3v1Tag->isEmpty()) {
+  if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
     if(!d->hasID3v1) {
       seek(0, End);
       d->ID3v1Location = tell();
     }
     else
       seek(d->ID3v1Location);
-    writeBlock(d->ID3v1Tag->render());
+    writeBlock(ID3v1Tag()->render());
     d->hasID3v1 = true;
   }
   else if(d->hasID3v1) {
@@ -175,58 +172,26 @@ bool TrueAudio::File::save()
 
 ID3v1::Tag *TrueAudio::File::ID3v1Tag(bool create)
 {
-  if(!create || d->ID3v1Tag)
-    return d->ID3v1Tag;
-
-  // no ID3v1 tag exists and we've been asked to create one
-
-  d->ID3v1Tag = new ID3v1::Tag;
-
-  if(d->ID3v2Tag)
-    d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag);
-  else
-    d->tag = d->ID3v1Tag;
-
-  return d->ID3v1Tag;
+  return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
 }
 
 ID3v2::Tag *TrueAudio::File::ID3v2Tag(bool create)
 {
-  if(!create || d->ID3v2Tag)
-    return d->ID3v2Tag;
-
-  // no ID3v2 tag exists and we've been asked to create one
-
-  d->ID3v2Tag = new ID3v2::Tag;
-
-  if(d->ID3v1Tag)
-    d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag);
-  else
-    d->tag = d->ID3v2Tag;
-
-  return d->ID3v2Tag;
+  return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
 }
 
 void TrueAudio::File::strip(int tags)
 {
   if(tags & ID3v1) {
-    delete d->ID3v1Tag;
-    d->ID3v1Tag = 0;
-
-    if(d->ID3v2Tag)
-      d->tag = d->ID3v2Tag;
-    else
-      d->tag = d->ID3v2Tag = new ID3v2::Tag;
+    d->tag.set(ID3v1Index, 0);
+    ID3v2Tag(true);
   }
 
   if(tags & ID3v2) {
-    delete d->ID3v2Tag;
-    d->ID3v2Tag = 0;
+    d->tag.set(ID3v2Index, 0);
 
-    if(d->ID3v1Tag)
-      d->tag = d->ID3v1Tag;
-    else
-      d->tag = d->ID3v2Tag = new ID3v2::Tag;
+    if(!ID3v1Tag())
+      ID3v2Tag(true);
   }
 }
 
@@ -243,14 +208,12 @@ void TrueAudio::File::read(bool readProperties, Properties::ReadStyle /* propert
 
   if(d->ID3v2Location >= 0) {
 
-    d->ID3v2Tag = new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory);
+    d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
 
-    d->ID3v2OriginalSize = d->ID3v2Tag->header()->completeTagSize();
+    d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
 
-    if(d->ID3v2Tag->header()->tagSize() <= 0) {
-      delete d->ID3v2Tag;
-      d->ID3v2Tag = 0;
-    }
+    if(ID3v2Tag()->header()->tagSize() <= 0)
+      d->tag.set(ID3v2Index, 0);
     else
       d->hasID3v2 = true;
   }
@@ -260,22 +223,12 @@ void TrueAudio::File::read(bool readProperties, Properties::ReadStyle /* propert
   d->ID3v1Location = findID3v1();
 
   if(d->ID3v1Location >= 0) {
-    d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location);
+    d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
     d->hasID3v1 = true;
   }
 
-  if(d->hasID3v1 && d->hasID3v2)
-    d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag);
-  else {
-    if(d->hasID3v1)
-      d->tag = d->ID3v1Tag;
-    else {
-      if(d->hasID3v2)
-        d->tag = d->ID3v2Tag;
-      else
-        d->tag = d->ID3v2Tag = new ID3v2::Tag;
-    }
-  }
+  if(!d->hasID3v1)
+    ID3v2Tag(true);
 
   // Look for TrueAudio metadata
 
index 37ea42e77eaa7f1cbb3049a260bb43dc5f20895b..e036025375463fda5ad08a6037d368269c96a359 100644 (file)
 #include <tbytevector.h>
 #include <tstring.h>
 #include <tdebug.h>
+#include <tagunion.h>
 
 #include "wavpackfile.h"
 #include "id3v1tag.h"
 #include "id3v2header.h"
 #include "apetag.h"
 #include "apefooter.h"
-#include "combinedtag.h"
 
 using namespace TagLib;
 
+namespace
+{
+  enum { APEIndex, ID3v1Index };
+}
+
 class WavPack::File::FilePrivate
 {
 public:
   FilePrivate() :
-    APETag(0),
     APELocation(-1),
     APESize(0),
-    ID3v1Tag(0),
     ID3v1Location(-1),
-    tag(0),
     properties(0),
     scanned(false),
     hasAPE(false),
@@ -57,20 +59,15 @@ public:
 
   ~FilePrivate()
   {
-    if (tag != ID3v1Tag && tag != APETag) delete tag;
-    delete ID3v1Tag;
-    delete APETag;
     delete properties;
   }
 
-  APE::Tag *APETag;
   long APELocation;
   uint APESize;
 
-  ID3v1::Tag *ID3v1Tag;
   long ID3v1Location;
 
-  Tag *tag;
+  TagUnion tag;
 
   Properties *properties;
   bool scanned;
@@ -100,7 +97,7 @@ WavPack::File::~File()
 
 TagLib::Tag *WavPack::File::tag() const
 {
-  return d->tag;
+  return &d->tag;
 }
 
 WavPack::Properties *WavPack::File::audioProperties() const
@@ -117,18 +114,19 @@ bool WavPack::File::save()
 
   // Update ID3v1 tag
 
-  if(d->ID3v1Tag) {
+  if(ID3v1Tag()) {
     if(d->hasID3v1) {
       seek(d->ID3v1Location);
-      writeBlock(d->ID3v1Tag->render());
+      writeBlock(ID3v1Tag()->render());
     }
     else {
       seek(0, End);
       d->ID3v1Location = tell();
-      writeBlock(d->ID3v1Tag->render());
+      writeBlock(ID3v1Tag()->render());
       d->hasID3v1 = true;
     }
-  } else
+  }
+  else {
     if(d->hasID3v1) {
       removeBlock(d->ID3v1Location, 128);
       d->hasID3v1 = false;
@@ -137,16 +135,17 @@ bool WavPack::File::save()
           d->APELocation -= 128;
       }
     }
+  }
 
   // Update APE tag
 
-  if(d->APETag) {
+  if(APETag()) {
     if(d->hasAPE)
-      insert(d->APETag->render(), d->APELocation, d->APESize);
+      insert(APETag()->render(), d->APELocation, d->APESize);
     else {
       if(d->hasID3v1)  {
-        insert(d->APETag->render(), d->ID3v1Location, 0);
-        d->APESize = d->APETag->footer()->completeTagSize();
+        insert(APETag()->render(), d->ID3v1Location, 0);
+        d->APESize = APETag()->footer()->completeTagSize();
         d->hasAPE = true;
         d->APELocation = d->ID3v1Location;
         d->ID3v1Location += d->APESize;
@@ -154,79 +153,49 @@ bool WavPack::File::save()
       else {
         seek(0, End);
         d->APELocation = tell();
-        writeBlock(d->APETag->render());
-        d->APESize = d->APETag->footer()->completeTagSize();
+        writeBlock(APETag()->render());
+        d->APESize = APETag()->footer()->completeTagSize();
         d->hasAPE = true;
       }
     }
   }
-  else
+  else {
     if(d->hasAPE) {
       removeBlock(d->APELocation, d->APESize);
       d->hasAPE = false;
       if(d->hasID3v1) {
-        if (d->ID3v1Location > d->APELocation)
+        if(d->ID3v1Location > d->APELocation) {
           d->ID3v1Location -= d->APESize;
+       }
       }
     }
+  }
 
    return true;
 }
 
 ID3v1::Tag *WavPack::File::ID3v1Tag(bool create)
 {
-  if(!create || d->ID3v1Tag)
-    return d->ID3v1Tag;
-
-  // no ID3v1 tag exists and we've been asked to create one
-
-  d->ID3v1Tag = new ID3v1::Tag;
-
-  if(d->APETag)
-    d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
-  else
-    d->tag = d->ID3v1Tag;
-
-  return d->ID3v1Tag;
+  return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
 }
 
 APE::Tag *WavPack::File::APETag(bool create)
 {
-  if(!create || d->APETag)
-    return d->APETag;
-
-  // no APE tag exists and we've been asked to create one
-
-  d->APETag = new APE::Tag;
-
-  if(d->ID3v1Tag)
-    d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
-  else
-    d->tag = d->APETag;
-
-  return d->APETag;
+  return d->tag.access<APE::Tag>(APEIndex, create);
 }
 
 void WavPack::File::strip(int tags)
 {
   if(tags & ID3v1) {
-    delete d->ID3v1Tag;
-    d->ID3v1Tag = 0;
-
-    if(d->APETag)
-      d->tag = d->APETag;
-    else
-      d->tag = d->APETag = new APE::Tag;
+    d->tag.set(ID3v1Index, 0);
+    APETag(true);
   }
 
   if(tags & APE) {
-    delete d->APETag;
-    d->APETag = 0;
+    d->tag.set(APEIndex, 0);
 
-    if(d->ID3v1Tag)
-      d->tag = d->ID3v1Tag;
-    else
-      d->tag = d->APETag = new APE::Tag;
+    if(!ID3v1Tag())
+      APETag(true);
   }
 }
 
@@ -241,7 +210,7 @@ void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertie
   d->ID3v1Location = findID3v1();
 
   if(d->ID3v1Location >= 0) {
-    d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location);
+    d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
     d->hasID3v1 = true;
   }
 
@@ -250,24 +219,14 @@ void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertie
   d->APELocation = findAPE();
 
   if(d->APELocation >= 0) {
-    d->APETag = new APE::Tag(this, d->APELocation);
-    d->APESize = d->APETag->footer()->completeTagSize();
-    d->APELocation = d->APELocation + d->APETag->footer()->size() - d->APESize;
+    d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
+    d->APESize = APETag()->footer()->completeTagSize();
+    d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
     d->hasAPE = true;
   }
 
-  if(d->hasID3v1 && d->hasAPE)
-    d->tag = new CombinedTag(d->APETag, d->ID3v1Tag);
-  else {
-    if(d->hasID3v1)
-      d->tag = d->ID3v1Tag;
-    else {
-      if(d->hasAPE)
-        d->tag = d->APETag;
-      else
-        d->tag = d->APETag = new APE::Tag;
-    }
-  }
+  if(!d->hasID3v1)
+    APETag(true);
 
   // Look for WavPack audio properties