toolkit/tmap.tcc
toolkit/tpropertymap.h
toolkit/tbyteswap.h
+ toolkit/trefcountptr.h
mpeg/mpegfile.h
mpeg/mpegproperties.h
mpeg/mpegheader.h
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}
using namespace TagLib;
-class ASF::Attribute::AttributePrivate : public RefCounter
+class ASF::Attribute::AttributePrivate
{
public:
AttributePrivate()
////////////////////////////////////////////////////////////////////////////////
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;
}
ByteVector render(const String &name, int kind = 0) const;
class AttributePrivate;
- AttributePrivate *d;
+ RefCountPtr<AttributePrivate> d;
};
}
using namespace TagLib;
-class ASF::Picture::PicturePrivate : public RefCounter
+class ASF::Picture::PicturePrivate
{
public:
bool valid;
////////////////////////////////////////////////////////////////////////////////
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
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;
}
static Picture fromInvalid();
friend class Attribute;
#endif
- private:
- class PicturePrivate;
- PicturePrivate *d;
- };
+ private:
+ class PicturePrivate;
+ RefCountPtr<PicturePrivate> d;
+ };
}
}
#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;
};
////////////////////////////////////////////////////////////////////////////////
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
File *FileRef::file() const
{
- return d->file;
+ return d->file.get();
}
bool FileRef::save()
FileRef &FileRef::operator=(const FileRef &ref)
{
- if(&ref == this)
- return *this;
-
- if(d->deref())
- delete d;
-
d = ref.d;
- d->ref();
-
return *this;
}
// 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")
return 0;
}
+
+FileRef::FileTypeResolver::~FileTypeResolver()
+{
+}
class TAGLIB_EXPORT FileTypeResolver
{
- TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
/*!
* This method must be overridden to provide an additional file type
bool readAudioProperties = true,
AudioProperties::ReadStyle
audioPropertiesStyle = AudioProperties::Average) const = 0;
+
+ virtual ~FileTypeResolver();
};
/*!
private:
class FileRefPrivate;
- FileRefPrivate *d;
+ RefCountPtr<FileRefPrivate> d;
};
} // namespace TagLib
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
private:
class CoverArtPrivate;
- CoverArtPrivate *d;
+ RefCountPtr<CoverArtPrivate> d;
};
typedef List<CoverArt> CoverArtList;
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;
};
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;
}
private:
class ItemPrivate;
- ItemPrivate *d;
+ RefCountPtr<ItemPrivate> d;
};
}
using namespace TagLib;
-class MPEG::Header::HeaderPrivate : public RefCounter
+class MPEG::Header::HeaderPrivate
{
public:
HeaderPrivate() :
////////////////////////////////////////////////////////////////////////////////
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
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;
}
#define TAGLIB_MPEGHEADER_H
#include "taglib_export.h"
+#include "trefcountptr.h"
namespace TagLib {
void parse(const ByteVector &data);
class HeaderPrivate;
- HeaderPrivate *d;
+ RefCountPtr<HeaderPrivate> d;
};
}
}
#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.
* 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
-
}
/*!
return ByteVector(reinterpret_cast<const char *>(&value), size);
}
-class DataPrivate : public RefCounter
+class DataPrivate
{
public:
DataPrivate()
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)
{
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;
};
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)
ByteVector::~ByteVector()
{
- if(d->deref())
- delete d;
}
ByteVector &ByteVector::setData(const char *s, uint length)
}
// replace private data:
- if(d->deref())
- delete d;
-
- d = newData;
+ d.reset(newData);
return *this;
}
ByteVector &ByteVector::operator=(const ByteVector &v)
{
- if(&v == this)
- return *this;
-
- if(d->deref())
- delete d;
-
d = v.d;
- d->ref();
return *this;
}
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));
}
}
#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>
private:
class ByteVectorPrivate;
- ByteVectorPrivate *d;
+ RefCountPtr<ByteVectorPrivate> d;
};
}
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;
#define TAGLIB_LIST_H
#include "taglib.h"
-
+#include "trefcountptr.h"
#include <list>
namespace TagLib {
private:
#ifndef DO_NOT_DOCUMENT
template <class TP> class ListPrivate;
- ListPrivate<T> *d;
+ RefCountPtr<ListPrivate<T> > d;
#endif
};
// 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) {}
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;
};
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;
+ }
};
////////////////////////////////////////////////////////////////////////////////
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>
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;
}
}
template <class T>
-TagLib::uint List<T>::size() const
+uint List<T>::size() const
{
return d->list.size();
}
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;
}
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
#ifndef TAGLIB_MAP_H
#define TAGLIB_MAP_H
+#include "taglib.h"
+#include "trefcountptr.h"
#include <map>
-#include "taglib.h"
namespace TagLib {
private:
#ifndef DO_NOT_DOCUMENT
template <class KeyP, class TP> class MapPrivate;
- MapPrivate<Key, T> *d;
+ RefCountPtr<MapPrivate<Key, T> > d;
#endif
};
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>
}
template <class Key, class T>
-TagLib::uint Map<Key, T>::size() const
+uint Map<Key, T>::size() const
{
return d->map.size();
}
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;
}
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
--- /dev/null
+/***************************************************************************
+ 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
#include "tstringlist.h"
#include "tbyteswap.h"
-#include <iostream>
#include <string.h>
// Determine if the compiler supports codecvt.
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)
{
}
String::String(const String &s)
: d(s.d)
{
- d->ref();
}
String::String(const std::string &s, Type t)
String::~String()
{
- if(d->deref())
- delete d;
}
std::string String::to8Bit(bool unicode) const
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;
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;
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.
void String::detach()
{
- if(d->count() > 1) {
- d->deref();
- d = new StringPrivate(d->data);
- }
+ if(!d.unique())
+ d.reset(new StringPrivate(d->data));
}
////////////////////////////////////////////////////////////////////////////////
#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
static const Type WCharByteOrder;
class StringPrivate;
- StringPrivate *d;
+ RefCountPtr<StringPrivate> d;
};
}