]> granicus.if.org Git - taglib/commitdiff
Replace RefCounter with a smart pointer
authorTsuda kageyu <tsuda.kageyu@gmail.com>
Wed, 17 Apr 2013 01:10:25 +0000 (10:10 +0900)
committerTsuda kageyu <tsuda.kageyu@gmail.com>
Wed, 17 Apr 2013 01:10:25 +0000 (10:10 +0900)
24 files changed:
taglib/CMakeLists.txt
taglib/asf/asfattribute.cpp
taglib/asf/asfattribute.h
taglib/asf/asfpicture.cpp
taglib/asf/asfpicture.h
taglib/fileref.cpp
taglib/fileref.h
taglib/mp4/mp4coverart.cpp
taglib/mp4/mp4coverart.h
taglib/mp4/mp4item.cpp
taglib/mp4/mp4item.h
taglib/mpeg/mpegheader.cpp
taglib/mpeg/mpegheader.h
taglib/toolkit/taglib.h
taglib/toolkit/tbytevector.cpp
taglib/toolkit/tbytevector.h
taglib/toolkit/tiostream.h
taglib/toolkit/tlist.h
taglib/toolkit/tlist.tcc
taglib/toolkit/tmap.h
taglib/toolkit/tmap.tcc
taglib/toolkit/trefcountptr.h [new file with mode: 0644]
taglib/toolkit/tstring.cpp
taglib/toolkit/tstring.h

index a940caf5def3d2d4a726bfb897b6e0fb68db22ec..dab3430e8009a2b457f72c5efa8a715b3fef817b 100644 (file)
@@ -51,6 +51,7 @@ set(tag_HDRS
   toolkit/tmap.tcc
   toolkit/tpropertymap.h
   toolkit/tbyteswap.h
+  toolkit/trefcountptr.h
   mpeg/mpegfile.h
   mpeg/mpegproperties.h
   mpeg/mpegheader.h
@@ -311,6 +312,10 @@ if(ZLIB_FOUND)
        target_link_libraries(tag ${ZLIB_LIBRARIES})
 endif()
 
+if(WIN32 AND NOT TAGLIB_STATIC)
+       target_link_libraries(tag shlwapi.lib)
+endif()
+
 set_target_properties(tag PROPERTIES
   VERSION ${TAGLIB_SOVERSION_MAJOR}.${TAGLIB_SOVERSION_MINOR}.${TAGLIB_SOVERSION_PATCH}
   SOVERSION ${TAGLIB_SOVERSION_MAJOR}
index 2cfada7b0fa3d516321640a63b38bf010a811699..4ba2689bc3e455efb2d879b14d8af315b857210f 100644 (file)
@@ -34,7 +34,7 @@
 
 using namespace TagLib;
 
-class ASF::Attribute::AttributePrivate : public RefCounter
+class ASF::Attribute::AttributePrivate
 {
 public:
   AttributePrivate()
@@ -60,77 +60,71 @@ public:
 ////////////////////////////////////////////////////////////////////////////////
 
 ASF::Attribute::Attribute()
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = UnicodeType;
 }
 
 ASF::Attribute::Attribute(const ASF::Attribute &other)
   : d(other.d)
 {
-  d->ref();
 }
 
 ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
 {
-  if(d->deref())
-    delete d;
   d = other.d;
-  d->ref();
   return *this;
 }
 
 ASF::Attribute::~Attribute()
 {
-  if(d->deref())
-    delete d;
 }
 
 ASF::Attribute::Attribute(const String &value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = UnicodeType;
   d->stringValue = value;
 }
 
 ASF::Attribute::Attribute(const ByteVector &value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = BytesType;
   d->byteVectorValue = value;
 }
 
 ASF::Attribute::Attribute(const ASF::Picture &value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = BytesType;
   d->pictureValue = value;
 }
 
 ASF::Attribute::Attribute(unsigned int value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = DWordType;
   d->intValue = value;
 }
 
 ASF::Attribute::Attribute(unsigned long long value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = QWordType;
   d->longLongValue = value;
 }
 
 ASF::Attribute::Attribute(unsigned short value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = WordType;
   d->shortValue = value;
 }
 
 ASF::Attribute::Attribute(bool value)
+  : d(new AttributePrivate())
 {
-  d = new AttributePrivate;
   d->type = BoolType;
   d->boolValue = value;
 }
index 54eb0c7d104a07bcb3005e4276741e84926dfc27..ca26aec3f40da6c5bfc824da3147d03995d35902 100644 (file)
@@ -194,7 +194,7 @@ namespace TagLib
       ByteVector render(const String &name, int kind = 0) const;
 
       class AttributePrivate;
-      AttributePrivate *d;
+      RefCountPtr<AttributePrivate> d;
     };
   }
 
index c36ffa3a92411df9b189b242b52108e1bae9a865..82a38b6bc3e9cab0be880a9e082b9a3cd089be33 100644 (file)
@@ -35,7 +35,7 @@
 
 using namespace TagLib;
 
-class ASF::Picture::PicturePrivate : public RefCounter
+class ASF::Picture::PicturePrivate
 {
 public:
   bool valid;
@@ -50,21 +50,18 @@ public:
 ////////////////////////////////////////////////////////////////////////////////
 
 ASF::Picture::Picture()
+  : d(new PicturePrivate())
 {
-  d = new PicturePrivate();
   d->valid = true;
 }
 
 ASF::Picture::Picture(const Picture& other)
   : d(other.d)
 {
-  d->ref();
 }
 
 ASF::Picture::~Picture()
 {
-  if(d->deref())
-    delete d;
 }
 
 bool ASF::Picture::isValid() const
@@ -121,12 +118,7 @@ int ASF::Picture::dataSize() const
 
 ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other)
 {
-  if(other.d != d) {
-    if(d->deref())
-      delete d;
-    d = other.d;
-    d->ref();
-  }
+  d = other.d;
   return *this;
 }
 
index aa0a060c19f2eac21833b3ab7137f4dd7ca62bb2..aa838974639079dcb7c8314f38fd87272b1203f8 100644 (file)
@@ -207,10 +207,10 @@ namespace TagLib
       static Picture fromInvalid();
       friend class Attribute;
 #endif
-      private:
-        class PicturePrivate;
-        PicturePrivate *d;
-      };
+    private:
+      class PicturePrivate;
+      RefCountPtr<PicturePrivate> d;
+    };
   }
 }
 
index 859f3155bd72993f824e5f6e46db320086d8c11a..8e747fa844dc61e756e79c0735e1defc83b1bb3d 100644 (file)
 #include <config.h>
 #endif
 
+#ifdef _WIN32
+# include <Shlwapi.h>
+#endif
+
 #include <tfile.h>
 #include <tstring.h>
 #include <tdebug.h>
 
 using namespace TagLib;
 
-class FileRef::FileRefPrivate : public RefCounter
+class FileRef::FileRefPrivate 
 {
 public:
-  FileRefPrivate(File *f) : RefCounter(), file(f) {}
-  ~FileRefPrivate() {
-    delete file;
-  }
+  FileRefPrivate(File *f) : file(f) {}
 
-  File *file;
+  RefCountPtr<File> file;
   static List<const FileTypeResolver *> fileTypeResolvers;
 };
 
@@ -76,30 +77,28 @@ List<const FileRef::FileTypeResolver *> FileRef::FileRefPrivate::fileTypeResolve
 ////////////////////////////////////////////////////////////////////////////////
 
 FileRef::FileRef()
+  : d(new FileRefPrivate(0))
 {
-  d = new FileRefPrivate(0);
 }
 
-FileRef::FileRef(FileName fileName, bool readAudioProperties,
-                 AudioProperties::ReadStyle audioPropertiesStyle)
+FileRef::FileRef(
+  FileName fileName, bool readAudioProperties,  AudioProperties::ReadStyle audioPropertiesStyle)
+  : d(new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle)))
 {
-  d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle));
 }
 
 FileRef::FileRef(File *file)
+  : d(new FileRefPrivate(file))
 {
-  d = new FileRefPrivate(file);
 }
 
-FileRef::FileRef(const FileRef &ref) : d(ref.d)
+FileRef::FileRef(const FileRef &ref) 
+  : d(ref.d)
 {
-  d->ref();
 }
 
 FileRef::~FileRef()
 {
-  if(d->deref())
-    delete d;
 }
 
 Tag *FileRef::tag() const
@@ -122,7 +121,7 @@ AudioProperties *FileRef::audioProperties() const
 
 File *FileRef::file() const
 {
-  return d->file;
+  return d->file.get();
 }
 
 bool FileRef::save()
@@ -182,15 +181,7 @@ bool FileRef::isNull() const
 
 FileRef &FileRef::operator=(const FileRef &ref)
 {
-  if(&ref == this)
-    return *this;
-
-  if(d->deref())
-    delete d;
-
   d = ref.d;
-  d->ref();
-
   return *this;
 }
 
@@ -218,21 +209,36 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
 
   // Ok, this is really dumb for now, but it works for testing.
 
-  String s;
+  String ext;
 
 #ifdef _WIN32
-  s = (wcslen((const wchar_t *) fileName) > 0) ? String((const wchar_t *) fileName) : String((const char *) fileName);
+  // Avoids direct conversion from FileName to String
+  // because String can't accept non-Latin-1 string in char array.
+
+  if(!fileName.wstr().empty()) {
+    const wchar_t *pext = PathFindExtensionW(fileName.wstr().c_str());
+    if(*pext == L'.')
+      ext = String(pext + 1).upper();
+  }
+  else {
+    const char *pext = PathFindExtensionA(fileName.str().c_str());
+    if(*pext == '.')
+      ext = String(pext + 1).upper();
+  }
 #else
-  s = fileName;
+  {
+    String s = fileName;
+    const int pos = s.rfind(".");
+    if(pos != -1)
+      ext = s.substr(pos + 1).upper();
+  }
 #endif
 
   // If this list is updated, the method defaultFileExtensions() should also be
   // updated.  However at some point that list should be created at the same time
   // that a default file type resolver is created.
 
-  int pos = s.rfind(".");
-  if(pos != -1) {
-    String ext = s.substr(pos + 1).upper();
+  if(!ext.isEmpty()) {
     if(ext == "MP3")
       return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle);
     if(ext == "OGG")
@@ -280,3 +286,7 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
 
   return 0;
 }
+
+FileRef::FileTypeResolver::~FileTypeResolver() 
+{
+}
index 0f0c21a4dc77f917f9d5cd10657fcb80c9f05ffe..42cec8b486eed5b1d508c42aeecca42933cce554 100644 (file)
@@ -91,7 +91,6 @@ namespace TagLib {
 
     class TAGLIB_EXPORT FileTypeResolver
     {
-      TAGLIB_IGNORE_MISSING_DESTRUCTOR
     public:
       /*!
        * This method must be overridden to provide an additional file type
@@ -106,6 +105,8 @@ namespace TagLib {
                                bool readAudioProperties = true,
                                AudioProperties::ReadStyle
                                audioPropertiesStyle = AudioProperties::Average) const = 0;
+
+      virtual ~FileTypeResolver();
     };
 
     /*!
@@ -255,7 +256,7 @@ namespace TagLib {
 
   private:
     class FileRefPrivate;
-    FileRefPrivate *d;
+    RefCountPtr<FileRefPrivate> d;
   };
 
 } // namespace TagLib
index 928e3c4aa2f22f94f8ec0fdf4cfb2a066de5e8a9..5b6e6e230ac3e0d0c92a7d0a4301c0d7eff34af7 100644 (file)
 
 using namespace TagLib;
 
-class MP4::CoverArt::CoverArtPrivate : public RefCounter
+class MP4::CoverArt::CoverArtPrivate
 {
 public:
-  CoverArtPrivate() : RefCounter(), format(MP4::CoverArt::JPEG) {}
+  CoverArtPrivate() : format(MP4::CoverArt::JPEG) {}
 
   Format format;
   ByteVector data;
 };
 
 MP4::CoverArt::CoverArt(Format format, const ByteVector &data)
+  : d(new CoverArtPrivate())
 {
-  d = new CoverArtPrivate;
   d->format = format;
   d->data = data;
 }
 
 MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d)
 {
-  d->ref();
 }
 
 MP4::CoverArt &
 MP4::CoverArt::operator=(const CoverArt &item)
 {
-  if(d->deref()) {
-    delete d;
-  }
   d = item.d;
-  d->ref();
   return *this;
 }
 
 MP4::CoverArt::~CoverArt()
 {
-  if(d->deref()) {
-    delete d;
-  }
 }
 
 MP4::CoverArt::Format
index 64115b458ed8fafcb9c0adfb6e37783b0d96ea5b..b6b44c4968381bd6c9066e7113d95d9a5a73e85b 100644 (file)
@@ -63,7 +63,7 @@ namespace TagLib {
 
     private:
       class CoverArtPrivate;
-      CoverArtPrivate *d;
+      RefCountPtr<CoverArtPrivate> d;
     };
 
     typedef List<CoverArt> CoverArtList;
index af2cc65c80de9f06e3da1fcf27b50679c2004ba3..6a303652c58230348d9bd97e42e93cea7a170aaa 100644 (file)
 
 using namespace TagLib;
 
-class MP4::Item::ItemPrivate : public RefCounter
+class MP4::Item::ItemPrivate 
 {
 public:
-  ItemPrivate() : RefCounter(), valid(true), atomDataType(TypeUndefined) {}
+  ItemPrivate() : valid(true), atomDataType(TypeUndefined) {}
 
   bool valid;
   AtomDataType atomDataType;
@@ -54,86 +54,78 @@ public:
 };
 
 MP4::Item::Item()
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->valid = false;
 }
 
 MP4::Item::Item(const Item &item) : d(item.d)
 {
-  d->ref();
 }
 
 MP4::Item &
 MP4::Item::operator=(const Item &item)
 {
-  if(d->deref()) {
-    delete d;
-  }
   d = item.d;
-  d->ref();
   return *this;
 }
 
 MP4::Item::~Item()
 {
-  if(d->deref()) {
-    delete d;
-  }
 }
 
 MP4::Item::Item(bool value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_bool = value;
 }
 
 MP4::Item::Item(int value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_int = value;
 }
 
 MP4::Item::Item(uchar value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_byte = value;
 }
 
 MP4::Item::Item(uint value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_uint = value;
 }
 
 MP4::Item::Item(long long value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_longlong = value;
 }
 
 MP4::Item::Item(int value1, int value2)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_intPair.first = value1;
   d->m_intPair.second = value2;
 }
 
 MP4::Item::Item(const ByteVectorList &value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_byteVectorList = value;
 }
 
 MP4::Item::Item(const StringList &value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_stringList = value;
 }
 
 MP4::Item::Item(const MP4::CoverArtList &value)
+  : d(new ItemPrivate())
 {
-  d = new ItemPrivate;
   d->m_coverArtList = value;
 }
 
index be7aa1a17fc11760f424d8f2fc8bdf9922b367d4..3b4e23cd91ff1013813794aff3b7406de8e9fc49 100644 (file)
@@ -73,7 +73,7 @@ namespace TagLib {
 
     private:
       class ItemPrivate;
-      ItemPrivate *d;
+      RefCountPtr<ItemPrivate> d;
     };
 
   }
index c715dbc1435bf7884ab8fbb8e221c454c666a05a..bc98f4c979cad4d7b9d3b145e3ed346d56a1bf12 100644 (file)
@@ -33,7 +33,7 @@
 
 using namespace TagLib;
 
-class MPEG::Header::HeaderPrivate : public RefCounter
+class MPEG::Header::HeaderPrivate
 {
 public:
   HeaderPrivate() :
@@ -68,20 +68,18 @@ public:
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG::Header::Header(const ByteVector &data)
+  : d(new HeaderPrivate())
 {
-  d = new HeaderPrivate;
   parse(data);
 }
 
-MPEG::Header::Header(const Header &h) : d(h.d)
+MPEG::Header::Header(const Header &h) 
+  : d(h.d)
 {
-  d->ref();
 }
 
 MPEG::Header::~Header()
 {
-  if (d->deref())
-    delete d;
 }
 
 bool MPEG::Header::isValid() const
@@ -146,14 +144,7 @@ int MPEG::Header::samplesPerFrame() const
 
 MPEG::Header &MPEG::Header::operator=(const Header &h)
 {
-  if(&h == this)
-    return *this;
-
-  if(d->deref())
-    delete d;
-
   d = h.d;
-  d->ref();
   return *this;
 }
 
index 020ebd060302cd7ec4883aa94f5c4243b074bc00..7a352ed70811932d37b94c4bc2ff0e90d2227ef9 100644 (file)
@@ -27,6 +27,7 @@
 #define TAGLIB_MPEGHEADER_H
 
 #include "taglib_export.h"
+#include "trefcountptr.h"
 
 namespace TagLib {
 
@@ -158,7 +159,7 @@ namespace TagLib {
       void parse(const ByteVector &data);
 
       class HeaderPrivate;
-      HeaderPrivate *d;
+      RefCountPtr<HeaderPrivate> d;
     };
   }
 }
index dd4ee69da8b050b341f58bb681435369545cc9cc..03d16724f3200976916c893784496487e16516e3 100755 (executable)
 #include <string>
 #include <climits>
 
-#ifdef __APPLE__
-#  include <libkern/OSAtomic.h>
-#  define TAGLIB_ATOMIC_MAC
-#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-#  if !defined(NOMINMAX)
-#    define NOMINMAX
-#  endif
-#  include <windows.h>
-#  define TAGLIB_ATOMIC_WIN
-#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401)    \
-      && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \
-          defined(__i686__) || defined(__x86_64) || defined(__ia64)) \
-      && !defined(__INTEL_COMPILER)
-#  define TAGLIB_ATOMIC_GCC
-#elif defined(__ia64) && defined(__INTEL_COMPILER)
-#  include <ia64intrin.h>
-#  define TAGLIB_ATOMIC_GCC
+#ifdef _WIN32
+# if !defined(NOMINMAX)
+#   define NOMINMAX
+# endif
+# include <windows.h>
 #endif
 
 // Check the widths of integral types.
@@ -116,50 +104,6 @@ namespace TagLib {
    * so I'm providing something here that should be constant.
    */
   typedef std::basic_string<wchar> wstring;
-
-#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
-  /*!
-   * \internal
-   * This is just used as a base class for shared classes in TagLib.
-   *
-   * \warning This <b>is not</b> part of the TagLib public API!
-   */
-
-  class RefCounter
-  {
-  public:
-    RefCounter() : refCount(1) {}
-
-#ifdef TAGLIB_ATOMIC_MAC
-    void ref() { OSAtomicIncrement32Barrier(const_cast<int32_t*>(&refCount)); }
-    bool deref() { return ! OSAtomicDecrement32Barrier(const_cast<int32_t*>(&refCount)); }
-    int32_t count() { return refCount; }
-  private:
-    volatile int32_t refCount;
-#elif defined(TAGLIB_ATOMIC_WIN)
-    void ref() { InterlockedIncrement(&refCount); }
-    bool deref() { return ! InterlockedDecrement(&refCount); }
-    long count() { return refCount; }
-  private:
-    volatile long refCount;
-#elif defined(TAGLIB_ATOMIC_GCC)
-    void ref() { __sync_add_and_fetch(&refCount, 1); }
-    bool deref() { return ! __sync_sub_and_fetch(&refCount, 1); }
-    int count() { return refCount; }
-  private:
-    volatile int refCount;
-#else
-    void ref() { refCount++; }
-    bool deref() { return ! --refCount; }
-    int count() { return refCount; }
-  private:
-    uint refCount;
-#endif
-
-  };
-
-#endif // DO_NOT_DOCUMENT
-
 }
 
 /*!
index ca65cfaa8b2c1b7812565eff9ec4d10936021e69..aa76d6bff1b215a6471ec5baed589784a513127a 100644 (file)
@@ -236,7 +236,7 @@ ByteVector fromNumber(T value, bool mostSignificantByteFirst)
   return ByteVector(reinterpret_cast<const char *>(&value), size);
 }
 
-class DataPrivate : public RefCounter
+class DataPrivate
 {
 public:
   DataPrivate()
@@ -262,45 +262,39 @@ public:
   std::vector<char> data;
 };
 
-class ByteVector::ByteVectorPrivate : public RefCounter
+class ByteVector::ByteVectorPrivate 
 {
 public:
   ByteVectorPrivate() 
-    : RefCounter()
-    , data(new DataPrivate())
+    : data(new DataPrivate())
     , offset(0)
     , length(0) 
   {
   }
 
-  ByteVectorPrivate(ByteVectorPrivate *d, uint o, uint l)
-    : RefCounter()
-    , data(d->data)
+  ByteVectorPrivate(RefCountPtr<ByteVectorPrivate> d, uint o, uint l)
+    : data(d->data)
     , offset(d->offset + o)
     , length(l)
   {
-    data->ref();
   }
 
   ByteVectorPrivate(const std::vector<char> &v, uint o, uint l)
-    : RefCounter()
-    , data(new DataPrivate(v, o, l))
+    : data(new DataPrivate(v, o, l))
     , offset(0)
     , length(l)
   {
   }
 
   ByteVectorPrivate(uint l, char c) 
-    : RefCounter()
-    , data(new DataPrivate(l, c))
+    : data(new DataPrivate(l, c))
     , offset(0)
     , length(l)
   {
   }
 
   ByteVectorPrivate(const char *s, uint l) 
-    : RefCounter()
-    , data(new DataPrivate(s, s + l))
+    : data(new DataPrivate(s, s + l))
     , offset(0)
     , length(l)
   {
@@ -308,34 +302,25 @@ public:
   
   void detach()
   {
-    if(data->count() > 1) {
-      data->deref();
-      data = new DataPrivate(data->data, offset, length);
+    if(!data.unique()) {
+      data.reset(new DataPrivate(data->data, offset, length));
       offset = 0;
     }
   }
 
   ~ByteVectorPrivate()
   {
-    if(data->deref())
-      delete data;
   }
 
   ByteVectorPrivate &operator=(const ByteVectorPrivate &x)
   {
     if(&x != this)
-    {
-      if(data->deref())
-        delete data;
-
       data = x.data;
-      data->ref();
-    }
 
     return *this;
   }
 
-  DataPrivate *data;
+  RefCountPtr<DataPrivate> data;
   uint offset;
   uint length;
 };
@@ -386,13 +371,11 @@ ByteVector::ByteVector(uint size, char value)
 ByteVector::ByteVector(const ByteVector &v) 
   : d(v.d)
 {
-  d->ref();
 }
 
 ByteVector::ByteVector(const ByteVector &v, uint offset, uint length)
   : d(new ByteVectorPrivate(v.d, offset, length))
 {
-  d->ref();
 }
 
 ByteVector::ByteVector(char c)
@@ -412,8 +395,6 @@ ByteVector::ByteVector(const char *data)
 
 ByteVector::~ByteVector()
 {
-  if(d->deref())
-    delete d;
 }
 
 ByteVector &ByteVector::setData(const char *s, uint length)
@@ -563,10 +544,7 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
   }
 
   // replace private data:
-  if(d->deref())
-    delete d;
-
-  d = newData;
+  d.reset(newData);
 
   return *this;
 }
@@ -765,14 +743,7 @@ ByteVector ByteVector::operator+(const ByteVector &v) const
 
 ByteVector &ByteVector::operator=(const ByteVector &v)
 {
-  if(&v == this)
-    return *this;
-
-  if(d->deref())
-    delete d;
-
   d = v.d;
-  d->ref();
   return *this;
 }
 
@@ -808,16 +779,10 @@ ByteVector ByteVector::toHex() const
 
 void ByteVector::detach()
 {
-  if(d->data->count() > 1) {
-    d->data->deref();
-    d->data = new DataPrivate(d->data->data, d->offset, d->length);
-    d->offset = 0;
-  }
+  d->detach();
 
-  if(d->count() > 1) {
-    d->deref();
-    d = new ByteVectorPrivate(d->data->data, d->offset, d->length);
-  }
+  if(!d.unique())
+    d.reset(new ByteVectorPrivate(d->data->data, d->offset, d->length));
 }
 }
 
index ca810130f11244a46efe5d8ae9c7a2c9ce8245ef..cf7f66d5f0801f125da983b63da0e1fd96c6b0cc 100644 (file)
@@ -26,9 +26,9 @@
 #ifndef TAGLIB_BYTEVECTOR_H
 #define TAGLIB_BYTEVECTOR_H
 
-#include "taglib.h"
 #include "taglib_export.h"
-
+#include "taglib.h"
+#include "trefcountptr.h"
 #include <vector>
 #include <iostream>
 
@@ -446,7 +446,7 @@ namespace TagLib {
 
   private:
     class ByteVectorPrivate;
-    ByteVectorPrivate *d;
+    RefCountPtr<ByteVectorPrivate> d;
   };
 }
 
index 3e7de22aa5189b9419c81c79250101211d4129bc..ce1a0d0db3de44c6da90feaca1bd82c12d77c2b7 100644 (file)
@@ -38,8 +38,13 @@ namespace TagLib {
   public:
     FileName(const wchar_t *name) : m_wname(name) {}
     FileName(const char *name) : m_name(name) {}
+    
     operator const wchar_t *() const { return m_wname.c_str(); }
     operator const char *() const { return m_name.c_str(); }
+  
+    const std::wstring &wstr() const { return m_wname; }
+    const std::string  &str()  const { return m_name; }  
+  
   private:
     std::string m_name;
     std::wstring m_wname;
index 0099dad56d03584a996900b32f4f538703603661..535b374f1db722c7e1952381591a627fc1c6ac37 100644 (file)
@@ -27,7 +27,7 @@
 #define TAGLIB_LIST_H
 
 #include "taglib.h"
-
+#include "trefcountptr.h"
 #include <list>
 
 namespace TagLib {
@@ -243,7 +243,7 @@ namespace TagLib {
   private:
 #ifndef DO_NOT_DOCUMENT
     template <class TP> class ListPrivate;
-    ListPrivate<T> *d;
+    RefCountPtr<ListPrivate<T> > d;
 #endif
   };
 
index 37817f0592cf72ed3ba7f8627d43d99e397dea8e..17d68a5a35b0acad98d64de58fc31b517a30a388 100644 (file)
@@ -38,7 +38,7 @@ namespace TagLib {
 // A base for the generic and specialized private class types.  New
 // non-templatized members should be added here.
 
-class ListPrivateBase : public RefCounter
+class ListPrivateBase
 {
 public:
   ListPrivateBase() : autoDelete(false) {}
@@ -53,8 +53,9 @@ template <class TP> class List<T>::ListPrivate  : public ListPrivateBase
 public:
   ListPrivate() : ListPrivateBase() {}
   ListPrivate(const std::list<TP> &l) : ListPrivateBase(), list(l) {}
+
   void clear() {
-    list.clear();
+    std::list<TP>().swap(list);
   }
   std::list<TP> list;
 };
@@ -68,18 +69,27 @@ template <class TP> class List<T>::ListPrivate<TP *>  : public ListPrivateBase
 public:
   ListPrivate() : ListPrivateBase() {}
   ListPrivate(const std::list<TP *> &l) : ListPrivateBase(), list(l) {}
+
   ~ListPrivate() {
-    clear();
+    deletePointers();
   }
+
   void clear() {
-    if(autoDelete) {
-      typename std::list<TP *>::const_iterator it = list.begin();
-      for(; it != list.end(); ++it)
-        delete *it;
-    }
-    list.clear();
+    deletePointers();
+    std::list<TP *>().swap(list);
   }
+
   std::list<TP *> list;
+
+private:
+  void deletePointers() {
+    if(!autoDelete)
+      return;
+    
+    typename std::list<TP *>::const_iterator it = list.begin();
+    for(; it != list.end(); ++it)
+    delete *it;
+  }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -88,21 +98,19 @@ public:
 
 template <class T>
 List<T>::List()
+  : d(new ListPrivate<T>())
 {
-  d = new ListPrivate<T>;
 }
 
 template <class T>
-List<T>::List(const List<T> &l) : d(l.d)
+List<T>::List(const List<T> &l) 
+  : d(l.d)
 {
-  d->ref();
 }
 
 template <class T>
 List<T>::~List()
 {
-  if(d->deref())
-    delete d;
 }
 
 template <class T>
@@ -179,7 +187,7 @@ template <class T>
 List<T> &List<T>::prepend(const List<T> &l)
 {
   detach();
-  d->list.insert(d->list.begin(), l.begin(), l.end());
+  d->list.insert(d->list.begin(), l.d->list.begin(), l.d->list.end());
   return *this;
 }
 
@@ -192,7 +200,7 @@ List<T> &List<T>::clear()
 }
 
 template <class T>
-TagLib::uint List<T>::size() const
+uint List<T>::size() const
 {
   return d->list.size();
 }
@@ -284,13 +292,7 @@ const T &List<T>::operator[](uint i) const
 template <class T>
 List<T> &List<T>::operator=(const List<T> &l)
 {
-  if(&l == this)
-    return *this;
-
-  if(d->deref())
-    delete d;
   d = l.d;
-  d->ref();
   return *this;
 }
 
@@ -313,10 +315,8 @@ bool List<T>::operator!=(const List<T> &l) const
 template <class T>
 void List<T>::detach()
 {
-  if(d->count() > 1) {
-    d->deref();
-    d = new ListPrivate<T>(d->list);
-  }
+  if(!d.unique())
+    d.reset(new ListPrivate<T>(d->list));
 }
 
 } // namespace TagLib
index a7d99303572bac6fca801fa7f43d8d6653cfcf37..b5748e66c45f5101b5931b253437001bf89a8da1 100644 (file)
 #ifndef TAGLIB_MAP_H
 #define TAGLIB_MAP_H
 
+#include "taglib.h"
+#include "trefcountptr.h"
 #include <map>
 
-#include "taglib.h"
 
 namespace TagLib {
 
@@ -185,7 +186,7 @@ namespace TagLib {
   private:
 #ifndef DO_NOT_DOCUMENT
     template <class KeyP, class TP> class MapPrivate;
-    MapPrivate<Key, T> *d;
+    RefCountPtr<MapPrivate<Key, T> > d;
 #endif
   };
 
index 0f2b99332e55bc5a48b4a44753784965f10d66d4..783f99ccf353ea15084ee0e9070c49c761404e4f 100644 (file)
@@ -31,36 +31,49 @@ namespace TagLib {
 
 template <class Key, class T>
 template <class KeyP, class TP>
-class Map<Key, T>::MapPrivate : public RefCounter
+class Map<Key, T>::MapPrivate
 {
 public:
-  MapPrivate() : RefCounter() {}
+  MapPrivate() {}
+
 #ifdef WANT_CLASS_INSTANTIATION_OF_MAP
-  MapPrivate(const std::map<class KeyP, class TP>& m) : RefCounter(), map(m) {}
+
+  MapPrivate(const std::map<class KeyP, class TP> &m) : RefCounter(), map(m) {}
+
+  void clear() {
+    std::map<class KeyP, class TP>().swap(map);
+  }
+
   std::map<class KeyP, class TP> map;
+
 #else
-  MapPrivate(const std::map<KeyP, TP>& m) : RefCounter(), map(m) {}
+
+  MapPrivate(const std::map<KeyP, TP>& m) : map(m) {}
+
+  void clear() {
+    std::map<KeyP, TP>().swap(map);
+  }
+
   std::map<KeyP, TP> map;
+
 #endif
 };
 
 template <class Key, class T>
 Map<Key, T>::Map()
+  : d(new MapPrivate<Key, T>())
 {
-  d = new MapPrivate<Key, T>;
 }
 
 template <class Key, class T>
-Map<Key, T>::Map(const Map<Key, T> &m) : d(m.d)
+Map<Key, T>::Map(const Map<Key, T> &m) 
+  : d(m.d)
 {
-  d->ref();
 }
 
 template <class Key, class T>
 Map<Key, T>::~Map()
 {
-  if(d->deref())
-    delete(d);
 }
 
 template <class Key, class T>
@@ -149,7 +162,7 @@ Map<Key, T> &Map<Key,T>::erase(const Key &key)
 }
 
 template <class Key, class T>
-TagLib::uint Map<Key, T>::size() const
+uint Map<Key, T>::size() const
 {
   return d->map.size();
 }
@@ -170,13 +183,7 @@ T &Map<Key, T>::operator[](const Key &key)
 template <class Key, class T>
 Map<Key, T> &Map<Key, T>::operator=(const Map<Key, T> &m)
 {
-  if(&m == this)
-    return *this;
-
-  if(d->deref())
-    delete(d);
   d = m.d;
-  d->ref();
   return *this;
 }
 
@@ -187,10 +194,8 @@ Map<Key, T> &Map<Key, T>::operator=(const Map<Key, T> &m)
 template <class Key, class T>
 void Map<Key, T>::detach()
 {
-  if(d->count() > 1) {
-    d->deref();
-    d = new MapPrivate<Key, T>(d->map);
-  }
+  if(!d.unique())
+    d.reset(new MapPrivate<Key, T>(d->map));
 }
 
-} // namespace TagLib
+} // namespace TagLib
\ No newline at end of file
diff --git a/taglib/toolkit/trefcountptr.h b/taglib/toolkit/trefcountptr.h
new file mode 100644 (file)
index 0000000..49e0ee9
--- /dev/null
@@ -0,0 +1,240 @@
+/***************************************************************************
+    copyright            : (C) 2013 by Tsuda Kageyu
+    email                : tsuda.kageyu@gmail.com
+ ***************************************************************************/
+
+/***************************************************************************
+ *   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., 51 Franklin Street, Fifth Floor, Boston, MA         *
+ *   02110-1301  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 TAGLIB_REFCOUNTPTR_H
+#define TAGLIB_REFCOUNTPTR_H
+
+#include "tdebug.h"
+
+#ifdef __APPLE__
+#  include <libkern/OSAtomic.h>
+#  define TAGLIB_ATOMIC_MAC
+#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#  define TAGLIB_ATOMIC_WIN
+#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401)    \
+  && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \
+  defined(__i686__) || defined(__x86_64) || defined(__ia64)) \
+  && !defined(__INTEL_COMPILER)
+#  define TAGLIB_ATOMIC_GCC
+#elif defined(__ia64) && defined(__INTEL_COMPILER)
+#  include <ia64intrin.h>
+#  define TAGLIB_ATOMIC_GCC
+#endif
+
+#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
+
+/*!
+ * \internal
+ * This is just used as a smart pointer for shared classes in TagLib.
+ *
+ * \warning This <b>is not</b> part of the TagLib public API!
+ */
+
+namespace TagLib {
+
+  // RefCountPtr<T> mimics std::shared_ptr<T>.
+
+  template<typename T>
+  class RefCountPtr
+  {
+  private:
+
+    // Counter base class. Provides a reference counter.
+
+    class counter_base
+    {
+    public:
+      counter_base() 
+        : count(1) 
+      {
+      }
+
+      virtual ~counter_base()
+      {
+      }
+
+      void addref() 
+      { 
+        increment(&count); 
+      }
+
+      void release()
+      {
+        if(decrement(&count) == 0) {
+          dispose();
+          delete this;
+        }
+      }
+
+      long use_count() const
+      {
+        return static_cast<long>(count);
+      }
+
+      virtual void dispose() = 0;
+
+    private:
+# if defined(TAGLIB_ATOMIC_MAC)
+      typedef volatile int32_t counter_t;
+
+      inline static void increment(counter_t *c) { OSAtomicIncrement32Barrier(c); }
+      inline static counter_t decrement(counter_t *c) { return OSAtomicDecrement32Barrier(c); }
+
+# elif defined(TAGLIB_ATOMIC_WIN)
+      typedef volatile long counter_t;
+
+      inline static void increment(counter_t *c) { InterlockedIncrement(c); }
+      inline static counter_t decrement(counter_t *c) { return InterlockedDecrement(c); }
+
+# elif defined(TAGLIB_ATOMIC_GCC)
+      typedef volatile int counter_t;
+
+      inline static void increment(counter_t *c) { __sync_add_and_fetch(c, 1); }
+      inline static counter_t decrement(counter_t *c) { return __sync_sub_and_fetch(c, 1); }
+
+# else
+      typedef uint counter_t;
+
+      inline static void increment(counter_t *c) { ++(*c) }
+      inline static counter_t decrement(counter_t *c) { return --(*c); }
+
+# endif
+
+      counter_t count;
+    };
+
+    // Counter impl class. Provides a dynamic deleter.
+
+    template <typename U>
+    class counter_impl : public counter_base
+    {
+    public:
+      counter_impl(U *p)
+        : p(p)
+      {
+      }
+
+      virtual void dispose() 
+      { 
+        delete p; 
+      }
+
+      U *get() const
+      {
+        return p;
+      }
+
+    private:
+      U *p;
+    };
+
+  public:
+    template <typename U>
+    explicit RefCountPtr(U *p)
+      : counter(new counter_impl<U>(p))
+    {
+    }
+
+    RefCountPtr(const RefCountPtr &x)
+    {
+      counter = x.counter;
+      counter->addref();
+    }
+
+    ~RefCountPtr()
+    {
+      counter->release();
+    }
+
+    T *get() const
+    {
+      return static_cast<counter_impl<T>*>(counter)->get();
+    }
+
+    long use_count() const
+    {
+      return counter->use_count();
+    }
+
+    bool unique() const 
+    { 
+      return (use_count() == 1);
+    }
+
+    template <typename U>
+    void reset(U *p)
+    {
+      if(get() != p)
+      {
+        counter->release();
+        counter = new counter_impl<U>(p);
+      }
+    }
+
+    RefCountPtr<T> &operator=(const RefCountPtr<T> &x)
+    {
+      if(get() != x.get())
+      {
+        counter->release();
+
+        counter = x.counter;
+        counter->addref();
+      }
+      return *this;
+    }
+
+    T& operator*() const
+    {
+      return *get();
+    }
+
+    T* operator->() const
+    {
+      return get();
+    }
+
+    bool operator==(const RefCountPtr<T> &x) const 
+    {
+      return (get() == x.get());
+    }
+
+    bool operator!=(const RefCountPtr<T> &x) const
+    {
+      return !operator==(x);
+    }
+
+    operator bool() const
+    {
+      return (get() != 0);
+    }
+
+  private:
+    counter_base *counter;
+  };
+}
+
+#endif // DO_NOT_DOCUMENT
+
+#endif
index 219d3daf6ceb48fed46f8926bb818236b694072d..14abae2f3d0504f0ca8fc9885742e4fb03f0c856 100644 (file)
@@ -30,7 +30,6 @@
 #include "tstringlist.h"
 #include "tbyteswap.h"
 
-#include <iostream>
 #include <string.h>
 
 // Determine if the compiler supports codecvt.
@@ -56,23 +55,20 @@ namespace {
 
 namespace TagLib {
 
-class String::StringPrivate : public RefCounter
+class String::StringPrivate
 {
 public:
   StringPrivate() 
-    : RefCounter() 
   {
   }
 
   StringPrivate(const wstring &s) 
-    : RefCounter()
-    , data(s) 
+    : data(s) 
   {
   }
   
   StringPrivate(uint n, wchar_t c) 
-    : RefCounter()
-    , data(static_cast<size_t>(n), c) 
+    : data(static_cast<size_t>(n), c) 
   {
   }
 
@@ -99,7 +95,6 @@ String::String()
 String::String(const String &s) 
   : d(s.d)
 {
-  d->ref();
 }
 
 String::String(const std::string &s, Type t)
@@ -182,8 +177,6 @@ String::String(const ByteVector &v, Type t)
 
 String::~String()
 {
-  if(d->deref())
-    delete d;
 }
 
 std::string String::to8Bit(bool unicode) const
@@ -616,22 +609,13 @@ String &String::operator+=(char c)
 
 String &String::operator=(const String &s)
 {
-  if(&s == this)
-    return *this;
-
-  if(d->deref())
-    delete d;
   d = s.d;
-  d->ref();
   return *this;
 }
 
 String &String::operator=(const std::string &s)
 {
-  if(d->deref())
-    delete d;
-
-  d = new StringPrivate;
+  d.reset(new StringPrivate());
   copyFromLatin1(s.c_str(), s.length());
 
   return *this;
@@ -639,45 +623,33 @@ String &String::operator=(const std::string &s)
 
 String &String::operator=(const wstring &s)
 {
-  if(d->deref())
-    delete d;
-  d = new StringPrivate(s);
+  d.reset(new StringPrivate(s));
   return *this;
 }
 
 String &String::operator=(const wchar_t *s)
 {
-  if(d->deref())
-    delete d;
+  d.reset(new StringPrivate());
+  copyFromUTF16(s, ::wcslen(s), WCharByteOrder);
 
-  d = new StringPrivate(s);
   return *this;
 }
 
 String &String::operator=(char c)
 {
-  if(d->deref())
-    delete d;
-
-  d = new StringPrivate(1, static_cast<uchar>(c));
+  d.reset(new StringPrivate(1, static_cast<uchar>(c)));
   return *this;
 }
 
 String &String::operator=(wchar_t c)
 {
-  if(d->deref())
-    delete d;
-
-  d = new StringPrivate(1, static_cast<uchar>(c));
+  d.reset(new StringPrivate(1, static_cast<uchar>(c)));
   return *this;
 }
 
 String &String::operator=(const char *s)
 {
-  if(d->deref())
-    delete d;
-
-  d = new StringPrivate;
+  d.reset(new StringPrivate());
   copyFromLatin1(s, ::strlen(s));
 
   return *this;
@@ -685,10 +657,7 @@ String &String::operator=(const char *s)
 
 String &String::operator=(const ByteVector &v)
 {
-  if(d->deref())
-    delete d;
-
-  d = new StringPrivate;
+  d.reset(new StringPrivate());
   copyFromLatin1(v.data(), v.size());
 
   // If we hit a null in the ByteVector, shrink the string again.
@@ -708,10 +677,8 @@ bool String::operator<(const String &s) const
 
 void String::detach()
 {
-  if(d->count() > 1) {
-    d->deref();
-    d = new StringPrivate(d->data);
-  }
+  if(!d.unique())
+    d.reset(new StringPrivate(d->data));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index 150d7c37a61765003f38f470aea6e562cb921cbe..652c6ca74189c81fe8647223e15c5cbf59fe596c 100644 (file)
 #ifndef TAGLIB_STRING_H
 #define TAGLIB_STRING_H
 
-#include "taglib_export.h"
-#include "taglib.h"
 #include "tbytevector.h"
-
 #include <string>
-#include <iostream>
 
 /*!
  * \relates TagLib::String
@@ -485,7 +481,7 @@ namespace TagLib {
     static const Type WCharByteOrder;
 
     class StringPrivate;
-    StringPrivate *d;
+    RefCountPtr<StringPrivate> d;
   };
 }