Merge pull request #140 from TsudaKageyu/smart-ptr

Replace RefCounter with a smart pointer
This commit is contained in:
Tsuda Kageyu 2013-04-16 15:29:10 -07:00
commit 1390860929
26 changed files with 318 additions and 696 deletions

View File

@ -52,6 +52,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

View File

@ -34,7 +34,7 @@
using namespace TagLib;
class ASF::Attribute::AttributePrivate : public RefCounter
class ASF::Attribute::AttributePrivate
{
public:
AttributePrivate()
@ -68,11 +68,6 @@ ASF::Attribute::Attribute()
ASF::Attribute::Attribute(const ASF::Attribute &other)
: d(other.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
ASF::Attribute::Attribute(const String &value)
@ -126,29 +121,11 @@ ASF::Attribute::Attribute(bool value)
ASF::Attribute::~Attribute()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
{
#ifdef TAGLIB_USE_CXX11
d = other.d;
#else
if(d->deref())
delete d;
d = other.d;
d->ref();
#endif
return *this;
}

View File

@ -205,12 +205,7 @@ namespace TagLib
ByteVector render(const String &name, int kind = 0) const;
class AttributePrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<AttributePrivate> d;
#else
AttributePrivate *d;
#endif
RefCountPtr<AttributePrivate> d;
};
}

View File

@ -35,7 +35,7 @@
using namespace TagLib;
class ASF::Picture::PicturePrivate : public RefCounter
class ASF::Picture::PicturePrivate
{
public:
bool valid;
@ -58,11 +58,6 @@ ASF::Picture::Picture()
ASF::Picture::Picture(const Picture& other)
: d(other.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -76,12 +71,6 @@ ASF::Picture::Picture(Picture &&other)
ASF::Picture::~Picture()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
bool ASF::Picture::isValid() const
@ -138,21 +127,7 @@ int ASF::Picture::dataSize() const
ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other)
{
#ifdef TAGLIB_USE_CXX11
d = other.d;
#else
if(other.d != d) {
if(d->deref())
delete d;
d = other.d;
d->ref();
}
#endif
return *this;
}

View File

@ -231,12 +231,7 @@ namespace TagLib
#endif
private:
class PicturePrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<PicturePrivate> d;
#else
PicturePrivate *d;
#endif
RefCountPtr<PicturePrivate> d;
};
}
}

View File

@ -61,26 +61,12 @@
using namespace TagLib;
class FileRef::FileRefPrivate : public RefCounter
class FileRef::FileRefPrivate
{
public:
FileRefPrivate(File *f)
: RefCounter(), file(f) {}
FileRefPrivate(File *f) : file(f) {}
~FileRefPrivate()
{
#ifndef TAGLIB_USE_CXX11
delete file;
#endif
}
#ifdef TAGLIB_USE_CXX11
std::unique_ptr<File> file;
#else
File *file;
#endif
RefCountPtr<File> file;
static List<const FileTypeResolver *> fileTypeResolvers;
};
@ -110,11 +96,6 @@ FileRef::FileRef(File *file)
FileRef::FileRef(const FileRef &ref)
: d(ref.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -128,12 +109,6 @@ FileRef::FileRef(FileRef &&ref)
FileRef::~FileRef()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
Tag *FileRef::tag() const
@ -156,15 +131,7 @@ AudioProperties *FileRef::audioProperties() const
File *FileRef::file() const
{
#ifdef TAGLIB_USE_CXX11
return d->file.get();
#else
return d->file;
#endif
}
bool FileRef::save()
@ -224,23 +191,7 @@ bool FileRef::isNull() const
FileRef &FileRef::operator=(const FileRef &ref)
{
#ifdef TAGLIB_USE_CXX11
d = ref.d;
#else
if(&ref == this)
return *this;
if(d->deref())
delete d;
d = ref.d;
d->ref();
#endif
return *this;
}

View File

@ -278,12 +278,7 @@ namespace TagLib {
private:
class FileRefPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<FileRefPrivate> d;
#else
FileRefPrivate *d;
#endif
RefCountPtr<FileRefPrivate> d;
};
} // namespace TagLib

View File

@ -33,10 +33,10 @@
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;
@ -51,30 +51,12 @@ MP4::CoverArt::CoverArt(Format format, const ByteVector &data)
MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
MP4::CoverArt &
MP4::CoverArt::operator=(const CoverArt &item)
{
#ifdef TAGLIB_USE_CXX11
d = item.d;
#else
if(d->deref()) {
delete d;
}
d = item.d;
d->ref();
#endif
return *this;
}
@ -91,13 +73,6 @@ MP4::CoverArt &
MP4::CoverArt::~CoverArt()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref()) {
delete d;
}
#endif
}
MP4::CoverArt::Format

View File

@ -66,12 +66,7 @@ namespace TagLib {
private:
class CoverArtPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<CoverArtPrivate> d;
#else
CoverArtPrivate *d;
#endif
RefCountPtr<CoverArtPrivate> d;
};
typedef List<CoverArt> CoverArtList;

View File

@ -40,10 +40,10 @@
using namespace TagLib;
class MP4::Item::ItemPrivate : public RefCounter
class MP4::Item::ItemPrivate
{
public:
ItemPrivate() : RefCounter(), valid(true), atomDataType(MP4::TypeUndefined), type(MP4::Item::TypeUndefined) {}
ItemPrivate() : valid(true), atomDataType(MP4::TypeUndefined), type(MP4::Item::TypeUndefined) {}
bool valid;
AtomDataType atomDataType;
@ -70,11 +70,6 @@ MP4::Item::Item()
MP4::Item::Item(const Item &item)
: d(item.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -89,20 +84,7 @@ MP4::Item::Item(Item &&item)
MP4::Item &
MP4::Item::operator=(const Item &item)
{
#ifdef TAGLIB_USE_CXX11
d = item.d;
#else
if(d->deref()) {
delete d;
}
d = item.d;
d->ref();
#endif
return *this;
}
@ -119,13 +101,6 @@ MP4::Item &
MP4::Item::~Item()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref()) {
delete d;
}
#endif
}
MP4::Item::Item(bool value)

View File

@ -97,12 +97,7 @@ namespace TagLib {
private:
class ItemPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<ItemPrivate> d;
#else
ItemPrivate *d;
#endif
RefCountPtr<ItemPrivate> d;
};
}

View File

@ -33,7 +33,7 @@
using namespace TagLib;
class MPEG::Header::HeaderPrivate : public RefCounter
class MPEG::Header::HeaderPrivate
{
public:
HeaderPrivate() :
@ -76,11 +76,6 @@ MPEG::Header::Header(const ByteVector &data)
MPEG::Header::Header(const Header &h)
: d(h.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -94,12 +89,6 @@ MPEG::Header::Header(Header &&h)
MPEG::Header::~Header()
{
#ifndef TAGLIB_USE_CXX11
if (d->deref())
delete d;
#endif
}
bool MPEG::Header::isValid() const
@ -164,23 +153,7 @@ int MPEG::Header::samplesPerFrame() const
MPEG::Header &MPEG::Header::operator=(const Header &h)
{
#ifdef TAGLIB_USE_CXX11
d = h.d;
#else
if(&h == this)
return *this;
if(d->deref())
delete d;
d = h.d;
d->ref();
#endif
return *this;
}

View File

@ -27,6 +27,7 @@
#define TAGLIB_MPEGHEADER_H
#include "taglib_export.h"
#include "trefcountptr.h"
namespace TagLib {
@ -180,12 +181,7 @@ namespace TagLib {
void parse(const ByteVector &data);
class HeaderPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<HeaderPrivate> d;
#else
HeaderPrivate *d;
#endif
RefCountPtr<HeaderPrivate> d;
};
}
}

View File

@ -53,30 +53,6 @@
#endif
// TAGLIB_USE_CXX11 determines whether or not to enable C++11 features.
// Replaces RefCounter capability with std::shared_ptr<T> if available.
#ifdef TAGLIB_USE_CXX11
# include <memory>
#endif
#ifndef TAGLIB_USE_CXX11
# 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
#endif
// Check the widths of integral types.
#if UCHAR_MAX != 255U
@ -161,57 +137,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
{
// RefCounter is a mere dummy if std::shared_ptr<T> is available.
#ifndef TAGLIB_USE_CXX11
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
public:
virtual ~RefCounter() {}
};
#endif // DO_NOT_DOCUMENT
}
/*!

View File

@ -28,16 +28,6 @@
#include <tdebug.h>
#include <string.h>
#if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(_M_IX86) || defined(_M_X64))
# define TAGLIB_MSC_BYTESWAP
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
# define TAGLIB_GCC_BYTESWAP
#endif
#ifdef TAGLIB_GCC_BYTESWAP
# include <byteswap.h>
#endif
#include "tbytevector.h"
#include "tbyteswap.h"
@ -246,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()
@ -258,6 +248,12 @@ public:
{
}
// A char* can be an iterator.
DataPrivate(const char *begin, const char *end)
: data(begin, end)
{
}
DataPrivate(size_t l, char c)
: data(l, c)
{
@ -266,124 +262,65 @@ 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)
{
}
#ifdef TAGLIB_USE_CXX11
ByteVectorPrivate(std::shared_ptr<ByteVectorPrivate> d, size_t o, size_t l)
: RefCounter()
, data(d->data)
ByteVectorPrivate(RefCountPtr<ByteVectorPrivate> d, size_t o, size_t l)
: data(d->data)
, offset(d->offset + o)
, length(l)
{
}
#else
ByteVectorPrivate(ByteVectorPrivate *d, size_t o, size_t l)
: RefCounter()
, data(d->data)
, offset(d->offset + o)
, length(l)
{
data->ref();
}
#endif
ByteVectorPrivate(const std::vector<char> &v, size_t o, size_t l)
: RefCounter()
, data(new DataPrivate(v, o, l))
: data(new DataPrivate(v, o, l))
, offset(0)
, length(l)
{
}
ByteVectorPrivate(size_t l, char c)
: RefCounter()
, data(new DataPrivate(l, c))
: data(new DataPrivate(l, c))
, offset(0)
, length(l)
{
}
ByteVectorPrivate(const char *s, size_t l)
: RefCounter()
, data(new DataPrivate())
: data(new DataPrivate(s, s + l))
, offset(0)
, length(l)
{
data->data.resize(length);
memcpy(DATA(this), s, l);
}
void detach()
{
#ifdef TAGLIB_USE_CXX11
if(!data.unique()) {
data.reset(new DataPrivate(data->data, offset, length));
offset = 0;
}
#else
if(data->count() > 1) {
data->deref();
data = new DataPrivate(data->data, offset, length);
offset = 0;
}
#endif
}
~ByteVectorPrivate()
{
#ifndef TAGLIB_USE_CXX11
if(data->deref())
delete data;
#endif
}
ByteVectorPrivate &operator=(const ByteVectorPrivate &x)
{
if(&x != this)
{
#ifdef TAGLIB_USE_CXX11
data = x.data;
#else
if(data->deref())
delete data;
data = x.data;
data->ref();
#endif
}
return *this;
}
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<DataPrivate> data;
#else
DataPrivate *data;
#endif
RefCountPtr<DataPrivate> data;
size_t offset;
size_t length;
};
@ -436,11 +373,6 @@ ByteVector::ByteVector(size_t size, char value)
ByteVector::ByteVector(const ByteVector &v)
: d(v.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
ByteVector::ByteVector(const ByteVector &v, size_t offset, size_t length)
@ -474,12 +406,6 @@ ByteVector::ByteVector(const char *data)
ByteVector::~ByteVector()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
ByteVector &ByteVector::setData(const char *data, size_t length)
@ -630,19 +556,8 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
}
// replace private data:
#ifdef TAGLIB_USE_CXX11
d.reset(newData);
#else
if(d->deref())
delete d;
d = newData;
#endif
return *this;
}
@ -842,23 +757,8 @@ ByteVector ByteVector::operator+(const ByteVector &v) const
ByteVector &ByteVector::operator=(const ByteVector &v)
{
#ifdef TAGLIB_USE_CXX11
d = v.d;
#else
if(&v == this)
return *this;
if(d->deref())
delete d;
d = v.d;
d->ref();
#endif
return *this;
}
@ -874,31 +774,13 @@ ByteVector &ByteVector::operator=(ByteVector &&v)
ByteVector &ByteVector::operator=(char c)
{
#ifdef TAGLIB_USE_CXX11
d = ByteVector(c).d;
#else
*this = ByteVector(c);
#endif
return *this;
}
ByteVector &ByteVector::operator=(const char *data)
{
#ifdef TAGLIB_USE_CXX11
d = ByteVector(data).d;
#else
*this = ByteVector(data);
#endif
return *this;
}
@ -924,19 +806,8 @@ void ByteVector::detach()
{
d->detach();
#ifdef TAGLIB_USE_CXX11
if(!d.unique())
d.reset(new ByteVectorPrivate(d->data->data, d->offset, d->length));
#else
if(d->count() > 1) {
d->deref();
d = new ByteVectorPrivate(d->data->data, d->offset, d->length);
}
#endif
}
////////////////////////////////////////////////////////////////////////////////

View 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>
@ -478,12 +478,7 @@ namespace TagLib {
private:
class ByteVectorPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<ByteVectorPrivate> d;
#else
ByteVectorPrivate *d;
#endif
RefCountPtr<ByteVectorPrivate> d;
};
/*!

View File

@ -26,10 +26,8 @@
#ifndef TAGLIB_FILE_H
#define TAGLIB_FILE_H
#include "taglib_export.h"
#include "taglib.h"
#include "tag.h"
#include "tbytevector.h"
#include "tag.h"
#include "tiostream.h"
namespace TagLib {

View File

@ -26,8 +26,6 @@
#ifndef TAGLIB_FILESTREAM_H
#define TAGLIB_FILESTREAM_H
#include "taglib_export.h"
#include "taglib.h"
#include "tbytevector.h"
#include "tiostream.h"

View File

@ -26,8 +26,6 @@
#ifndef TAGLIB_IOSTREAM_H
#define TAGLIB_IOSTREAM_H
#include "taglib_export.h"
#include "taglib.h"
#include "tbytevector.h"
#ifdef _WIN32

View File

@ -27,7 +27,7 @@
#define TAGLIB_LIST_H
#include "taglib.h"
#include "trefcountptr.h"
#include <list>
namespace TagLib {
@ -305,12 +305,7 @@ namespace TagLib {
private:
#ifndef DO_NOT_DOCUMENT
template <class TP> class ListPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<ListPrivate<T>> d;
#else
ListPrivate<T> *d;
#endif
RefCountPtr<ListPrivate<T> > d;
#endif
};

View 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) {}
@ -118,11 +118,6 @@ template <class T>
List<T>::List(const List<T> &l)
: d(l.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -138,12 +133,6 @@ List<T>::List(List<T> &&l)
template <class T>
List<T>::~List()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
template <class T>
@ -371,21 +360,7 @@ const T &List<T>::operator[](size_t i) const
template <class T>
List<T> &List<T>::operator=(const List<T> &l)
{
#ifdef TAGLIB_USE_CXX11
d = l.d;
#else
if(&l == this)
return *this;
if(d->deref())
delete d;
d = l.d;
d->ref();
#endif
return *this;
}
@ -419,19 +394,8 @@ bool List<T>::operator!=(const List<T> &l) const
template <class T>
void List<T>::detach()
{
#ifdef TAGLIB_USE_CXX11
if(!d.unique())
d.reset(new ListPrivate<T>(d->list));
#else
if(d->count() > 1) {
d->deref();
d = new ListPrivate<T>(d->list);
}
#endif
}
} // namespace TagLib

View File

@ -26,9 +26,9 @@
#ifndef TAGLIB_MAP_H
#define TAGLIB_MAP_H
#include <map>
#include "taglib.h"
#include "trefcountptr.h"
#include <map>
namespace TagLib {
@ -219,12 +219,7 @@ namespace TagLib {
private:
#ifndef DO_NOT_DOCUMENT
template <class KeyP, class TP> class MapPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<MapPrivate<Key, T>> d;
#else
MapPrivate<Key, T> *d;
#endif
RefCountPtr<MapPrivate<Key, T> > d;
#endif
};

View File

@ -31,10 +31,10 @@ 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
@ -54,11 +54,11 @@ public:
#else
MapPrivate(const std::map<KeyP, TP>& m) : RefCounter(), map(m) {}
MapPrivate(const std::map<KeyP, TP>& m) : map(m) {}
# ifdef TAGLIB_USE_CXX11
MapPrivate(std::map<KeyP, TP> &&m) : RefCounter(), map(m) {}
MapPrivate(std::map<KeyP, TP> &&m) : map(m) {}
# endif
@ -81,11 +81,6 @@ template <class Key, class T>
Map<Key, T>::Map(const Map<Key, T> &m)
: d(m.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -101,12 +96,6 @@ TagLib::Map<Key, T>::Map(Map<Key, T> &&m)
template <class Key, class T>
Map<Key, T>::~Map()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete(d);
#endif
}
template <class Key, class T>
@ -228,22 +217,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)
{
#ifdef TAGLIB_USE_CXX11
d = m.d;
#else
if(&m == this)
return *this;
if(d->deref())
delete(d);
d = m.d;
d->ref();
#endif
return *this;
}
@ -265,19 +239,8 @@ Map<Key, T> &Map<Key, T>::operator=(Map<Key, T> &&m)
template <class Key, class T>
void Map<Key, T>::detach()
{
#ifdef TAGLIB_USE_CXX11
if(!d.unique())
d.reset(new MapPrivate<Key, T>(d->map));
#else
if(d->count() > 1) {
d->deref();
d = new MapPrivate<Key, T>(d->map);
}
#endif
}
} // namespace TagLib

View File

@ -0,0 +1,257 @@
/***************************************************************************
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
// TAGLIB_USE_CXX11 determines whether or not to enable C++11 features.
#include "tdebug.h"
#ifdef TAGLIB_USE_CXX11
# include <memory>
#else
# 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
#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!
*/
#ifdef TAGLIB_USE_CXX11
// RefCountPtr<T> is just an alias of std::shared_ptr<T> if C++11 is available.
# define RefCountPtr std::shared_ptr
// Workaround for the fact that some compilers don't support the template aliases.
#else
namespace TagLib {
// RefCountPtr<T> mimics std::shared_ptr<T> if C++11 is not available.
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 // TAGLIB_USE_CXX11
#endif // DO_NOT_DOCUMENT
#endif

View File

@ -46,10 +46,6 @@
# include "unicode.h"
#endif
#if defined(__GNUC__)
# include <byteswap.h>
#endif
namespace {
inline unsigned short combine(unsigned char c1, unsigned char c2)
@ -60,25 +56,24 @@ namespace {
namespace TagLib {
class String::StringPrivate : public RefCounter
class String::StringPrivate
{
public:
StringPrivate()
{
}
StringPrivate(const wstring &s)
: data(s)
{
}
#ifdef TAGLIB_USE_CXX11
StringPrivate() {}
StringPrivate(const wstring &s) : data(s) {}
StringPrivate(wstring &&s) : data(s) {}
#else
public:
StringPrivate(const wstring &s) :
RefCounter(),
data(s) {}
StringPrivate() :
RefCounter() {}
StringPrivate(wstring &&s)
: data(s)
{
}
#endif
@ -108,11 +103,6 @@ String::String()
String::String(const String &s)
: d(s.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
@ -208,12 +198,6 @@ String::String(const ByteVector &v, Type t)
String::~String()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
std::string String::to8Bit(bool unicode) const
@ -660,22 +644,7 @@ String &String::operator+=(char c)
String &String::operator=(const String &s)
{
#ifdef TAGLIB_USE_CXX11
d = s.d;
#else
if(&s == this)
return *this;
if(d->deref())
delete d;
d = s.d;
d->ref();
#endif
return *this;
}
@ -691,19 +660,7 @@ String &String::operator=(String &&s)
String &String::operator=(const std::string &s)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate());
#else
if(d->deref())
delete d;
d = new StringPrivate;
#endif
copyFromLatin1(s.c_str(), s.length());
return *this;
@ -711,19 +668,7 @@ String &String::operator=(const std::string &s)
String &String::operator=(const wstring &s)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate(s));
#else
if(d->deref())
delete d;
d = new StringPrivate(s);
#endif
return *this;
}
@ -739,19 +684,7 @@ String &String::operator=(wstring &&s)
String &String::operator=(const wchar_t *s)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate());
#else
if(d->deref())
delete d;
d = new StringPrivate;
#endif
copyFromUTF16(s, ::wcslen(s), WCharByteOrder);
return *this;
@ -759,19 +692,7 @@ String &String::operator=(const wchar_t *s)
String &String::operator=(char c)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate());
#else
if(d->deref())
delete d;
d = new StringPrivate;
#endif
d->data.resize(1);
d->data[0] = static_cast<uchar>(c);
@ -780,19 +701,7 @@ String &String::operator=(char c)
String &String::operator=(wchar_t c)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate());
#else
if(d->deref())
delete d;
d = new StringPrivate;
#endif
d->data.resize(1);
d->data[0] = c;
@ -801,19 +710,7 @@ String &String::operator=(wchar_t c)
String &String::operator=(const char *s)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate());
#else
if(d->deref())
delete d;
d = new StringPrivate;
#endif
copyFromLatin1(s, ::strlen(s));
return *this;
@ -821,19 +718,7 @@ String &String::operator=(const char *s)
String &String::operator=(const ByteVector &v)
{
#ifdef TAGLIB_USE_CXX11
d.reset(new StringPrivate());
#else
if(d->deref())
delete d;
d = new StringPrivate;
#endif
copyFromLatin1(v.data(), v.size());
// If we hit a null in the ByteVector, shrink the string again.
@ -853,19 +738,8 @@ bool String::operator<(const String &s) const
void String::detach()
{
#ifdef TAGLIB_USE_CXX11
if(!d.unique())
d.reset(new StringPrivate(d->data));
#else
if(d->count() > 1) {
d->deref();
d = new StringPrivate(d->data);
}
#endif
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -26,12 +26,8 @@
#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
@ -527,12 +523,7 @@ namespace TagLib {
static const Type WCharByteOrder;
class StringPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<StringPrivate> d;
#else
StringPrivate *d;
#endif
RefCountPtr<StringPrivate> d;
};
/*!