From 96cf90823279b4191b917cb36a00f8a219bf374b Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Tue, 19 Mar 2013 05:45:45 +0900 Subject: [PATCH] Replace RefCounter with std::shared_ptr if possible --- taglib/asf/asfattribute.cpp | 69 +++++++++---- taglib/asf/asfattribute.h | 14 +++ taglib/asf/asffile.cpp | 22 ++-- taglib/asf/asfpicture.cpp | 39 ++++++- taglib/asf/asfpicture.h | 33 +++++- taglib/fileref.cpp | 105 ++++++++++++++++--- taglib/fileref.h | 25 ++++- taglib/mp4/mp4coverart.cpp | 32 +++++- taglib/mp4/mp4coverart.h | 8 ++ taglib/mp4/mp4item.cpp | 64 +++++++++--- taglib/mp4/mp4item.h | 12 +++ taglib/mpeg/mpegheader.cpp | 41 +++++++- taglib/mpeg/mpegheader.h | 23 +++++ taglib/toolkit/taglib.h | 86 +++++++++------ taglib/toolkit/tbytevector.cpp | 91 ++++++++++++++-- taglib/toolkit/tbytevector.h | 27 ++++- taglib/toolkit/tbytevectorlist.cpp | 24 ++++- taglib/toolkit/tbytevectorlist.h | 29 ++++-- taglib/toolkit/tfilestream.cpp | 18 +++- taglib/toolkit/tiostream.h | 15 ++- taglib/toolkit/tlist.h | 55 ++++++++++ taglib/toolkit/tlist.tcc | 135 ++++++++++++++++++++++-- taglib/toolkit/tmap.h | 35 ++++++- taglib/toolkit/tmap.tcc | 93 ++++++++++++++++- taglib/toolkit/tstring.cpp | 161 +++++++++++++++++++++++++---- taglib/toolkit/tstring.h | 32 ++++++ taglib/toolkit/tstringlist.cpp | 52 +++++++--- taglib/toolkit/tstringlist.h | 50 +++++++-- 28 files changed, 1210 insertions(+), 180 deletions(-) diff --git a/taglib/asf/asfattribute.cpp b/taglib/asf/asfattribute.cpp index 2cfada7b..c6f24910 100644 --- a/taglib/asf/asfattribute.cpp +++ b/taglib/asf/asfattribute.cpp @@ -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; diff --git a/taglib/asf/asfattribute.h b/taglib/asf/asfattribute.h index 54eb0c7d..28f945aa 100644 --- a/taglib/asf/asfattribute.h +++ b/taglib/asf/asfattribute.h @@ -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 d; +#else AttributePrivate *d; +#endif }; } diff --git a/taglib/asf/asffile.cpp b/taglib/asf/asffile.cpp index 25efa55f..a62f2504 100644 --- a/taglib/asf/asffile.cpp +++ b/taglib/asf/asffile.cpp @@ -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 { diff --git a/taglib/asf/asfpicture.cpp b/taglib/asf/asfpicture.cpp index c36ffa3a..d8f6b23a 100644 --- a/taglib/asf/asfpicture.cpp +++ b/taglib/asf/asfpicture.cpp @@ -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()) diff --git a/taglib/asf/asfpicture.h b/taglib/asf/asfpicture.h index aa0a060c..1703c71f 100644 --- a/taglib/asf/asfpicture.h +++ b/taglib/asf/asfpicture.h @@ -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 d; +#else + PicturePrivate *d; +#endif + }; } } diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index 859f3155..4b456a94 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -31,6 +31,10 @@ #include #endif +#ifdef _WIN32 +# include +#endif + #include #include #include @@ -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; +#else File *file; +#endif + static List fileTypeResolvers; }; @@ -76,30 +92,48 @@ List FileRef::FileRefPrivate::fileTypeResolve //////////////////////////////////////////////////////////////////////////////// FileRef::FileRef() + : d(new FileRefPrivate(0)) { - d = new FileRefPrivate(0); } -FileRef::FileRef(FileName fileName, bool readAudioProperties, - AudioProperties::ReadStyle audioPropertiesStyle) +FileRef::FileRef(FileName fileName, + bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) + : d(new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle))) { - d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle)); } FileRef::FileRef(File *file) + : d(new FileRefPrivate(file)) { - d = new FileRefPrivate(file); } -FileRef::FileRef(const FileRef &ref) : d(ref.d) +FileRef::FileRef(const FileRef &ref) + : d(ref.d) { +#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") diff --git a/taglib/fileref.h b/taglib/fileref.h index 57a2c1b9..1bcd1039 100644 --- a/taglib/fileref.h +++ b/taglib/fileref.h @@ -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 d; +#else FileRefPrivate *d; +#endif }; } // namespace TagLib diff --git a/taglib/mp4/mp4coverart.cpp b/taglib/mp4/mp4coverart.cpp index 928e3c4a..bcb617b1 100644 --- a/taglib/mp4/mp4coverart.cpp +++ b/taglib/mp4/mp4coverart.cpp @@ -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 diff --git a/taglib/mp4/mp4coverart.h b/taglib/mp4/mp4coverart.h index 64115b45..9d4618d7 100644 --- a/taglib/mp4/mp4coverart.h +++ b/taglib/mp4/mp4coverart.h @@ -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 d; +#else CoverArtPrivate *d; +#endif }; typedef List CoverArtList; diff --git a/taglib/mp4/mp4item.cpp b/taglib/mp4/mp4item.cpp index d1158aac..bc918fe9 100644 --- a/taglib/mp4/mp4item.cpp +++ b/taglib/mp4/mp4item.cpp @@ -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; } diff --git a/taglib/mp4/mp4item.h b/taglib/mp4/mp4item.h index d97c9834..c9c89142 100644 --- a/taglib/mp4/mp4item.h +++ b/taglib/mp4/mp4item.h @@ -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 d; +#else ItemPrivate *d; +#endif }; } diff --git a/taglib/mpeg/mpegheader.cpp b/taglib/mpeg/mpegheader.cpp index c715dbc1..c120b2b9 100644 --- a/taglib/mpeg/mpegheader.cpp +++ b/taglib/mpeg/mpegheader.cpp @@ -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 //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/mpeg/mpegheader.h b/taglib/mpeg/mpegheader.h index 020ebd06..e601ded5 100644 --- a/taglib/mpeg/mpegheader.h +++ b/taglib/mpeg/mpegheader.h @@ -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 d; +#else HeaderPrivate *d; +#endif }; } } diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index 1086397b..b87d6506 100755 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -38,34 +38,55 @@ #include -#ifndef _WIN32 - -# ifndef _LARGEFILE_SOURCE -# define _LARGEFILE_SOURCE -# endif - -# define _FILE_OFFSET_BITS 64 -# include +#ifdef _WIN32 +# if !defined(NOMINMAX) +# define NOMINMAX +# endif +# include +#else +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE +# endif +# define _FILE_OFFSET_BITS 64 +# include #endif -#ifdef __APPLE__ -# include -# define TAGLIB_ATOMIC_MAC -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if !defined(NOMINMAX) -# define NOMINMAX -# endif -# include -# define TAGLIB_ATOMIC_WIN -#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \ +// Determines if std::shared_ptr and rvalue reference are available. +// Replaces RefCounter capability with std::shared_ptr 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 +#endif + +#ifndef TAGLIB_USE_CXX11 +# ifdef __APPLE__ +# include +# define TAGLIB_ATOMIC_MAC +# elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define TAGLIB_ATOMIC_WIN +# elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \ && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \ defined(__i686__) || defined(__x86_64) || defined(__ia64)) \ && !defined(__INTEL_COMPILER) -# define TAGLIB_ATOMIC_GCC -#elif defined(__ia64) && defined(__INTEL_COMPILER) -# include -# define TAGLIB_ATOMIC_GCC +# define TAGLIB_ATOMIC_GCC +# elif defined(__ia64) && defined(__INTEL_COMPILER) +# include +# define TAGLIB_ATOMIC_GCC +# endif #endif //! A namespace for all TagLib related classes and functions @@ -110,39 +131,46 @@ namespace TagLib { * \warning This is not part of the TagLib public API! */ + class RefCounter { + // RefCounter is a mere dummy if std::shared_ptr is available. + +#ifndef TAGLIB_USE_CXX11 + public: RefCounter() : refCount(1) {} - -#ifdef TAGLIB_ATOMIC_MAC + +# ifdef TAGLIB_ATOMIC_MAC void ref() { OSAtomicIncrement32Barrier(const_cast(&refCount)); } bool deref() { return ! OSAtomicDecrement32Barrier(const_cast(&refCount)); } int32_t count() { return refCount; } private: volatile int32_t refCount; -#elif defined(TAGLIB_ATOMIC_WIN) +# 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 } diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index ec253e56..ee29185c 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -244,6 +244,13 @@ public: ByteVectorPrivate(const std::vector &v) : RefCounter(), data(v), size(static_cast(v.size())) {} +#ifdef TAGLIB_USE_CXX11 + + ByteVectorPrivate(std::vector &&v) + : RefCounter(), data(v), size(static_cast(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 } //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/toolkit/tbytevector.h b/taglib/toolkit/tbytevector.h index eb4292f5..d2f3d5af 100644 --- a/taglib/toolkit/tbytevector.h +++ b/taglib/toolkit/tbytevector.h @@ -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 d; +#else ByteVectorPrivate *d; +#endif }; /*! diff --git a/taglib/toolkit/tbytevectorlist.cpp b/taglib/toolkit/tbytevectorlist.cpp index 4ab65803..3a399aba 100644 --- a/taglib/toolkit/tbytevectorlist.cpp +++ b/taglib/toolkit/tbytevectorlist.cpp @@ -71,14 +71,32 @@ ByteVectorList::ByteVectorList() : List() ByteVectorList::ByteVectorList(const ByteVectorList &l) : List(l) { - } -ByteVectorList::~ByteVectorList() +#ifdef TAGLIB_USE_CXX11 + +ByteVectorList::ByteVectorList(ByteVectorList &&l) : List(l) { - } +#endif + +ByteVectorList &ByteVectorList::operator=(const ByteVectorList &l) +{ + List::operator=(l); + return *this; +} + +#ifdef TAGLIB_USE_CXX11 + +ByteVectorList &ByteVectorList::operator=(ByteVectorList &&l) +{ + List::operator=(l); + return *this; +} + +#endif + ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const { ByteVector v; diff --git a/taglib/toolkit/tbytevectorlist.h b/taglib/toolkit/tbytevectorlist.h index 17444522..22e558b4 100644 --- a/taglib/toolkit/tbytevectorlist.h +++ b/taglib/toolkit/tbytevectorlist.h @@ -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; }; } diff --git a/taglib/toolkit/tfilestream.cpp b/taglib/toolkit/tfilestream.cpp index fc7c55d9..5075ec68 100644 --- a/taglib/toolkit/tfilestream.cpp +++ b/taglib/toolkit/tfilestream.cpp @@ -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); } } diff --git a/taglib/toolkit/tiostream.h b/taglib/toolkit/tiostream.h index ac7ad7fc..d418810e 100644 --- a/taglib/toolkit/tiostream.h +++ b/taglib/toolkit/tiostream.h @@ -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; diff --git a/taglib/toolkit/tlist.h b/taglib/toolkit/tlist.h index 0099dad5..feffc954 100644 --- a/taglib/toolkit/tlist.h +++ b/taglib/toolkit/tlist.h @@ -70,6 +70,15 @@ namespace TagLib { */ List(const List &l); +#ifdef TAGLIB_USE_CXX11 + + /*! + * Moves \a l into the \e List. + */ + List(List &&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 &append(const List &l); +#ifdef TAGLIB_USE_CXX11 + + /*! + * Appends \a item to the end of the list and returns a reference to the + * list. + */ + List &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 &append(List &&l); + +#endif + /*! * Prepends \a item to the beginning list and returns a reference to the * list. @@ -136,6 +161,22 @@ namespace TagLib { */ List &prepend(const List &l); +#ifdef TAGLIB_USE_CXX11 + + /*! + * Prepends \a item to the beginning list and returns a reference to the + * list. + */ + List &prepend(T &&item); + + /*! + * Prepends all of the items in \a l to the beginning list and returns a + * reference to the list. + */ + List &prepend(List &&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 &operator=(const List &l); +#ifdef TAGLIB_USE_CXX11 + + /*! + * Moves \a l into the \e List. + */ + List &operator=(List &&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 ListPrivate; + +#ifdef TAGLIB_USE_CXX11 + std::shared_ptr> d; +#else ListPrivate *d; +#endif #endif }; diff --git a/taglib/toolkit/tlist.tcc b/taglib/toolkit/tlist.tcc index 2de29956..3b7e5808 100644 --- a/taglib/toolkit/tlist.tcc +++ b/taglib/toolkit/tlist.tcc @@ -53,8 +53,15 @@ template class List::ListPrivate : public ListPrivateBase public: ListPrivate() : ListPrivateBase() {} ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + +#ifdef TAGLIB_USE_CXX11 + + ListPrivate(std::list &&l) : ListPrivateBase(), list(l) {} + +#endif + void clear() { - list.clear(); + std::list().swap(list); } std::list list; }; @@ -68,18 +75,33 @@ template class List::ListPrivate : public ListPrivateBase public: ListPrivate() : ListPrivateBase() {} ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + +#ifdef TAGLIB_USE_CXX11 + + ListPrivate(std::list &&l) : ListPrivateBase(), list(l) {} + +#endif + ~ListPrivate() { - clear(); + deletePointers(); } + void clear() { - if(autoDelete) { - typename std::list::const_iterator it = list.begin(); - for(; it != list.end(); ++it) - delete *it; - } - list.clear(); + deletePointers(); + std::list().swap(list); } + std::list list; + +private: + void deletePointers() { + if(!autoDelete) + return; + + typename std::list::const_iterator it = list.begin(); + for(; it != list.end(); ++it) + delete *it; + } }; //////////////////////////////////////////////////////////////////////////////// @@ -88,21 +110,40 @@ public: template List::List() + : d(new ListPrivate()) { - d = new ListPrivate; } template -List::List(const List &l) : d(l.d) +List::List(const List &l) +: d(l.d) { +#ifndef TAGLIB_USE_CXX11 + d->ref(); + +#endif } +#ifdef TAGLIB_USE_CXX11 + +template +List::List(List &&l) + : d(std::move(l.d)) +{ +} + +#endif + template List::~List() { +#ifndef TAGLIB_USE_CXX11 + if(d->deref()) delete d; + +#endif } template @@ -167,6 +208,29 @@ List &List::append(const List &l) return *this; } +#ifdef TAGLIB_USE_CXX11 + +template +List &List::append(T &&item) +{ + detach(); + d->list.push_back(item); + return *this; +} + +template +List &List::append(List &&l) +{ + detach(); + + for(Iterator it = l.begin(); it != l.end(); ++it) + d->list.push_back(std::move(*it)); + + return *this; +} + +#endif + template List &List::prepend(const T &item) { @@ -183,6 +247,29 @@ List &List::prepend(const List &l) return *this; } +#ifdef TAGLIB_USE_CXX11 + +template +List &List::prepend(T &&item) +{ + detach(); + d->list.push_front(item); + return *this; +} + +template +List &List::prepend(List &&l) +{ + detach(); + + for(Iterator it = l.rbegin(); it != l.rend(); ++it) + d->list.push_front(std::move(*it)); + + return *this; +} + +#endif + template List &List::clear() { @@ -284,6 +371,12 @@ const T &List::operator[](uint i) const template List &List::operator=(const List &l) { + #ifdef TAGLIB_USE_CXX11 + + d = l.d; + + #else + if(&l == this) return *this; @@ -291,9 +384,22 @@ List &List::operator=(const List &l) delete d; d = l.d; d->ref(); +#endif + return *this; } +#ifdef TAGLIB_USE_CXX11 + +template +List &List::operator=(List &&l) +{ + d = std::move(l.d); + return *this; +} + +#endif + template bool List::operator==(const List &l) const { @@ -313,10 +419,19 @@ bool List::operator!=(const List &l) const template void List::detach() { +#ifdef TAGLIB_USE_CXX11 + + if(!d.unique()) + d.reset(new ListPrivate(d->list)); + +#else + if(d->count() > 1) { d->deref(); d = new ListPrivate(d->list); } + +#endif } } // namespace TagLib diff --git a/taglib/toolkit/tmap.h b/taglib/toolkit/tmap.h index a7d99303..457d2c7d 100644 --- a/taglib/toolkit/tmap.h +++ b/taglib/toolkit/tmap.h @@ -73,6 +73,15 @@ namespace TagLib { */ Map(const Map &m); +#ifdef TAGLIB_USE_CXX11 + + /*! + * Moves \a m into the Map. + */ + Map(Map &&m); + +#endif + /*! * Destroys this instance of the Map. */ @@ -108,6 +117,16 @@ namespace TagLib { */ Map &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 &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 &operator=(const Map &m); +#ifdef TAGLIB_USE_CXX11 + + /*! + * Moves \a m into the Map. + */ + Map &operator=(Map &&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 MapPrivate; + +#ifdef TAGLIB_USE_CXX11 + std::shared_ptr> d; +#else MapPrivate *d; #endif - }; +#endif + }; } // Since GCC doesn't support the "export" keyword, we have to include the diff --git a/taglib/toolkit/tmap.tcc b/taglib/toolkit/tmap.tcc index 0f2b9933..9266a21d 100644 --- a/taglib/toolkit/tmap.tcc +++ b/taglib/toolkit/tmap.tcc @@ -35,32 +35,78 @@ class Map::MapPrivate : public RefCounter { public: MapPrivate() : RefCounter() {} + #ifdef WANT_CLASS_INSTANTIATION_OF_MAP - MapPrivate(const std::map& m) : RefCounter(), map(m) {} + + MapPrivate(const std::map &m) : RefCounter(), map(m) {} + +# ifdef TAGLIB_USE_CXX11 + + MapPrivate(std::map &&m) : RefCounter(), map(m) {} + +# endif + + void clear() { + std::map().swap(map); + } + std::map map; + #else + MapPrivate(const std::map& m) : RefCounter(), map(m) {} + +# ifdef TAGLIB_USE_CXX11 + + MapPrivate(std::map &&m) : RefCounter(), map(m) {} + +# endif + + void clear() { + std::map().swap(map); + } + std::map map; + #endif }; template Map::Map() + : d(new MapPrivate()) { - d = new MapPrivate; } template -Map::Map(const Map &m) : d(m.d) +Map::Map(const Map &m) + : d(m.d) { +#ifndef TAGLIB_USE_CXX11 + d->ref(); + +#endif } +#ifdef TAGLIB_USE_CXX11 + +template +TagLib::Map::Map(Map &&m) + : d(std::move(m.d)) +{ +} + +#endif + template Map::~Map() { +#ifndef TAGLIB_USE_CXX11 + if(d->deref()) delete(d); + +#endif } template @@ -97,6 +143,18 @@ Map &Map::insert(const Key &key, const T &value) return *this; } +#ifdef TAGLIB_USE_CXX11 + +template +Map &Map::insert(const Key &key, T &&value) +{ + detach(); + d->map[key] = value; + return *this; +} + +#endif + template Map &Map::clear() { @@ -170,6 +228,12 @@ T &Map::operator[](const Key &key) template Map &Map::operator=(const Map &m) { +#ifdef TAGLIB_USE_CXX11 + + d = m.d; + +#else + if(&m == this) return *this; @@ -177,9 +241,23 @@ Map &Map::operator=(const Map &m) delete(d); d = m.d; d->ref(); + +#endif + return *this; } +#ifdef TAGLIB_USE_CXX11 + +template +Map &Map::operator=(Map &&m) +{ + d = std::move(m.d); + return *this; +} + +#endif + //////////////////////////////////////////////////////////////////////////////// // protected members //////////////////////////////////////////////////////////////////////////////// @@ -187,10 +265,19 @@ Map &Map::operator=(const Map &m) template void Map::detach() { +#ifdef TAGLIB_USE_CXX11 + + if(!d.unique()) + d.reset(new MapPrivate(d->map)); + +#else + if(d->count() > 1) { d->deref(); d = new MapPrivate(d->map); } + +#endif } } // namespace TagLib diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 97309913..2eae6b04 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -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(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(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 } //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index c502e56c..4512ec72 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -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 d; +#else StringPrivate *d; +#endif }; /*! diff --git a/taglib/toolkit/tstringlist.cpp b/taglib/toolkit/tstringlist.cpp index 0645ede5..910de970 100644 --- a/taglib/toolkit/tstringlist.cpp +++ b/taglib/toolkit/tstringlist.cpp @@ -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() { - } StringList::StringList(const StringList &l) : List(l) { - } +#ifdef TAGLIB_USE_CXX11 + +StringList::StringList(StringList &&l) : List(l) +{ +} + +#endif + StringList::StringList(const String &s) : List() { append(s); @@ -78,11 +79,6 @@ StringList::StringList(const ByteVectorList &bl, String::Type t) : List( } } -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::append(s); + return *this; +} + +StringList &StringList::append(StringList &&l) +{ + List::append(l); + return *this; +} + +#endif + +StringList &StringList::operator=(const StringList &l) +{ + List::operator=(l); + return *this; +} + +#ifdef TAGLIB_USE_CXX11 + +StringList &StringList::operator=(StringList &&l) +{ + List::operator=(l); + return *this; +} + +#endif + //////////////////////////////////////////////////////////////////////////////// // related functions //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/toolkit/tstringlist.h b/taglib/toolkit/tstringlist.h index 2a0cf385..babefa17 100644 --- a/taglib/toolkit/tstringlist.h +++ b/taglib/toolkit/tstringlist.h @@ -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; }; /*!