diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index a940caf5..dab3430e 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -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} diff --git a/taglib/asf/asfattribute.cpp b/taglib/asf/asfattribute.cpp index 2cfada7b..4ba2689b 100644 --- a/taglib/asf/asfattribute.cpp +++ b/taglib/asf/asfattribute.cpp @@ -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; } diff --git a/taglib/asf/asfattribute.h b/taglib/asf/asfattribute.h index 54eb0c7d..ca26aec3 100644 --- a/taglib/asf/asfattribute.h +++ b/taglib/asf/asfattribute.h @@ -194,7 +194,7 @@ namespace TagLib ByteVector render(const String &name, int kind = 0) const; class AttributePrivate; - AttributePrivate *d; + RefCountPtr d; }; } diff --git a/taglib/asf/asfpicture.cpp b/taglib/asf/asfpicture.cpp index c36ffa3a..82a38b6b 100644 --- a/taglib/asf/asfpicture.cpp +++ b/taglib/asf/asfpicture.cpp @@ -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; } diff --git a/taglib/asf/asfpicture.h b/taglib/asf/asfpicture.h index aa0a060c..aa838974 100644 --- a/taglib/asf/asfpicture.h +++ b/taglib/asf/asfpicture.h @@ -207,10 +207,10 @@ namespace TagLib static Picture fromInvalid(); friend class Attribute; #endif - private: - class PicturePrivate; - PicturePrivate *d; - }; + private: + class PicturePrivate; + RefCountPtr d; + }; } } diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index 859f3155..8e747fa8 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -31,6 +31,10 @@ #include #endif +#ifdef _WIN32 +# include +#endif + #include #include #include @@ -57,15 +61,12 @@ 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; static List fileTypeResolvers; }; @@ -76,30 +77,28 @@ List 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() +{ +} diff --git a/taglib/fileref.h b/taglib/fileref.h index 0f0c21a4..42cec8b4 100644 --- a/taglib/fileref.h +++ b/taglib/fileref.h @@ -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 d; }; } // namespace TagLib diff --git a/taglib/mp4/mp4coverart.cpp b/taglib/mp4/mp4coverart.cpp index 928e3c4a..5b6e6e23 100644 --- a/taglib/mp4/mp4coverart.cpp +++ b/taglib/mp4/mp4coverart.cpp @@ -33,43 +33,35 @@ 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 diff --git a/taglib/mp4/mp4coverart.h b/taglib/mp4/mp4coverart.h index 64115b45..b6b44c49 100644 --- a/taglib/mp4/mp4coverart.h +++ b/taglib/mp4/mp4coverart.h @@ -63,7 +63,7 @@ namespace TagLib { private: class CoverArtPrivate; - CoverArtPrivate *d; + RefCountPtr d; }; typedef List CoverArtList; diff --git a/taglib/mp4/mp4item.cpp b/taglib/mp4/mp4item.cpp index af2cc65c..6a303652 100644 --- a/taglib/mp4/mp4item.cpp +++ b/taglib/mp4/mp4item.cpp @@ -33,10 +33,10 @@ 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; } diff --git a/taglib/mp4/mp4item.h b/taglib/mp4/mp4item.h index be7aa1a1..3b4e23cd 100644 --- a/taglib/mp4/mp4item.h +++ b/taglib/mp4/mp4item.h @@ -73,7 +73,7 @@ namespace TagLib { private: class ItemPrivate; - ItemPrivate *d; + RefCountPtr d; }; } diff --git a/taglib/mpeg/mpegheader.cpp b/taglib/mpeg/mpegheader.cpp index c715dbc1..bc98f4c9 100644 --- a/taglib/mpeg/mpegheader.cpp +++ b/taglib/mpeg/mpegheader.cpp @@ -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; } diff --git a/taglib/mpeg/mpegheader.h b/taglib/mpeg/mpegheader.h index 020ebd06..7a352ed7 100644 --- a/taglib/mpeg/mpegheader.h +++ b/taglib/mpeg/mpegheader.h @@ -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 d; }; } } diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index dd4ee69d..03d16724 100755 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -45,23 +45,11 @@ #include #include -#ifdef __APPLE__ -# include -# define TAGLIB_ATOMIC_MAC -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if !defined(NOMINMAX) -# define NOMINMAX -# endif -# include -# 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 -# define TAGLIB_ATOMIC_GCC +#ifdef _WIN32 +# if !defined(NOMINMAX) +# define NOMINMAX +# endif +# include #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 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 is not part of the TagLib public API! - */ - - class RefCounter - { - public: - RefCounter() : refCount(1) {} - -#ifdef TAGLIB_ATOMIC_MAC - void ref() { OSAtomicIncrement32Barrier(const_cast(&refCount)); } - bool deref() { return ! OSAtomicDecrement32Barrier(const_cast(&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 - } /*! diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index ca65cfaa..aa76d6bf 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -236,7 +236,7 @@ ByteVector fromNumber(T value, bool mostSignificantByteFirst) return ByteVector(reinterpret_cast(&value), size); } -class DataPrivate : public RefCounter +class DataPrivate { public: DataPrivate() @@ -262,45 +262,39 @@ public: std::vector 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 d, uint o, uint l) + : data(d->data) , offset(d->offset + o) , length(l) { - data->ref(); } ByteVectorPrivate(const std::vector &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 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)); } } diff --git a/taglib/toolkit/tbytevector.h b/taglib/toolkit/tbytevector.h index ca810130..cf7f66d5 100644 --- a/taglib/toolkit/tbytevector.h +++ b/taglib/toolkit/tbytevector.h @@ -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 #include @@ -446,7 +446,7 @@ namespace TagLib { private: class ByteVectorPrivate; - ByteVectorPrivate *d; + RefCountPtr d; }; } diff --git a/taglib/toolkit/tiostream.h b/taglib/toolkit/tiostream.h index 3e7de22a..ce1a0d0d 100644 --- a/taglib/toolkit/tiostream.h +++ b/taglib/toolkit/tiostream.h @@ -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; diff --git a/taglib/toolkit/tlist.h b/taglib/toolkit/tlist.h index 0099dad5..535b374f 100644 --- a/taglib/toolkit/tlist.h +++ b/taglib/toolkit/tlist.h @@ -27,7 +27,7 @@ #define TAGLIB_LIST_H #include "taglib.h" - +#include "trefcountptr.h" #include namespace TagLib { @@ -243,7 +243,7 @@ namespace TagLib { private: #ifndef DO_NOT_DOCUMENT template class ListPrivate; - ListPrivate *d; + RefCountPtr > d; #endif }; diff --git a/taglib/toolkit/tlist.tcc b/taglib/toolkit/tlist.tcc index 37817f05..17d68a5a 100644 --- a/taglib/toolkit/tlist.tcc +++ b/taglib/toolkit/tlist.tcc @@ -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 List::ListPrivate : public ListPrivateBase public: ListPrivate() : ListPrivateBase() {} ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + void clear() { - list.clear(); + std::list().swap(list); } std::list list; }; @@ -68,18 +69,27 @@ template class List::ListPrivate : public ListPrivateBase public: ListPrivate() : ListPrivateBase() {} ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + ~ListPrivate() { - clear(); + deletePointers(); } + void clear() { - if(autoDelete) { - typename std::list::const_iterator it = list.begin(); - for(; it != list.end(); ++it) - delete *it; - } - list.clear(); + deletePointers(); + std::list().swap(list); } + std::list list; + +private: + void deletePointers() { + if(!autoDelete) + return; + + typename std::list::const_iterator it = list.begin(); + for(; it != list.end(); ++it) + delete *it; + } }; //////////////////////////////////////////////////////////////////////////////// @@ -88,21 +98,19 @@ public: template List::List() + : d(new ListPrivate()) { - d = new ListPrivate; } template -List::List(const List &l) : d(l.d) +List::List(const List &l) + : d(l.d) { - d->ref(); } template List::~List() { - if(d->deref()) - delete d; } template @@ -179,7 +187,7 @@ template List &List::prepend(const List &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 &List::clear() } template -TagLib::uint List::size() const +uint List::size() const { return d->list.size(); } @@ -284,13 +292,7 @@ const T &List::operator[](uint i) const template List &List::operator=(const List &l) { - if(&l == this) - return *this; - - if(d->deref()) - delete d; d = l.d; - d->ref(); return *this; } @@ -313,10 +315,8 @@ bool List::operator!=(const List &l) const template void List::detach() { - if(d->count() > 1) { - d->deref(); - d = new ListPrivate(d->list); - } + if(!d.unique()) + d.reset(new ListPrivate(d->list)); } } // namespace TagLib diff --git a/taglib/toolkit/tmap.h b/taglib/toolkit/tmap.h index a7d99303..b5748e66 100644 --- a/taglib/toolkit/tmap.h +++ b/taglib/toolkit/tmap.h @@ -26,9 +26,10 @@ #ifndef TAGLIB_MAP_H #define TAGLIB_MAP_H +#include "taglib.h" +#include "trefcountptr.h" #include -#include "taglib.h" namespace TagLib { @@ -185,7 +186,7 @@ namespace TagLib { private: #ifndef DO_NOT_DOCUMENT template class MapPrivate; - MapPrivate *d; + RefCountPtr > d; #endif }; diff --git a/taglib/toolkit/tmap.tcc b/taglib/toolkit/tmap.tcc index 0f2b9933..783f99cc 100644 --- a/taglib/toolkit/tmap.tcc +++ b/taglib/toolkit/tmap.tcc @@ -31,36 +31,49 @@ namespace TagLib { template template -class Map::MapPrivate : public RefCounter +class Map::MapPrivate { public: - MapPrivate() : RefCounter() {} + MapPrivate() {} + #ifdef WANT_CLASS_INSTANTIATION_OF_MAP - MapPrivate(const std::map& m) : RefCounter(), map(m) {} + + MapPrivate(const std::map &m) : RefCounter(), map(m) {} + + void clear() { + std::map().swap(map); + } + std::map map; + #else - MapPrivate(const std::map& m) : RefCounter(), map(m) {} + + MapPrivate(const std::map& m) : map(m) {} + + void clear() { + std::map().swap(map); + } + std::map map; + #endif }; template Map::Map() + : d(new MapPrivate()) { - d = new MapPrivate; } template -Map::Map(const Map &m) : d(m.d) +Map::Map(const Map &m) + : d(m.d) { - d->ref(); } template Map::~Map() { - if(d->deref()) - delete(d); } template @@ -149,7 +162,7 @@ Map &Map::erase(const Key &key) } template -TagLib::uint Map::size() const +uint Map::size() const { return d->map.size(); } @@ -170,13 +183,7 @@ T &Map::operator[](const Key &key) template Map &Map::operator=(const Map &m) { - if(&m == this) - return *this; - - if(d->deref()) - delete(d); d = m.d; - d->ref(); return *this; } @@ -187,10 +194,8 @@ Map &Map::operator=(const Map &m) template void Map::detach() { - if(d->count() > 1) { - d->deref(); - d = new MapPrivate(d->map); - } + if(!d.unique()) + d.reset(new MapPrivate(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 index 00000000..49e0ee9e --- /dev/null +++ b/taglib/toolkit/trefcountptr.h @@ -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 +# 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 +# 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 is not part of the TagLib public API! + */ + +namespace TagLib { + + // RefCountPtr mimics std::shared_ptr. + + template + 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(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 + 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 + explicit RefCountPtr(U *p) + : counter(new counter_impl(p)) + { + } + + RefCountPtr(const RefCountPtr &x) + { + counter = x.counter; + counter->addref(); + } + + ~RefCountPtr() + { + counter->release(); + } + + T *get() const + { + return static_cast*>(counter)->get(); + } + + long use_count() const + { + return counter->use_count(); + } + + bool unique() const + { + return (use_count() == 1); + } + + template + void reset(U *p) + { + if(get() != p) + { + counter->release(); + counter = new counter_impl(p); + } + } + + RefCountPtr &operator=(const RefCountPtr &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 &x) const + { + return (get() == x.get()); + } + + bool operator!=(const RefCountPtr &x) const + { + return !operator==(x); + } + + operator bool() const + { + return (get() != 0); + } + + private: + counter_base *counter; + }; +} + +#endif // DO_NOT_DOCUMENT + +#endif diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 219d3daf..14abae2f 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -30,7 +30,6 @@ #include "tstringlist.h" #include "tbyteswap.h" -#include #include // 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(n), c) + : data(static_cast(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(c)); + d.reset(new StringPrivate(1, static_cast(c))); return *this; } String &String::operator=(wchar_t c) { - if(d->deref()) - delete d; - - d = new StringPrivate(1, static_cast(c)); + d.reset(new StringPrivate(1, static_cast(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)); } //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index 150d7c37..652c6ca7 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -26,12 +26,8 @@ #ifndef TAGLIB_STRING_H #define TAGLIB_STRING_H -#include "taglib_export.h" -#include "taglib.h" #include "tbytevector.h" - #include -#include /*! * \relates TagLib::String @@ -485,7 +481,7 @@ namespace TagLib { static const Type WCharByteOrder; class StringPrivate; - StringPrivate *d; + RefCountPtr d; }; }