Replace RefCounter with std::shared_ptr if possible

This commit is contained in:
Tsuda Kageyu 2013-03-19 05:45:45 +09:00
parent 42a74babb5
commit 96cf908232
28 changed files with 1210 additions and 180 deletions

View File

@ -60,81 +60,108 @@ 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();
}
#ifndef TAGLIB_USE_CXX11
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;
#endif
}
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;
}
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;
}
#ifdef TAGLIB_USE_CXX11
ASF::Attribute &ASF::Attribute::operator=(ASF::Attribute &&other)
{
d = std::move(other.d);
return *this;
}
#endif
ASF::Attribute::AttributeTypes ASF::Attribute::type() const
{
return d->type;

View File

@ -115,6 +115,15 @@ namespace TagLib
*/
ASF::Attribute &operator=(const Attribute &other);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves the contents of \a other into this item.
*/
ASF::Attribute &operator=(Attribute &&other);
#endif
/*!
* Destroys the attribute.
*/
@ -194,7 +203,12 @@ 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
};
}

View File

@ -60,17 +60,17 @@ public:
ASF::File::MetadataLibraryObject *metadataLibraryObject;
};
static ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
static ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
static ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
static ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
static ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
static ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
static ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
static ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
static ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
static ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
static const ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
static const ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
static const ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
static const ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
static const ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
static const ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
static const ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
static const ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
static const ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
static const ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
static const ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
class ASF::File::BaseObject
{

View File

@ -50,21 +50,38 @@ public:
////////////////////////////////////////////////////////////////////////////////
ASF::Picture::Picture()
: d(new PicturePrivate())
{
d = new PicturePrivate();
d->valid = true;
}
ASF::Picture::Picture(const Picture& other)
: d(other.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
ASF::Picture::Picture(Picture &&other)
: d(std::move(other.d))
{
}
#endif
ASF::Picture::~Picture()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
bool ASF::Picture::isValid() const
@ -121,15 +138,35 @@ 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;
}
#ifdef TAGLIB_USE_CXX11
ASF::Picture& ASF::Picture::operator=(ASF::Picture &&other)
{
d = std::move(other.d);
return *this;
}
#endif
ByteVector ASF::Picture::render() const
{
if(!isValid())

View File

@ -103,10 +103,19 @@ namespace TagLib
Picture();
/*!
* Construct an picture as a copy of \a other.
* Constructs an picture as a copy of \a other.
*/
Picture(const Picture& other);
#ifdef TAGLIB_USE_CXX11
/*!
* Constructs an picture equivalent to \a other.
*/
Picture(Picture &&other);
#endif
/*!
* Destroys the picture.
*/
@ -117,6 +126,15 @@ namespace TagLib
*/
Picture& operator=(const Picture& other);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves the contents of \a other into this picture.
*/
Picture& operator=(Picture &&other);
#endif
/*!
* Returns true if Picture stores valid picture
*/
@ -207,10 +225,15 @@ namespace TagLib
static Picture fromInvalid();
friend class Attribute;
#endif
private:
class PicturePrivate;
PicturePrivate *d;
};
private:
class PicturePrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<PicturePrivate> d;
#else
PicturePrivate *d;
#endif
};
}
}

View File

@ -31,6 +31,10 @@
#include <config.h>
#endif
#ifdef _WIN32
# include <Shlwapi.h>
#endif
#include <tfile.h>
#include <tstring.h>
#include <tdebug.h>
@ -60,12 +64,24 @@ using namespace TagLib;
class FileRef::FileRefPrivate : public RefCounter
{
public:
FileRefPrivate(File *f) : RefCounter(), file(f) {}
~FileRefPrivate() {
FileRefPrivate(File *f)
: RefCounter(), file(f) {}
~FileRefPrivate()
{
#ifndef TAGLIB_USE_CXX11
delete file;
#endif
}
#ifdef TAGLIB_USE_CXX11
std::unique_ptr<File> file;
#else
File *file;
#endif
static List<const FileTypeResolver *> fileTypeResolvers;
};
@ -76,30 +92,48 @@ 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)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
FileRef::FileRef(FileRef &&ref)
: d(std::move(ref.d))
{
}
#endif
FileRef::~FileRef()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
Tag *FileRef::tag() const
@ -122,7 +156,15 @@ AudioProperties *FileRef::audioProperties() const
File *FileRef::file() const
{
#ifdef TAGLIB_USE_CXX11
return d->file.get();
#else
return d->file;
#endif
}
bool FileRef::save()
@ -182,6 +224,12 @@ bool FileRef::isNull() const
FileRef &FileRef::operator=(const FileRef &ref)
{
#ifdef TAGLIB_USE_CXX11
d = ref.d;
#else
if(&ref == this)
return *this;
@ -191,9 +239,21 @@ FileRef &FileRef::operator=(const FileRef &ref)
d = ref.d;
d->ref();
#endif
return *this;
}
#ifdef TAGLIB_USE_CXX11
FileRef &FileRef::operator=(FileRef &&ref)
{
d = std::move(ref.d);
return *this;
}
#endif
bool FileRef::operator==(const FileRef &ref) const
{
return ref.d->file == d->file;
@ -216,23 +276,36 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
return file;
}
// 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;
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")

View File

@ -92,7 +92,7 @@ namespace TagLib {
class TAGLIB_EXPORT FileTypeResolver
{
public:
virtual ~FileTypeResolver();
virtual ~FileTypeResolver() {}
/*!
* This method must be overridden to provide an additional file type
@ -139,6 +139,15 @@ namespace TagLib {
*/
FileRef(const FileRef &ref);
#ifdef TAGLIB_USE_CXX11
/*!
* Move \a ref into the FileRef.
*/
FileRef(FileRef &&ref);
#endif
/*!
* Destroys this FileRef instance.
*/
@ -227,6 +236,15 @@ namespace TagLib {
*/
FileRef &operator=(const FileRef &ref);
#ifdef TAGLIB_USE_CXX11
/*!
* Assign the file pointed to by \a ref to this FileRef.
*/
FileRef &operator=(FileRef &&ref);
#endif
/*!
* Returns true if this FileRef and \a ref point to the same File object.
*/
@ -256,7 +274,12 @@ namespace TagLib {
private:
class FileRefPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<FileRefPrivate> d;
#else
FileRefPrivate *d;
#endif
};
} // namespace TagLib

View File

@ -43,33 +43,61 @@ public:
};
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)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
MP4::CoverArt &
MP4::CoverArt::operator=(const CoverArt &item)
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;
}
#ifdef TAGLIB_USE_CXX11
MP4::CoverArt &
MP4::CoverArt::operator=(CoverArt &&item)
{
d = std::move(item.d);
return *this;
}
#endif
MP4::CoverArt::~CoverArt()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref()) {
delete d;
}
#endif
}
MP4::CoverArt::Format

View File

@ -54,6 +54,9 @@ namespace TagLib {
CoverArt(const CoverArt &item);
CoverArt &operator=(const CoverArt &item);
#ifdef TAGLIB_USE_CXX11
CoverArt &operator=(CoverArt &&item);
#endif
//! Format of the image
Format format() const;
@ -63,7 +66,12 @@ namespace TagLib {
private:
class CoverArtPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<CoverArtPrivate> d;
#else
CoverArtPrivate *d;
#endif
};
typedef List<CoverArt> CoverArtList;

View File

@ -62,94 +62,132 @@ public:
};
MP4::Item::Item()
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->valid = false;
}
MP4::Item::Item(const Item &item) : d(item.d)
MP4::Item::Item(const Item &item)
: d(item.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
MP4::Item &
MP4::Item::operator=(const Item &item)
#ifdef TAGLIB_USE_CXX11
MP4::Item::Item(Item &&item)
: d(std::move(item.d))
{
}
#endif
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;
}
#ifdef TAGLIB_USE_CXX11
MP4::Item &
MP4::Item::operator=(Item &&item)
{
d = std::move(item.d);
return *this;
}
#endif
MP4::Item::~Item()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref()) {
delete d;
}
#endif
}
MP4::Item::Item(bool value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_bool = value;
d->type = TypeBool;
}
MP4::Item::Item(int value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_int = value;
d->type = TypeInt;
}
MP4::Item::Item(uchar value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_byte = value;
d->type = TypeByte;
}
MP4::Item::Item(uint value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_uint = value;
d->type = TypeUInt;
}
MP4::Item::Item(long long value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_longlong = value;
d->type = TypeLongLong;
}
MP4::Item::Item(int value1, int value2)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_intPair.first = value1;
d->m_intPair.second = value2;
d->type = TypeIntPair;
}
MP4::Item::Item(const ByteVectorList &value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_byteVectorList = value;
d->type = TypeByteVectorList;
}
MP4::Item::Item(const StringList &value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_stringList = value;
d->type = TypeStringList;
}
MP4::Item::Item(const MP4::CoverArtList &value)
: d(new ItemPrivate())
{
d = new ItemPrivate;
d->m_coverArtList = value;
d->type = TypeCoverArtList;
}

View File

@ -56,7 +56,14 @@ namespace TagLib {
Item();
Item(const Item &item);
#ifdef TAGLIB_USE_CXX11
Item(Item &&item);
#endif
Item &operator=(const Item &item);
#ifdef TAGLIB_USE_CXX11
Item &operator=(Item &&item);
#endif
~Item();
Item(int value);
@ -90,7 +97,12 @@ namespace TagLib {
private:
class ItemPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<ItemPrivate> d;
#else
ItemPrivate *d;
#endif
};
}

View File

@ -68,20 +68,38 @@ 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)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
MPEG::Header::Header(Header &&h)
: d(std::move(h.d))
{
}
#endif
MPEG::Header::~Header()
{
#ifndef TAGLIB_USE_CXX11
if (d->deref())
delete d;
#endif
}
bool MPEG::Header::isValid() const
@ -146,6 +164,12 @@ 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;
@ -154,9 +178,22 @@ MPEG::Header &MPEG::Header::operator=(const Header &h)
d = h.d;
d->ref();
#endif
return *this;
}
#ifdef TAGLIB_USE_CXX11
MPEG::Header &MPEG::Header::operator=(Header &&h)
{
d = std::move(h.d);
return *this;
}
#endif
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

View File

@ -56,6 +56,15 @@ namespace TagLib {
*/
Header(const Header &h);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a h into the \e Header.
*/
Header(Header &&h);
#endif
/*!
* Destroys this Header instance.
*/
@ -154,11 +163,25 @@ namespace TagLib {
*/
Header &operator=(const Header &h);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a h into the \e Header.
*/
Header &operator=(Header &&h);
#endif
private:
void parse(const ByteVector &data);
class HeaderPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<HeaderPrivate> d;
#else
HeaderPrivate *d;
#endif
};
}
}

View File

@ -38,34 +38,55 @@
#include <string>
#ifndef _WIN32
# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE
# endif
# define _FILE_OFFSET_BITS 64
# include <sys/types.h>
#ifdef _WIN32
# if !defined(NOMINMAX)
# define NOMINMAX
# endif
# include <windows.h>
#else
# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE
# endif
# define _FILE_OFFSET_BITS 64
# include <sys/types.h>
#endif
#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) \
// Determines if std::shared_ptr<T> and rvalue reference are available.
// Replaces RefCounter capability with std::shared_ptr<T> if available.
#ifndef __has_feature
# define __has_feature(x) 0
#endif
#ifndef TAGLIB_USE_CXX11
# if (defined(_MSC_VER) && _MSC_VER >= 1600) \
|| (defined(__clang__) && __has_feature(cxx_rvalue_references)) \
|| (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__))
# define TAGLIB_USE_CXX11
# endif
#endif
#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
# define TAGLIB_ATOMIC_GCC
# elif defined(__ia64) && defined(__INTEL_COMPILER)
# include <ia64intrin.h>
# define TAGLIB_ATOMIC_GCC
# endif
#endif
//! A namespace for all TagLib related classes and functions
@ -110,39 +131,46 @@ namespace 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
# 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)
# 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)
# 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
# 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

@ -244,6 +244,13 @@ public:
ByteVectorPrivate(const std::vector<char> &v)
: RefCounter(), data(v), size(static_cast<TagLib::uint>(v.size())) {}
#ifdef TAGLIB_USE_CXX11
ByteVectorPrivate(std::vector<char> &&v)
: RefCounter(), data(v), size(static_cast<TagLib::uint>(v.size())) {}
#endif
ByteVectorPrivate(TagLib::uint len, char value)
: RefCounter(), data(len, value), size(len) {}
@ -292,43 +299,61 @@ ByteVector ByteVector::fromLongLong(long long value, bool mostSignificantByteFir
////////////////////////////////////////////////////////////////////////////////
ByteVector::ByteVector()
: d(new ByteVectorPrivate())
{
d = new ByteVectorPrivate;
}
ByteVector::ByteVector(uint size, char value)
: d(new ByteVectorPrivate(size, value))
{
d = new ByteVectorPrivate(size, value);
}
ByteVector::ByteVector(const ByteVector &v) : d(v.d)
ByteVector::ByteVector(const ByteVector &v)
: d(v.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
ByteVector::ByteVector(ByteVector &&v)
: d(std::move(v.d))
{
}
#endif
ByteVector::ByteVector(char c)
: d(new ByteVectorPrivate())
{
d = new ByteVectorPrivate;
d->data.push_back(c);
d->size = 1;
}
ByteVector::ByteVector(const char *data, uint length)
: d(new ByteVectorPrivate())
{
d = new ByteVectorPrivate;
setData(data, length);
}
ByteVector::ByteVector(const char *data)
: d(new ByteVectorPrivate())
{
d = new ByteVectorPrivate;
setData(data);
}
ByteVector::~ByteVector()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
ByteVector &ByteVector::setData(const char *data, uint length)
@ -488,11 +513,19 @@ 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;
}
@ -676,6 +709,12 @@ 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;
@ -684,18 +723,49 @@ ByteVector &ByteVector::operator=(const ByteVector &v)
d = v.d;
d->ref();
#endif
return *this;
}
#ifdef TAGLIB_USE_CXX11
ByteVector &ByteVector::operator=(ByteVector &&v)
{
d = std::move(v.d);
return *this;
}
#endif
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;
}
@ -719,10 +789,19 @@ ByteVector ByteVector::toHex() const
void ByteVector::detach()
{
#ifdef TAGLIB_USE_CXX11
if(!d.unique())
d.reset(new ByteVectorPrivate(d->data));
#else
if(d->count() > 1) {
d->deref();
d = new ByteVectorPrivate(d->data);
}
#endif
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -62,12 +62,21 @@ namespace TagLib {
ByteVector(uint size, char value = 0);
/*!
* Contructs a byte vector that is a copy of \a v.
* Constructs a byte vector that is a copy of \a v.
*/
ByteVector(const ByteVector &v);
#ifdef TAGLIB_USE_CXX11
/*!
* Contructs a byte vector that contains \a c.
* Constructs a byte vector equivalent to \a v.
*/
ByteVector(ByteVector &&v);
#endif
/*!
* Constructs a byte vector that contains \a c.
*/
ByteVector(char c);
@ -380,6 +389,15 @@ namespace TagLib {
*/
ByteVector &operator=(const ByteVector &v);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a v into the ByteVector.
*/
ByteVector &operator=(ByteVector &&v);
#endif
/*!
* Copies ByteVector \a v.
*/
@ -411,7 +429,12 @@ namespace TagLib {
private:
class ByteVectorPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<ByteVectorPrivate> d;
#else
ByteVectorPrivate *d;
#endif
};
/*!

View File

@ -71,14 +71,32 @@ ByteVectorList::ByteVectorList() : List<ByteVector>()
ByteVectorList::ByteVectorList(const ByteVectorList &l) : List<ByteVector>(l)
{
}
ByteVectorList::~ByteVectorList()
#ifdef TAGLIB_USE_CXX11
ByteVectorList::ByteVectorList(ByteVectorList &&l) : List<ByteVector>(l)
{
}
#endif
ByteVectorList &ByteVectorList::operator=(const ByteVectorList &l)
{
List<ByteVector>::operator=(l);
return *this;
}
#ifdef TAGLIB_USE_CXX11
ByteVectorList &ByteVectorList::operator=(ByteVectorList &&l)
{
List<ByteVector>::operator=(l);
return *this;
}
#endif
ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const
{
ByteVector v;

View File

@ -48,16 +48,36 @@ namespace TagLib {
ByteVectorList();
/*!
* Destroys this ByteVectorList instance.
* Make a shallow, implicitly shared, copy of \a l. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
virtual ~ByteVectorList();
ByteVectorList(const ByteVectorList &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a l into the StringList.
*/
ByteVectorList(ByteVectorList &&l);
#endif
/*!
* Make a shallow, implicitly shared, copy of \a l. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
ByteVectorList(const ByteVectorList &l);
ByteVectorList &operator=(const ByteVectorList &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a l into the \e ByteVectorList.
*/
ByteVectorList &operator=(ByteVectorList &&l);
#endif
/*!
* Convert the ByteVectorList to a ByteVector separated by \a separator. By
@ -74,9 +94,6 @@ namespace TagLib {
*/
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern,
int byteAlign = 1, int max = 0);
private:
class ByteVectorListPrivate;
ByteVectorListPrivate *d;
};
}

View File

@ -55,10 +55,10 @@ namespace {
{
DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
if(wcslen(path) > 0)
return CreateFileW(path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(!path.wstr().empty())
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
else
return CreateFileA(path, access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
return CreateFileA(path.str().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
}
size_t fread(void *ptr, size_t size, size_t nmemb, HANDLE stream)
@ -136,7 +136,17 @@ FileStream::FileStreamPrivate::FileStreamPrivate(FileName fileName, bool openRea
file = openFile(name, true);
if(file == InvalidFile) {
debug("Could not open file " + String((const char *) name));
#ifdef _WIN32
String n;
if(!name.wstr().empty())
n = name.wstr();
else
n = name.str();
#else
String n(name);
#endif // DEBUG
debug("Could not open file " + n);
}
}

View File

@ -30,6 +30,11 @@
#include "taglib.h"
#include "tbytevector.h"
#ifdef _WIN32
# include "tstring.h"
# include "tdebug.h"
#endif
namespace TagLib {
#ifdef _WIN32
@ -38,11 +43,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;
const std::string m_name;
const std::wstring m_wname;
};
#else
typedef const char *FileName;

View File

@ -70,6 +70,15 @@ namespace TagLib {
*/
List(const List<T> &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a l into the \e List.
*/
List(List<T> &&l);
#endif
/*!
* Destroys this List instance. If auto deletion is enabled and this list
* contains a pointer type all of the memebers are also deleted.
@ -124,6 +133,22 @@ namespace TagLib {
*/
List<T> &append(const List<T> &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Appends \a item to the end of the list and returns a reference to the
* list.
*/
List<T> &append(T &&item);
/*!
* Appends all of the values in \a l to the end of the list and returns a
* reference to the list.
*/
List<T> &append(List<T> &&l);
#endif
/*!
* Prepends \a item to the beginning list and returns a reference to the
* list.
@ -136,6 +161,22 @@ namespace TagLib {
*/
List<T> &prepend(const List<T> &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Prepends \a item to the beginning list and returns a reference to the
* list.
*/
List<T> &prepend(T &&item);
/*!
* Prepends all of the items in \a l to the beginning list and returns a
* reference to the list.
*/
List<T> &prepend(List<T> &&l);
#endif
/*!
* Clears the list. If auto deletion is enabled and this list contains a
* pointer type the members are also deleted.
@ -221,6 +262,15 @@ namespace TagLib {
*/
List<T> &operator=(const List<T> &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a l into the \e List.
*/
List<T> &operator=(List<T> &&l);
#endif
/*!
* Compares this list with \a l and returns true if all of the elements are
* the same.
@ -243,7 +293,12 @@ 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
#endif
};

View File

@ -53,8 +53,15 @@ template <class TP> class List<T>::ListPrivate : public ListPrivateBase
public:
ListPrivate() : ListPrivateBase() {}
ListPrivate(const std::list<TP> &l) : ListPrivateBase(), list(l) {}
#ifdef TAGLIB_USE_CXX11
ListPrivate(std::list<TP> &&l) : ListPrivateBase(), list(l) {}
#endif
void clear() {
list.clear();
std::list<TP>().swap(list);
}
std::list<TP> list;
};
@ -68,18 +75,33 @@ template <class TP> class List<T>::ListPrivate<TP *> : public ListPrivateBase
public:
ListPrivate() : ListPrivateBase() {}
ListPrivate(const std::list<TP *> &l) : ListPrivateBase(), list(l) {}
#ifdef TAGLIB_USE_CXX11
ListPrivate(std::list<TP *> &&l) : ListPrivateBase(), list(l) {}
#endif
~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 +110,40 @@ 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)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
template <class T>
List<T>::List(List<T> &&l)
: d(std::move(l.d))
{
}
#endif
template <class T>
List<T>::~List()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete d;
#endif
}
template <class T>
@ -167,6 +208,29 @@ List<T> &List<T>::append(const List<T> &l)
return *this;
}
#ifdef TAGLIB_USE_CXX11
template <class T>
List<T> &List<T>::append(T &&item)
{
detach();
d->list.push_back(item);
return *this;
}
template <class T>
List<T> &List<T>::append(List<T> &&l)
{
detach();
for(Iterator it = l.begin(); it != l.end(); ++it)
d->list.push_back(std::move(*it));
return *this;
}
#endif
template <class T>
List<T> &List<T>::prepend(const T &item)
{
@ -183,6 +247,29 @@ List<T> &List<T>::prepend(const List<T> &l)
return *this;
}
#ifdef TAGLIB_USE_CXX11
template <class T>
List<T> &List<T>::prepend(T &&item)
{
detach();
d->list.push_front(item);
return *this;
}
template <class T>
List<T> &List<T>::prepend(List<T> &&l)
{
detach();
for(Iterator it = l.rbegin(); it != l.rend(); ++it)
d->list.push_front(std::move(*it));
return *this;
}
#endif
template <class T>
List<T> &List<T>::clear()
{
@ -284,6 +371,12 @@ const T &List<T>::operator[](uint 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;
@ -291,9 +384,22 @@ List<T> &List<T>::operator=(const List<T> &l)
delete d;
d = l.d;
d->ref();
#endif
return *this;
}
#ifdef TAGLIB_USE_CXX11
template <class T>
List<T> &List<T>::operator=(List<T> &&l)
{
d = std::move(l.d);
return *this;
}
#endif
template <class T>
bool List<T>::operator==(const List<T> &l) const
{
@ -313,10 +419,19 @@ 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

@ -73,6 +73,15 @@ namespace TagLib {
*/
Map(const Map<Key, T> &m);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a m into the Map.
*/
Map(Map<Key, T> &&m);
#endif
/*!
* Destroys this instance of the Map.
*/
@ -108,6 +117,16 @@ namespace TagLib {
*/
Map<Key, T> &insert(const Key &key, const T &value);
#ifdef TAGLIB_USE_CXX11
/*!
* Inserts \a value under \a key in the map. If a value for \a key already
* exists it will be overwritten.
*/
Map<Key, T> &insert(const Key &key, T &&value);
#endif
/*!
* Removes all of the elements from elements from the map. This however
* will not delete pointers if the mapped type is a pointer type.
@ -174,6 +193,15 @@ namespace TagLib {
*/
Map<Key, T> &operator=(const Map<Key, T> &m);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a m into the Map.
*/
Map<Key, T> &operator=(Map<Key, T> &&m);
#endif
protected:
/*
* If this List is being shared via implicit sharing, do a deep copy of the
@ -185,10 +213,15 @@ 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
};
#endif
};
}
// Since GCC doesn't support the "export" keyword, we have to include the

View File

@ -35,32 +35,78 @@ class Map<Key, T>::MapPrivate : public RefCounter
{
public:
MapPrivate() : RefCounter() {}
#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) {}
# ifdef TAGLIB_USE_CXX11
MapPrivate(std::map<class KeyP, class TP> &&m) : RefCounter(), map(m) {}
# endif
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) {}
# ifdef TAGLIB_USE_CXX11
MapPrivate(std::map<KeyP, TP> &&m) : RefCounter(), map(m) {}
# endif
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)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
template <class Key, class T>
TagLib::Map<Key, T>::Map(Map<Key, T> &&m)
: d(std::move(m.d))
{
}
#endif
template <class Key, class T>
Map<Key, T>::~Map()
{
#ifndef TAGLIB_USE_CXX11
if(d->deref())
delete(d);
#endif
}
template <class Key, class T>
@ -97,6 +143,18 @@ Map<Key, T> &Map<Key, T>::insert(const Key &key, const T &value)
return *this;
}
#ifdef TAGLIB_USE_CXX11
template <class Key, class T>
Map<Key, T> &Map<Key, T>::insert(const Key &key, T &&value)
{
detach();
d->map[key] = value;
return *this;
}
#endif
template <class Key, class T>
Map<Key, T> &Map<Key, T>::clear()
{
@ -170,6 +228,12 @@ 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;
@ -177,9 +241,23 @@ Map<Key, T> &Map<Key, T>::operator=(const Map<Key, T> &m)
delete(d);
d = m.d;
d->ref();
#endif
return *this;
}
#ifdef TAGLIB_USE_CXX11
template <class Key, class T>
Map<Key, T> &Map<Key, T>::operator=(Map<Key, T> &&m)
{
d = std::move(m.d);
return *this;
}
#endif
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
@ -187,10 +265,19 @@ Map<Key, T> &Map<Key, T>::operator=(const 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

@ -82,6 +82,16 @@ namespace {
class String::StringPrivate : public RefCounter
{
public:
#ifdef TAGLIB_USE_CXX11
StringPrivate() {}
StringPrivate(const wstring &s) : data(s) {}
StringPrivate(wstring &&s) : data(s) {}
#else
public:
StringPrivate(const wstring &s) :
RefCounter(),
@ -90,6 +100,8 @@ public:
StringPrivate() :
RefCounter() {}
#endif
/*!
* Stores string in UTF-16. The byte order depends on the CPU endian.
*/
@ -105,20 +117,33 @@ String String::null;
////////////////////////////////////////////////////////////////////////////////
String::String()
String::String()
: d(new StringPrivate())
{
d = new StringPrivate;
}
String::String(const String &s) : d(s.d)
String::String(const String &s)
: d(s.d)
{
#ifndef TAGLIB_USE_CXX11
d->ref();
#endif
}
#ifdef TAGLIB_USE_CXX11
String::String(String &&s)
: d(std::move(s.d))
{
}
#endif
String::String(const std::string &s, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(t == Latin1)
copyFromLatin1(&s[0], s.length());
else if(t == String::UTF8)
@ -129,9 +154,8 @@ String::String(const std::string &s, Type t)
}
String::String(const wstring &s, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(s.c_str(), s.length(), t);
else {
@ -140,9 +164,8 @@ String::String(const wstring &s, Type t)
}
String::String(const wchar_t *s, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(s, ::wcslen(s), t);
else {
@ -151,9 +174,8 @@ String::String(const wchar_t *s, Type t)
}
String::String(const char *s, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(t == Latin1)
copyFromLatin1(s, ::strlen(s));
else if(t == String::UTF8)
@ -164,9 +186,8 @@ String::String(const char *s, Type t)
}
String::String(wchar_t c, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(&c, 1, t);
else {
@ -175,9 +196,8 @@ String::String(wchar_t c, Type t)
}
String::String(char c, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(t == Latin1 || t == UTF8) {
d->data.resize(1);
d->data[0] = static_cast<uchar>(c);
@ -188,9 +208,8 @@ String::String(char c, Type t)
}
String::String(const ByteVector &v, Type t)
: d(new StringPrivate())
{
d = new StringPrivate;
if(v.isEmpty())
return;
@ -206,8 +225,12 @@ 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
@ -663,6 +686,12 @@ String &String::operator+=(char c)
String &String::operator=(const String &s)
{
#ifdef TAGLIB_USE_CXX11
d = s.d;
#else
if(&s == this)
return *this;
@ -670,15 +699,37 @@ String &String::operator=(const String &s)
delete d;
d = s.d;
d->ref();
#endif
return *this;
}
#ifdef TAGLIB_USE_CXX11
String &String::operator=(String &&s)
{
d = std::move(s.d);
return *this;
}
#endif
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;
@ -686,20 +737,47 @@ 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;
}
#ifdef TAGLIB_USE_CXX11
String &String::operator=(wstring &&s)
{
d.reset(new StringPrivate(s));
return *this;
}
#endif
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;
@ -707,10 +785,19 @@ 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);
@ -719,10 +806,19 @@ 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;
@ -731,10 +827,19 @@ 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;
@ -742,10 +847,19 @@ 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.
@ -765,10 +879,19 @@ 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

@ -123,6 +123,15 @@ namespace TagLib {
*/
String(const String &s);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a s into the \e String.
*/
String(String &&s);
#endif
/*!
* Makes a deep copy of the data in \a s.
*
@ -396,6 +405,15 @@ namespace TagLib {
*/
String &operator=(const String &s);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a s into the \e String.
*/
String &operator=(String &&s);
#endif
/*!
* Performs a deep copy of the data in \a s.
*/
@ -406,6 +424,15 @@ namespace TagLib {
*/
String &operator=(const wstring &s);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a s into the \e String.
*/
String &operator=(wstring &&s);
#endif
/*!
* Performs a deep copy of the data in \a s.
*/
@ -484,7 +511,12 @@ namespace TagLib {
static Type WCharByteOrder;
class StringPrivate;
#ifdef TAGLIB_USE_CXX11
std::shared_ptr<StringPrivate> d;
#else
StringPrivate *d;
#endif
};
/*!

View File

@ -27,11 +27,6 @@
using namespace TagLib;
class StringListPrivate
{
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
@ -57,14 +52,20 @@ StringList StringList::split(const String &s, const String &pattern)
StringList::StringList() : List<String>()
{
}
StringList::StringList(const StringList &l) : List<String>(l)
{
}
#ifdef TAGLIB_USE_CXX11
StringList::StringList(StringList &&l) : List<String>(l)
{
}
#endif
StringList::StringList(const String &s) : List<String>()
{
append(s);
@ -78,11 +79,6 @@ StringList::StringList(const ByteVectorList &bl, String::Type t) : List<String>(
}
}
StringList::~StringList()
{
}
String StringList::toString(const String &separator) const
{
String s;
@ -112,6 +108,38 @@ StringList &StringList::append(const StringList &l)
return *this;
}
#ifdef TAGLIB_USE_CXX11
StringList &StringList::append(String &&s)
{
List<String>::append(s);
return *this;
}
StringList &StringList::append(StringList &&l)
{
List<String>::append(l);
return *this;
}
#endif
StringList &StringList::operator=(const StringList &l)
{
List<String>::operator=(l);
return *this;
}
#ifdef TAGLIB_USE_CXX11
StringList &StringList::operator=(StringList &&l)
{
List<String>::operator=(l);
return *this;
}
#endif
////////////////////////////////////////////////////////////////////////////////
// related functions
////////////////////////////////////////////////////////////////////////////////

View File

@ -58,6 +58,15 @@ namespace TagLib {
*/
StringList(const StringList &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a l into the StringList.
*/
StringList(StringList &&l);
#endif
/*!
* Constructs a StringList with \a s as a member.
*/
@ -71,11 +80,6 @@ namespace TagLib {
*/
StringList(const ByteVectorList &vl, String::Type t = String::Latin1);
/*!
* Destroys this StringList instance.
*/
virtual ~StringList();
/*!
* Concatenate the list of strings into one string separated by \a separator.
*/
@ -93,15 +97,43 @@ namespace TagLib {
*/
StringList &append(const StringList &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Appends \a s to the end of the list and returns a reference to the
* list.
*/
StringList &append(String &&s);
/*!
* Appends all of the values in \a l to the end of the list and returns a
* reference to the list.
*/
StringList &append(StringList &&l);
#endif
/*!
* Make a shallow, implicitly shared, copy of \a l. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
StringList &operator=(const StringList &l);
#ifdef TAGLIB_USE_CXX11
/*!
* Moves \a l into the \e StringList.
*/
StringList &operator=(StringList &&l);
#endif
/*!
* Splits the String \a s into several strings at \a pattern. This will not include
* the pattern in the returned strings.
*/
static StringList split(const String &s, const String &pattern);
private:
class StringListPrivate;
StringListPrivate *d;
};
/*!