Merge pull request #214 from TsudaKageyu/removeptr

Removed smart pointers from public headers
This commit is contained in:
Tsuda Kageyu
2013-06-01 08:05:48 -07:00
40 changed files with 861 additions and 1412 deletions

View File

@ -118,54 +118,113 @@ if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP
endif()
endif()
# Determine where shared_ptr<T> is defined regardless of C++11 support.
check_cxx_source_compiles("
#include <memory>
int main() { std::shared_ptr<int> x; return 0; }
" HAVE_STD_SHARED_PTR)
if(NOT HAVE_STD_SHARED_PTR)
check_cxx_source_compiles("
#include <tr1/memory>
int main() { std::tr1::shared_ptr<int> x; return 0; }
" HAVE_TR1_SHARED_PTR)
if(NOT HAVE_TR1_SHARED_PTR)
check_cxx_source_compiles("
#include <boost/shared_ptr.hpp>
int main() { boost::shared_ptr<int> x; return 0; }
" HAVE_BOOST_SHARED_PTR)
endif()
endif()
# Determine where unique_ptr<T> or scoped_ptr<T> is defined regardless of C++11 support.
check_cxx_source_compiles("
#include <memory>
int main() { std::unique_ptr<int> x; return 0; }
" HAVE_STD_UNIQUE_PTR)
if(NOT HAVE_STD_UNIQUE_PTR)
check_cxx_source_compiles("
#include <boost/scoped_ptr.hpp>
int main() { boost::scoped_ptr<int> x; return 0; }
" HAVE_BOOST_SCOPED_PTR)
endif()
# Determine which kind of atomic operations your compiler supports.
check_cxx_source_compiles("
#include <atomic>
int main() {
volatile int x;
__sync_add_and_fetch(&x, 1);
int y = __sync_sub_and_fetch(&x, 1);
std::atomic<unsigned int> x;
x.fetch_add(1);
x.fetch_sub(1);
return 0;
}
" HAVE_GCC_ATOMIC)
" HAVE_STD_ATOMIC)
if(NOT HAVE_GCC_ATOMIC)
if(NOT HAVE_STD_ATOMIC)
check_cxx_source_compiles("
#include <libkern/OSAtomic.h>
#include <boost/atomic.hpp>
int main() {
volatile int32_t x;
OSAtomicIncrement32Barrier(&x);
int32_t y = OSAtomicDecrement32Barrier(&x);
boost::atomic<unsigned int> x(1);
x.fetch_add(1);
x.fetch_sub(1);
return 0;
}
" HAVE_MAC_ATOMIC)
" HAVE_BOOST_ATOMIC)
if(NOT HAVE_MAC_ATOMIC)
if(NOT HAVE_BOOST_ATOMIC)
check_cxx_source_compiles("
#include <windows.h>
int main() {
volatile LONG x;
InterlockedIncrement(&x);
LONG y = InterlockedDecrement(&x);
volatile int x;
__sync_add_and_fetch(&x, 1);
int y = __sync_sub_and_fetch(&x, 1);
return 0;
}
" HAVE_WIN_ATOMIC)
" HAVE_GCC_ATOMIC)
if(NOT HAVE_WIN_ATOMIC)
if(NOT HAVE_GCC_ATOMIC)
check_cxx_source_compiles("
#include <ia64intrin.h>
#include <libkern/OSAtomic.h>
int main() {
volatile int x;
__sync_add_and_fetch(&x, 1);
int y = __sync_sub_and_fetch(&x, 1);
volatile int32_t x;
OSAtomicIncrement32Barrier(&x);
int32_t y = OSAtomicDecrement32Barrier(&x);
return 0;
}
" HAVE_IA64_ATOMIC)
" HAVE_MAC_ATOMIC)
if(NOT HAVE_MAC_ATOMIC)
check_cxx_source_compiles("
#include <windows.h>
int main() {
volatile LONG x;
InterlockedIncrement(&x);
LONG y = InterlockedDecrement(&x);
return 0;
}
" HAVE_WIN_ATOMIC)
if(NOT HAVE_WIN_ATOMIC)
check_cxx_source_compiles("
#include <ia64intrin.h>
int main() {
volatile int x;
__sync_add_and_fetch(&x, 1);
int y = __sync_sub_and_fetch(&x, 1);
return 0;
}
" HAVE_IA64_ATOMIC)
endif()
endif()
endif()
endif()
endif()
# Determine whether your compiler supports some safer version of sprintf.
# Determine whether your compiler supports snpritf or sprintf_s.
check_cxx_source_compiles("
#include <cstdio>
@ -198,52 +257,6 @@ else()
set(HAVE_ZLIB 0)
endif()
# Determine whether your compiler supports move semantics.
check_cxx_source_compiles("
#ifdef __clang__
# pragma clang diagnostic error \"-Wc++11-extensions\"
#endif
#include <utility>
int func(int &&x) { return x - 1; }
int main() { return func(std::move(1)); }
" TAGLIB_USE_MOVE_SEMANTICS)
# Determine where shared_ptr<T> is defined regardless of C++11 support.
check_cxx_source_compiles("
#include <memory>
int main() { std::shared_ptr<int> x; return 0; }
" TAGLIB_USE_STD_SHARED_PTR)
if(NOT TAGLIB_USE_STD_SHARED_PTR)
check_cxx_source_compiles("
#include <tr1/memory>
int main() { std::tr1::shared_ptr<int> x; return 0; }
" TAGLIB_USE_TR1_SHARED_PTR)
if(NOT TAGLIB_USE_TR1_SHARED_PTR)
check_cxx_source_compiles("
#include <boost/shared_ptr.hpp>
int main() { boost::shared_ptr<int> x; return 0; }
" TAGLIB_USE_BOOST_SHARED_PTR)
endif()
endif()
# Determine where unique_ptr<T> or scoped_ptr<T> is defined regardless of C++11 support.
check_cxx_source_compiles("
#include <memory>
int main() { std::unique_ptr<int> x; return 0; }
" TAGLIB_USE_STD_UNIQUE_PTR)
if(NOT TAGLIB_USE_STD_UNIQUE_PTR)
check_cxx_source_compiles("
#include <boost/scoped_ptr.hpp>
int main() { boost::scoped_ptr<int> x; return 0; }
" TAGLIB_USE_BOOST_SCOPED_PTR)
endif()
# Determine whether CppUnit is installed.
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)

View File

@ -18,13 +18,24 @@
#cmakedefine HAVE_MAC_BYTESWAP 1
#cmakedefine HAVE_OPENBSD_BYTESWAP 1
/* Defined if your compiler supports shared_ptr */
#cmakedefine HAVE_STD_SHARED_PTR 1 // #include <memory> / std::shared_ptr<T>
#cmakedefine HAVE_TR1_SHARED_PTR 1 // #include <tr1/memory> / std::tr1::shared_ptr<T>
#cmakedefine HAVE_BOOST_SHARED_PTR 1 // #include <boost/shared_ptr.hpp> / boost::shared_ptr<T>
/* Defined if your compiler supports unique_ptr or scoped_ptr */
#cmakedefine HAVE_STD_UNIQUE_PTR 1 // #include <memory> / std::unique_ptr<T>
#cmakedefine HAVE_BOOST_SCOPED_PTR 1 // #include <boost/scoped_ptr.hpp> / boost::scoped_ptr<T>
/* Defined if your compiler supports some atomic operations */
#cmakedefine HAVE_STD_ATOMIC 1
#cmakedefine HAVE_BOOST_ATOMIC 1
#cmakedefine HAVE_GCC_ATOMIC 1
#cmakedefine HAVE_MAC_ATOMIC 1
#cmakedefine HAVE_WIN_ATOMIC 1
#cmakedefine HAVE_IA64_ATOMIC 1
/* Defined if your compiler supports some safer version of sprintf */
/* Defined if your compiler supports snpritf or sprintf_s. */
#cmakedefine HAVE_SNPRINTF 1
#cmakedefine HAVE_SPRINTF_S 1

View File

@ -53,7 +53,7 @@ set(tag_HDRS
toolkit/tmap.h
toolkit/tmap.tcc
toolkit/tpropertymap.h
toolkit/tsmartptr.h
toolkit/trefcounter.h
mpeg/mpegfile.h
mpeg/mpegproperties.h
mpeg/mpegheader.h
@ -300,7 +300,7 @@ set(toolkit_SRCS
toolkit/tfilestream.cpp
toolkit/tdebug.cpp
toolkit/tpropertymap.cpp
toolkit/tsmartptr.cpp
toolkit/trefcounter.cpp
toolkit/unicode.cpp
)

View File

@ -23,32 +23,45 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "asfattribute.h"
#include "asffile.h"
using namespace TagLib;
namespace
{
struct AttributeData
{
ASF::Attribute::AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
union {
unsigned int intValue;
unsigned short shortValue;
unsigned long long longLongValue;
bool boolValue;
};
int stream;
int language;
};
}
class ASF::Attribute::AttributePrivate
{
public:
AttributePrivate()
: pictureValue(ASF::Picture::fromInvalid()),
stream(0),
language(0) {}
AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
union {
unsigned int intValue;
unsigned short shortValue;
unsigned long long longLongValue;
bool boolValue;
};
int stream;
int language;
: data(new AttributeData())
{
data->pictureValue = ASF::Picture::fromInvalid();
data->stream = 0;
data->language = 0;
}
SHARED_PTR<AttributeData> data;
};
////////////////////////////////////////////////////////////////////////////////
@ -58,135 +71,127 @@ public:
ASF::Attribute::Attribute()
: d(new AttributePrivate())
{
d->type = UnicodeType;
d->data->type = UnicodeType;
}
ASF::Attribute::Attribute(const ASF::Attribute &other)
: d(other.d)
: d(new AttributePrivate(*other.d))
{
}
ASF::Attribute::Attribute(const String &value)
: d(new AttributePrivate())
{
d->type = UnicodeType;
d->stringValue = value;
d->data->type = UnicodeType;
d->data->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value)
: d(new AttributePrivate())
{
d->type = BytesType;
d->byteVectorValue = value;
d->data->type = BytesType;
d->data->byteVectorValue = value;
}
ASF::Attribute::Attribute(const ASF::Picture &value)
: d(new AttributePrivate())
{
d->type = BytesType;
d->pictureValue = value;
d->data->type = BytesType;
d->data->pictureValue = value;
}
ASF::Attribute::Attribute(unsigned int value)
: d(new AttributePrivate())
{
d->type = DWordType;
d->intValue = value;
d->data->type = DWordType;
d->data->intValue = value;
}
ASF::Attribute::Attribute(unsigned long long value)
: d(new AttributePrivate())
{
d->type = QWordType;
d->longLongValue = value;
d->data->type = QWordType;
d->data->longLongValue = value;
}
ASF::Attribute::Attribute(unsigned short value)
: d(new AttributePrivate())
{
d->type = WordType;
d->shortValue = value;
d->data->type = WordType;
d->data->shortValue = value;
}
ASF::Attribute::Attribute(bool value)
: d(new AttributePrivate())
{
d->type = BoolType;
d->boolValue = value;
d->data->type = BoolType;
d->data->boolValue = value;
}
ASF::Attribute::~Attribute()
{
delete d;
}
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
{
d = other.d;
*d = *other.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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;
return d->data->type;
}
String ASF::Attribute::toString() const
{
return d->stringValue;
return d->data->stringValue;
}
ByteVector ASF::Attribute::toByteVector() const
{
if(d->pictureValue.isValid())
return d->pictureValue.render();
return d->byteVectorValue;
if(d->data->pictureValue.isValid())
return d->data->pictureValue.render();
return d->data->byteVectorValue;
}
unsigned short ASF::Attribute::toBool() const
{
return d->shortValue;
return d->data->shortValue;
}
unsigned short ASF::Attribute::toUShort() const
{
return d->shortValue;
return d->data->shortValue;
}
unsigned int ASF::Attribute::toUInt() const
{
return d->intValue;
return d->data->intValue;
}
unsigned long long ASF::Attribute::toULongLong() const
{
return d->longLongValue;
return d->data->longLongValue;
}
ASF::Picture ASF::Attribute::toPicture() const
{
return d->pictureValue;
return d->data->pictureValue;
}
String ASF::Attribute::parse(ASF::File &f, int kind)
{
uint size, nameLength;
String name;
d->pictureValue = Picture::fromInvalid();
d->data->pictureValue = Picture::fromInvalid();
// extended content descriptor
if(kind == 0) {
nameLength = f.readWORD();
name = f.readString(nameLength);
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
d->data->type = ASF::Attribute::AttributeTypes(f.readWORD());
size = f.readWORD();
}
// metadata & metadata library
@ -194,11 +199,11 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
int temp = f.readWORD();
// metadata library
if(kind == 2) {
d->language = temp;
d->data->language = temp;
}
d->stream = f.readWORD();
d->data->stream = f.readWORD();
nameLength = f.readWORD();
d->type = ASF::Attribute::AttributeTypes(f.readWORD());
d->data->type = ASF::Attribute::AttributeTypes(f.readWORD());
size = f.readDWORD();
name = f.readString(nameLength);
}
@ -207,42 +212,42 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
debug("ASF::Attribute::parse() -- Value larger than 64kB");
}
switch(d->type) {
switch(d->data->type) {
case WordType:
d->shortValue = f.readWORD();
d->data->shortValue = f.readWORD();
break;
case BoolType:
if(kind == 0) {
d->boolValue = f.readDWORD() == 1;
d->data->boolValue = f.readDWORD() == 1;
}
else {
d->boolValue = f.readWORD() == 1;
d->data->boolValue = f.readWORD() == 1;
}
break;
case DWordType:
d->intValue = f.readDWORD();
d->data->intValue = f.readDWORD();
break;
case QWordType:
d->longLongValue = f.readQWORD();
d->data->longLongValue = f.readQWORD();
break;
case UnicodeType:
d->stringValue = f.readString(size);
d->data->stringValue = f.readString(size);
break;
case BytesType:
case GuidType:
d->byteVectorValue = f.readBlock(size);
d->data->byteVectorValue = f.readBlock(size);
break;
}
if(d->type == BytesType && name == "WM/Picture") {
d->pictureValue.parse(d->byteVectorValue);
if(d->pictureValue.isValid()) {
d->byteVectorValue.clear();
if(d->data->type == BytesType && name == "WM/Picture") {
d->data->pictureValue.parse(d->data->byteVectorValue);
if(d->data->pictureValue.isValid()) {
d->data->byteVectorValue.clear();
}
}
@ -251,7 +256,7 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
int ASF::Attribute::dataSize() const
{
switch (d->type) {
switch (d->data->type) {
case WordType:
return 2;
case BoolType:
@ -261,12 +266,12 @@ int ASF::Attribute::dataSize() const
case QWordType:
return 5;
case UnicodeType:
return static_cast<int>(d->stringValue.size() * 2 + 2);
return static_cast<int>(d->data->stringValue.size() * 2 + 2);
case BytesType:
if(d->pictureValue.isValid())
return d->pictureValue.dataSize();
if(d->data->pictureValue.isValid())
return d->data->pictureValue.dataSize();
case GuidType:
return static_cast<int>(d->byteVectorValue.size());
return static_cast<int>(d->data->byteVectorValue.size());
}
return 0;
}
@ -275,54 +280,54 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
{
ByteVector data;
switch (d->type) {
switch (d->data->type) {
case WordType:
data.append(ByteVector::fromUInt16LE(d->shortValue));
data.append(ByteVector::fromUInt16LE(d->data->shortValue));
break;
case BoolType:
if(kind == 0) {
data.append(ByteVector::fromUInt32LE(d->boolValue ? 1 : 0));
data.append(ByteVector::fromUInt32LE(d->data->boolValue ? 1 : 0));
}
else {
data.append(ByteVector::fromUInt16LE(d->boolValue ? 1 : 0));
data.append(ByteVector::fromUInt16LE(d->data->boolValue ? 1 : 0));
}
break;
case DWordType:
data.append(ByteVector::fromUInt32LE(d->intValue));
data.append(ByteVector::fromUInt32LE(d->data->intValue));
break;
case QWordType:
data.append(ByteVector::fromUInt64LE(d->longLongValue));
data.append(ByteVector::fromUInt64LE(d->data->longLongValue));
break;
case UnicodeType:
data.append(File::renderString(d->stringValue));
data.append(File::renderString(d->data->stringValue));
break;
case BytesType:
if(d->pictureValue.isValid()) {
data.append(d->pictureValue.render());
if(d->data->pictureValue.isValid()) {
data.append(d->data->pictureValue.render());
break;
}
case GuidType:
data.append(d->byteVectorValue);
data.append(d->data->byteVectorValue);
break;
}
if(kind == 0) {
data = File::renderString(name, true) +
ByteVector::fromUInt16LE((int)d->type) +
ByteVector::fromUInt16LE((int)d->data->type) +
ByteVector::fromUInt16LE(data.size()) +
data;
}
else {
ByteVector nameData = File::renderString(name);
data = ByteVector::fromUInt16LE(kind == 2 ? d->language : 0) +
ByteVector::fromUInt16LE(d->stream) +
data = ByteVector::fromUInt16LE(kind == 2 ? d->data->language : 0) +
ByteVector::fromUInt16LE(d->data->stream) +
ByteVector::fromUInt16LE(nameData.size()) +
ByteVector::fromUInt16LE((int)d->type) +
ByteVector::fromUInt16LE((int)d->data->type) +
ByteVector::fromUInt32LE(data.size()) +
nameData +
data;
@ -333,21 +338,21 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
int ASF::Attribute::language() const
{
return d->language;
return d->data->language;
}
void ASF::Attribute::setLanguage(int value)
{
d->language = value;
d->data->language = value;
}
int ASF::Attribute::stream() const
{
return d->stream;
return d->data->stream;
}
void ASF::Attribute::setStream(int value)
{
d->stream = value;
d->data->stream = value;
}

View File

@ -36,7 +36,6 @@ namespace TagLib
namespace ASF
{
class File;
class Picture;
@ -115,17 +114,6 @@ namespace TagLib
*/
ASF::Attribute &operator=(const Attribute &other);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves the contents of \a other into this item.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
ASF::Attribute &operator=(Attribute &&other);
#endif
/*!
* Destroys the attribute.
*/
@ -191,21 +179,17 @@ namespace TagLib
*/
void setStream(int value);
#ifndef DO_NOT_DOCUMENT
/* THIS IS PRIVATE, DON'T TOUCH IT! */
String parse(ASF::File &file, int kind = 0);
#endif
//! Returns the size of the stored data
int dataSize() const;
private:
friend class File;
String parse(ASF::File &file, int kind = 0);
ByteVector render(const String &name, int kind = 0) const;
class AttributePrivate;
RefCountPtr<AttributePrivate> d;
AttributePrivate *d;
};
}

View File

@ -23,24 +23,39 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "asfattribute.h"
#include "asffile.h"
#include "asfpicture.h"
using namespace TagLib;
namespace
{
struct PictureData
{
bool valid;
ASF::Picture::Type type;
String mimeType;
String description;
ByteVector picture;
};
}
class ASF::Picture::PicturePrivate
{
public:
bool valid;
Type type;
String mimeType;
String description;
ByteVector picture;
PicturePrivate()
: data(new PictureData())
{
}
SHARED_PTR<PictureData> data;
};
////////////////////////////////////////////////////////////////////////////////
// Picture class members
////////////////////////////////////////////////////////////////////////////////
@ -48,115 +63,96 @@ public:
ASF::Picture::Picture()
: d(new PicturePrivate())
{
d->valid = true;
d->data->valid = true;
}
ASF::Picture::Picture(const Picture& other)
: d(other.d)
: d(new PicturePrivate(*other.d))
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
ASF::Picture::Picture(Picture &&other)
: d(std::move(other.d))
{
}
#endif
ASF::Picture::~Picture()
{
delete d;
}
bool ASF::Picture::isValid() const
{
return d->valid;
return d->data->valid;
}
String ASF::Picture::mimeType() const
{
return d->mimeType;
return d->data->mimeType;
}
void ASF::Picture::setMimeType(const String &value)
{
d->mimeType = value;
d->data->mimeType = value;
}
ASF::Picture::Type ASF::Picture::type() const
{
return d->type;
return d->data->type;
}
void ASF::Picture::setType(const ASF::Picture::Type& t)
{
d->type = t;
d->data->type = t;
}
String ASF::Picture::description() const
{
return d->description;
return d->data->description;
}
void ASF::Picture::setDescription(const String &desc)
{
d->description = desc;
d->data->description = desc;
}
ByteVector ASF::Picture::picture() const
{
return d->picture;
return d->data->picture;
}
void ASF::Picture::setPicture(const ByteVector &p)
{
d->picture = p;
d->data->picture = p;
}
int ASF::Picture::dataSize() const
{
return static_cast<int>(
9 + (d->mimeType.length() + d->description.length()) * 2 +
d->picture.size());
9 + (d->data->mimeType.length() + d->data->description.length()) * 2 +
d->data->picture.size());
}
ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other)
{
d = other.d;
*d = *other.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
ASF::Picture& ASF::Picture::operator=(ASF::Picture &&other)
{
d = std::move(other.d);
return *this;
}
#endif
ByteVector ASF::Picture::render() const
{
if(!isValid())
return ByteVector::null;
return
ByteVector((char)d->type) +
ByteVector::fromUInt32LE(d->picture.size()) +
ASF::File::renderString(d->mimeType) +
ASF::File::renderString(d->description) +
d->picture;
ByteVector((char)d->data->type) +
ByteVector::fromUInt32LE(d->data->picture.size()) +
ASF::File::renderString(d->data->mimeType) +
ASF::File::renderString(d->data->description) +
d->data->picture;
}
void ASF::Picture::parse(const ByteVector& bytes)
{
d->valid = false;
d->data->valid = false;
if(bytes.size() < 9)
return;
size_t pos = 0;
d->type = (Type)bytes[0]; ++pos;
d->data->type = (Type)bytes[0]; ++pos;
const uint dataLen = bytes.toUInt32LE(pos); pos+=4;
const ByteVector nullStringTerminator(2, 0);
@ -164,27 +160,27 @@ void ASF::Picture::parse(const ByteVector& bytes)
size_t endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos == ByteVector::npos)
return;
d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
d->data->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos+2;
endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos == ByteVector::npos)
return;
d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
d->data->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos+2;
if(dataLen + pos != bytes.size())
return;
d->picture = bytes.mid(pos, dataLen);
d->valid = true;
d->data->picture = bytes.mid(pos, dataLen);
d->data->valid = true;
return;
}
ASF::Picture ASF::Picture::fromInvalid()
{
Picture ret;
ret.d->valid = false;
ret.d->data->valid = false;
return ret;
}

View File

@ -35,6 +35,7 @@ namespace TagLib
{
namespace ASF
{
class Attribute;
//! An ASF attached picture interface implementation
@ -46,7 +47,8 @@ namespace TagLib
* \see Attribute::toPicture()
* \see Attribute::Attribute(const Picture& picture)
*/
class TAGLIB_EXPORT Picture {
class TAGLIB_EXPORT Picture
{
public:
/*!
@ -107,17 +109,6 @@ namespace TagLib
*/
Picture(const Picture& other);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Constructs an picture equivalent to \a other.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
Picture(Picture &&other);
#endif
/*!
* Destroys the picture.
*/
@ -128,17 +119,6 @@ namespace TagLib
*/
Picture& operator=(const Picture& other);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves the contents of \a other into this picture.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
Picture& operator=(Picture &&other);
#endif
/*!
* Returns true if Picture stores valid picture
*/
@ -223,15 +203,14 @@ namespace TagLib
*/
int dataSize() const;
#ifndef DO_NOT_DOCUMENT
/* THIS IS PRIVATE, DON'T TOUCH IT! */
void parse(const ByteVector& );
static Picture fromInvalid();
friend class Attribute;
#endif
private:
friend class Attribute;
void parse(const ByteVector &);
static Picture fromInvalid();
class PicturePrivate;
RefCountPtr<PicturePrivate> d;
PicturePrivate *d;
};
}
}

View File

@ -104,6 +104,7 @@ namespace TagLib {
AudioProperties(ReadStyle style);
private:
// Noncopyable. Derived classes as well.
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);

View File

@ -33,9 +33,10 @@
# include <Shlwapi.h>
#endif
#include <tfile.h>
#include <tstring.h>
#include <tdebug.h>
#include "tfile.h"
#include "tstring.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "fileref.h"
#include "asffile.h"
@ -66,12 +67,12 @@ namespace
ResolverList fileTypeResolvers;
RefCountPtr<File> create(
SHARED_PTR<File> create(
FileName fileName,
bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
RefCountPtr<File> file;
SHARED_PTR<File> file;
for(ResolverConstIterator it = fileTypeResolvers.begin(); it != fileTypeResolvers.end(); ++it)
{
file.reset((*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle));
@ -169,12 +170,12 @@ public:
{
}
FileRefPrivate(RefCountPtr<File> f)
: file(f)
FileRefPrivate(const SHARED_PTR<File> &f)
: file(f)
{
}
RefCountPtr<File> file;
SHARED_PTR<File> file;
};
////////////////////////////////////////////////////////////////////////////////
@ -187,7 +188,8 @@ FileRef::FileRef()
}
FileRef::FileRef(FileName fileName,
bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle)
bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
: d(new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle)))
{
}
@ -198,21 +200,13 @@ FileRef::FileRef(File *file)
}
FileRef::FileRef(const FileRef &ref)
: d(ref.d)
: d(new FileRefPrivate(ref.d->file))
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
FileRef::FileRef(FileRef &&ref)
: d(std::move(ref.d))
{
}
#endif
FileRef::~FileRef()
{
delete d;
}
Tag *FileRef::tag() const
@ -330,26 +324,16 @@ bool FileRef::isNull() const
FileRef &FileRef::operator=(const FileRef &ref)
{
d = ref.d;
*d = *ref.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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;
return (d->file == ref.d->file);
}
bool FileRef::operator!=(const FileRef &ref) const
{
return ref.d->file != d->file;
return (d->file != ref.d->file);
}

View File

@ -143,17 +143,6 @@ namespace TagLib {
*/
FileRef(const FileRef &ref);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Move \a ref into the FileRef.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
FileRef(FileRef &&ref);
#endif
/*!
* Destroys this FileRef instance.
*/
@ -286,17 +275,6 @@ namespace TagLib {
*/
FileRef &operator=(const FileRef &ref);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a ref into this FileRef.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
FileRef &operator=(FileRef &&ref);
#endif
/*!
* Returns true if this FileRef and \a ref point to the same File object.
*/
@ -310,7 +288,7 @@ namespace TagLib {
private:
class FileRefPrivate;
RefCountPtr<FileRefPrivate> d;
FileRefPrivate *d;
};
} // namespace TagLib

View File

@ -199,8 +199,6 @@ namespace TagLib {
PicturePrivate *d;
};
typedef List<Picture> PictureList;
}
}

View File

@ -23,63 +23,66 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "mp4coverart.h"
using namespace TagLib;
namespace
{
struct CoverArtData
{
MP4::CoverArt::Format format;
ByteVector data;
};
}
class MP4::CoverArt::CoverArtPrivate
{
public:
CoverArtPrivate() : format(MP4::CoverArt::JPEG) {}
CoverArtPrivate(Format f, const ByteVector &v)
: data(new CoverArtData())
{
data->format = f;
data->data = v;
}
Format format;
ByteVector data;
SHARED_PTR<CoverArtData> data;
};
MP4::CoverArt::CoverArt(Format format, const ByteVector &data)
: d(new CoverArtPrivate())
: d(new CoverArtPrivate(format, data))
{
d->format = format;
d->data = data;
}
MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d)
MP4::CoverArt::CoverArt(const CoverArt &item)
: d(new CoverArtPrivate(*item.d))
{
}
MP4::CoverArt &
MP4::CoverArt::operator=(const CoverArt &item)
MP4::CoverArt::operator=(const CoverArt &item)
{
d = item.d;
*d = *item.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
MP4::CoverArt &
MP4::CoverArt::operator=(CoverArt &&item)
{
d = std::move(item.d);
return *this;
}
#endif
MP4::CoverArt::~CoverArt()
{
delete d;
}
MP4::CoverArt::Format
MP4::CoverArt::format() const
{
return d->format;
return d->data->format;
}
ByteVector
MP4::CoverArt::data() const
{
return d->data;
return d->data->data;
}

View File

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

View File

@ -23,10 +23,14 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "config.h"
#include <cstdio>
#include <cstdarg>
#include <taglib.h>
#include <tdebug.h>
#include "taglib.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "mp4item.h"
using namespace TagLib;
@ -59,234 +63,227 @@ namespace
return String(buf);
}
struct ItemData
{
bool valid;
MP4::AtomDataType atomDataType;
MP4::Item::ItemType type;
union {
bool m_bool;
int m_int;
MP4::Item::IntPair m_intPair;
uchar m_byte;
uint m_uint;
long long m_longlong;
};
StringList m_stringList;
ByteVectorList m_byteVectorList;
MP4::CoverArtList m_coverArtList;
};
}
class MP4::Item::ItemPrivate
{
public:
ItemPrivate() : valid(true), atomDataType(MP4::TypeUndefined), type(MP4::Item::TypeUndefined) {}
ItemPrivate()
: data(new ItemData())
{
data->valid = true;
data->atomDataType = MP4::TypeUndefined;
data->type = MP4::Item::TypeUndefined;
}
bool valid;
AtomDataType atomDataType;
ItemType type;
union {
bool m_bool;
int m_int;
IntPair m_intPair;
uchar m_byte;
uint m_uint;
long long m_longlong;
};
StringList m_stringList;
ByteVectorList m_byteVectorList;
MP4::CoverArtList m_coverArtList;
SHARED_PTR<ItemData> data;
};
MP4::Item::Item()
: d(new ItemPrivate())
{
d->valid = false;
d->data->valid = false;
}
MP4::Item::Item(const Item &item)
: d(item.d)
: d(new ItemPrivate(*item.d))
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
MP4::Item::Item(Item &&item)
: d(std::move(item.d))
{
}
#endif
MP4::Item &
MP4::Item::operator=(const Item &item)
{
d = item.d;
*d = *item.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
MP4::Item &
MP4::Item::operator=(Item &&item)
{
d = std::move(item.d);
return *this;
}
#endif
MP4::Item::~Item()
{
delete d;
}
MP4::Item::Item(bool value)
: d(new ItemPrivate())
{
d->m_bool = value;
d->type = TypeBool;
d->data->m_bool = value;
d->data->type = TypeBool;
}
MP4::Item::Item(int value)
: d(new ItemPrivate())
{
d->m_int = value;
d->type = TypeInt;
d->data->m_int = value;
d->data->type = TypeInt;
}
MP4::Item::Item(uchar value)
: d(new ItemPrivate())
{
d->m_byte = value;
d->type = TypeByte;
d->data->m_byte = value;
d->data->type = TypeByte;
}
MP4::Item::Item(uint value)
: d(new ItemPrivate())
{
d->m_uint = value;
d->type = TypeUInt;
d->data->m_uint = value;
d->data->type = TypeUInt;
}
MP4::Item::Item(long long value)
: d(new ItemPrivate())
{
d->m_longlong = value;
d->type = TypeLongLong;
d->data->m_longlong = value;
d->data->type = TypeLongLong;
}
MP4::Item::Item(int value1, int value2)
: d(new ItemPrivate())
{
d->m_intPair.first = value1;
d->m_intPair.second = value2;
d->type = TypeIntPair;
d->data->m_intPair.first = value1;
d->data->m_intPair.second = value2;
d->data->type = TypeIntPair;
}
MP4::Item::Item(const ByteVectorList &value)
: d(new ItemPrivate())
{
d->m_byteVectorList = value;
d->type = TypeByteVectorList;
d->data->m_byteVectorList = value;
d->data->type = TypeByteVectorList;
}
MP4::Item::Item(const StringList &value)
: d(new ItemPrivate())
{
d->m_stringList = value;
d->type = TypeStringList;
d->data->m_stringList = value;
d->data->type = TypeStringList;
}
MP4::Item::Item(const MP4::CoverArtList &value)
: d(new ItemPrivate())
{
d->m_coverArtList = value;
d->type = TypeCoverArtList;
d->data->m_coverArtList = value;
d->data->type = TypeCoverArtList;
}
void MP4::Item::setAtomDataType(MP4::AtomDataType type)
{
d->atomDataType = type;
d->data->atomDataType = type;
}
MP4::AtomDataType MP4::Item::atomDataType() const
{
return d->atomDataType;
return d->data->atomDataType;
}
bool
MP4::Item::toBool() const
{
return d->m_bool;
return d->data->m_bool;
}
int
MP4::Item::toInt() const
{
return d->m_int;
return d->data->m_int;
}
uchar
MP4::Item::toByte() const
{
return d->m_byte;
return d->data->m_byte;
}
TagLib::uint
MP4::Item::toUInt() const
{
return d->m_uint;
return d->data->m_uint;
}
long long
MP4::Item::toLongLong() const
{
return d->m_longlong;
return d->data->m_longlong;
}
MP4::Item::IntPair
MP4::Item::toIntPair() const
{
return d->m_intPair;
return d->data->m_intPair;
}
StringList
MP4::Item::toStringList() const
{
return d->m_stringList;
return d->data->m_stringList;
}
ByteVectorList
MP4::Item::toByteVectorList() const
{
return d->m_byteVectorList;
return d->data->m_byteVectorList;
}
MP4::CoverArtList
MP4::Item::toCoverArtList() const
{
return d->m_coverArtList;
return d->data->m_coverArtList;
}
bool
MP4::Item::isValid() const
{
return d->valid;
return d->data->valid;
}
String
MP4::Item::toString() const
{
StringList desc;
switch (d->type) {
switch (d->data->type) {
case TypeBool:
return d->m_bool ? "true" : "false";
return d->data->m_bool ? "true" : "false";
case TypeInt:
return format("%d", d->m_int);
return format("%d", d->data->m_int);
case TypeIntPair:
return format("%d/%d", d->m_intPair.first, d->m_intPair.second);
return format("%d/%d", d->data->m_intPair.first, d->data->m_intPair.second);
case TypeByte:
return format("%d", d->m_byte);
return format("%d", d->data->m_byte);
case TypeUInt:
return format("%u", d->m_uint);
return format("%u", d->data->m_uint);
case TypeLongLong:
return format("%lld", d->m_longlong);
return format("%lld", d->data->m_longlong);
case TypeStringList:
return d->m_stringList.toString(" / ");
return d->data->m_stringList.toString(" / ");
case TypeByteVectorList:
for(TagLib::uint i = 0; i < d->m_byteVectorList.size(); i++) {
for(TagLib::uint i = 0; i < d->data->m_byteVectorList.size(); i++) {
desc.append(format(
"[%d bytes of data]", static_cast<int>(d->m_byteVectorList[i].size())));
"[%d bytes of data]", static_cast<int>(d->data->m_byteVectorList[i].size())));
}
return desc.toString(", ");
case TypeCoverArtList:
for(TagLib::uint i = 0; i < d->m_coverArtList.size(); i++) {
for(TagLib::uint i = 0; i < d->data->m_coverArtList.size(); i++) {
desc.append(format(
"[%d bytes of data]", static_cast<int>(d->m_coverArtList[i].data().size())));
"[%d bytes of data]", static_cast<int>(d->data->m_coverArtList[i].data().size())));
}
return desc.toString(", ");
case TypeUndefined:

View File

@ -56,14 +56,8 @@ namespace TagLib {
Item();
Item(const Item &item);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
Item(Item &&item);
#endif
Item &operator=(const Item &item);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
Item &operator=(Item &&item);
#endif
~Item();
Item(int value);
@ -97,7 +91,7 @@ namespace TagLib {
private:
class ItemPrivate;
RefCountPtr<ItemPrivate> d;
ItemPrivate *d;
};
}

View File

@ -48,10 +48,16 @@ using namespace ID3v2;
class ID3v2::Tag::TagPrivate
{
public:
TagPrivate() : file(0), tagOffset(-1), extendedHeader(0), footer(0), paddingSize(0)
TagPrivate()
: file(0)
, tagOffset(-1)
, extendedHeader(0)
, footer(0)
, paddingSize(0)
{
frameList.setAutoDelete(true);
}
~TagPrivate()
{
delete extendedHeader;

View File

@ -25,41 +25,51 @@
#include <bitset>
#include <tbytevector.h>
#include <tstring.h>
#include <tdebug.h>
#include "tstring.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "mpegheader.h"
using namespace TagLib;
namespace
{
struct HeaderData
{
bool isValid;
MPEG::Header::Version version;
int layer;
bool protectionEnabled;
int bitrate;
int sampleRate;
bool isPadded;
MPEG::Header::ChannelMode channelMode;
bool isCopyrighted;
bool isOriginal;
int frameLength;
int samplesPerFrame;
};
}
class MPEG::Header::HeaderPrivate
{
public:
HeaderPrivate() :
isValid(false),
version(Version1),
layer(0),
protectionEnabled(false),
sampleRate(0),
isPadded(false),
channelMode(Stereo),
isCopyrighted(false),
isOriginal(false),
frameLength(0),
samplesPerFrame(0) {}
HeaderPrivate()
: data(new HeaderData())
{
data->isValid = false;
data->layer = 0;
data->version = Version1;
data->protectionEnabled = false;
data->sampleRate = 0;
data->isPadded = false;
data->channelMode = Stereo;
data->isCopyrighted = false;
data->isOriginal = false;
data->frameLength = 0;
data->samplesPerFrame = 0;
}
bool isValid;
Version version;
int layer;
bool protectionEnabled;
int bitrate;
int sampleRate;
bool isPadded;
ChannelMode channelMode;
bool isCopyrighted;
bool isOriginal;
int frameLength;
int samplesPerFrame;
SHARED_PTR<HeaderData> data;
};
////////////////////////////////////////////////////////////////////////////////
@ -73,99 +83,80 @@ MPEG::Header::Header(const ByteVector &data)
}
MPEG::Header::Header(const Header &h)
: d(h.d)
: d(new HeaderPrivate(*h.d))
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
MPEG::Header::Header(Header &&h)
: d(std::move(h.d))
{
}
#endif
MPEG::Header::~Header()
{
}
bool MPEG::Header::isValid() const
{
return d->isValid;
return d->data->isValid;
}
MPEG::Header::Version MPEG::Header::version() const
{
return d->version;
return d->data->version;
}
int MPEG::Header::layer() const
{
return d->layer;
return d->data->layer;
}
bool MPEG::Header::protectionEnabled() const
{
return d->protectionEnabled;
return d->data->protectionEnabled;
}
int MPEG::Header::bitrate() const
{
return d->bitrate;
return d->data->bitrate;
}
int MPEG::Header::sampleRate() const
{
return d->sampleRate;
return d->data->sampleRate;
}
bool MPEG::Header::isPadded() const
{
return d->isPadded;
return d->data->isPadded;
}
MPEG::Header::ChannelMode MPEG::Header::channelMode() const
{
return d->channelMode;
return d->data->channelMode;
}
bool MPEG::Header::isCopyrighted() const
{
return d->isCopyrighted;
return d->data->isCopyrighted;
}
bool MPEG::Header::isOriginal() const
{
return d->isOriginal;
return d->data->isOriginal;
}
int MPEG::Header::frameLength() const
{
return d->frameLength;
return d->data->frameLength;
}
int MPEG::Header::samplesPerFrame() const
{
return d->samplesPerFrame;
return d->data->samplesPerFrame;
}
MPEG::Header &MPEG::Header::operator=(const Header &h)
{
d = h.d;
*d = *h.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
MPEG::Header &MPEG::Header::operator=(Header &&h)
{
d = std::move(h.d);
return *this;
}
#endif
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
@ -189,22 +180,22 @@ void MPEG::Header::parse(const ByteVector &data)
// Set the MPEG version
if(!flags[20] && !flags[19])
d->version = Version2_5;
d->data->version = Version2_5;
else if(flags[20] && !flags[19])
d->version = Version2;
d->data->version = Version2;
else if(flags[20] && flags[19])
d->version = Version1;
d->data->version = Version1;
// Set the MPEG layer
if(!flags[18] && flags[17])
d->layer = 3;
d->data->layer = 3;
else if(flags[18] && !flags[17])
d->layer = 2;
d->data->layer = 2;
else if(flags[18] && flags[17])
d->layer = 1;
d->data->layer = 1;
d->protectionEnabled = !flags[16];
d->data->protectionEnabled = !flags[16];
// Set the bitrate
@ -221,15 +212,15 @@ void MPEG::Header::parse(const ByteVector &data)
}
};
const int versionIndex = d->version == Version1 ? 0 : 1;
const int layerIndex = d->layer > 0 ? d->layer - 1 : 0;
const int versionIndex = d->data->version == Version1 ? 0 : 1;
const int layerIndex = d->data->layer > 0 ? d->data->layer - 1 : 0;
// The bitrate index is encoded as the first 4 bits of the 3rd byte,
// i.e. 1111xxxx
int i = uchar(data[2]) >> 4;
d->bitrate = bitrates[versionIndex][layerIndex][i];
d->data->bitrate = bitrates[versionIndex][layerIndex][i];
// Set the sample rate
@ -243,9 +234,9 @@ void MPEG::Header::parse(const ByteVector &data)
i = uchar(data[2]) >> 2 & 0x03;
d->sampleRate = sampleRates[d->version][i];
d->data->sampleRate = sampleRates[d->data->version][i];
if(d->sampleRate == 0) {
if(d->data->sampleRate == 0) {
debug("MPEG::Header::parse() -- Invalid sample rate.");
return;
}
@ -253,20 +244,20 @@ void MPEG::Header::parse(const ByteVector &data)
// The channel mode is encoded as a 2 bit value at the end of the 3nd byte,
// i.e. xxxxxx11
d->channelMode = ChannelMode((uchar(data[3]) & 0xC0) >> 6);
d->data->channelMode = ChannelMode((uchar(data[3]) & 0xC0) >> 6);
// TODO: Add mode extension for completeness
d->isOriginal = flags[2];
d->isCopyrighted = flags[3];
d->isPadded = flags[9];
d->data->isOriginal = flags[2];
d->data->isCopyrighted = flags[3];
d->data->isPadded = flags[9];
// Calculate the frame length
if(d->layer == 1)
d->frameLength = 24000 * 2 * d->bitrate / d->sampleRate + int(d->isPadded);
if(d->data->layer == 1)
d->data->frameLength = 24000 * 2 * d->data->bitrate / d->data->sampleRate + int(d->data->isPadded);
else
d->frameLength = 72000 * d->bitrate / d->sampleRate + int(d->isPadded);
d->data->frameLength = 72000 * d->data->bitrate / d->data->sampleRate + int(d->data->isPadded);
// Samples per frame
@ -277,9 +268,9 @@ void MPEG::Header::parse(const ByteVector &data)
{ 1152, 576 } // Layer III
};
d->samplesPerFrame = samplesPerFrame[layerIndex][versionIndex];
d->data->samplesPerFrame = samplesPerFrame[layerIndex][versionIndex];
// Now that we're done parsing, set this to be a valid frame.
d->isValid = true;
d->data->isValid = true;
}

View File

@ -27,7 +27,6 @@
#define TAGLIB_MPEGHEADER_H
#include "taglib_export.h"
#include "tsmartptr.h"
namespace TagLib {
@ -57,17 +56,6 @@ namespace TagLib {
*/
Header(const Header &h);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a h into this Header.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
Header(Header &&h);
#endif
/*!
* Destroys this Header instance.
*/
@ -166,22 +154,11 @@ namespace TagLib {
*/
Header &operator=(const Header &h);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a h into this Header.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
Header &operator=(Header &&h);
#endif
private:
void parse(const ByteVector &data);
class HeaderPrivate;
RefCountPtr<HeaderPrivate> d;
HeaderPrivate *d;
};
}
}

View File

@ -40,7 +40,6 @@ public:
sampleWidth(0),
sampleFrames(0)
{
}
int length;
@ -64,11 +63,12 @@ RIFF::AIFF::AudioProperties::AudioProperties(const ByteVector &data, ReadStyle s
RIFF::AIFF::AudioProperties::~AudioProperties()
{
delete d;
}
bool RIFF::AIFF::AudioProperties::isNull() const
{
return (static_cast<bool>(d));
return (d == 0);
}
int RIFF::AIFF::AudioProperties::length() const

View File

@ -73,7 +73,7 @@ namespace TagLib {
void read(const ByteVector &data);
class PropertiesPrivate;
RefCountPtr<PropertiesPrivate> d;
PropertiesPrivate *d;
};
}
}

View File

@ -1,17 +1,3 @@
/* taglib_config.h. Generated by cmake from taglib_config.h.cmake */
/* The variables below indicate the compiler capability. */
/* DO NOT MODIFY them manually. It may break the binary compatibility. */
/* Defined if your compiler supports the move semantics */
#cmakedefine TAGLIB_USE_MOVE_SEMANTICS 1
/* Defined if your compiler supports shared_ptr */
#cmakedefine TAGLIB_USE_STD_SHARED_PTR 1 // #include <memory> / std::shared_ptr<T>
#cmakedefine TAGLIB_USE_TR1_SHARED_PTR 1 // #include <tr1/memory> / std::tr1::shared_ptr<T>
#cmakedefine TAGLIB_USE_BOOST_SHARED_PTR 1 // #include <boost/shared_ptr.hpp> / boost::shared_ptr<T>
/* Defined if your compiler supports unique_ptr or scoped_ptr */
#cmakedefine TAGLIB_USE_STD_UNIQUE_PTR 1 // #include <memory> / std::unique_ptr<T>
#cmakedefine TAGLIB_USE_BOOST_SCOPED_PTR 1 // #include <boost/scoped_ptr.hpp> / boost::scoped_ptr<T>

View File

@ -26,7 +26,7 @@
#include "tagunion.h"
#include "tstringlist.h"
#include "tpropertymap.h"
#include "tsmartptr.h"
#define stringUnion(method) \
for(size_t j = 0; j < COUNT; ++j) { \
@ -56,7 +56,7 @@ namespace TagLib
class TagUnion<COUNT>::TagUnionPrivate
{
public:
NonRefCountPtr<Tag> tags[COUNT];
SCOPED_PTR<Tag> tags[COUNT];
};
template <size_t COUNT>
@ -68,6 +68,7 @@ namespace TagLib
template <size_t COUNT>
TagUnion<COUNT>::~TagUnion()
{
delete d;
}
template <size_t COUNT>

View File

@ -26,6 +26,8 @@
#ifndef TAGLIB_TAGUNION_H
#define TAGLIB_TAGUNION_H
// This file is not a part of TagLib public interface. This is not installed.
#include "tag.h"
#ifndef DO_NOT_DOCUMENT
@ -87,7 +89,7 @@ namespace TagLib {
private:
class TagUnionPrivate;
NonRefCountPtr<TagUnionPrivate> d;
TagUnionPrivate *d;
};
// If you add a new typedef here, add a corresponding explicit instantiation

View File

@ -41,8 +41,9 @@
# include <sys/endian.h>
#endif
#include <tstring.h>
#include <tdebug.h>
#include "tstring.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "tbytevector.h"
// This is a bit ugly to keep writing over and over again.
@ -366,20 +367,13 @@ public:
{
}
ByteVectorPrivate(RefCountPtr<ByteVectorPrivate> d, size_t o, size_t l)
ByteVectorPrivate(ByteVectorPrivate* d, size_t o, size_t l)
: data(d->data)
, offset(d->offset + o)
, length(l)
{
}
ByteVectorPrivate(const std::vector<char> &v, size_t o, size_t l)
: data(new std::vector<char>(v.begin() + o, v.begin() + o + l))
, offset(0)
, length(l)
{
}
ByteVectorPrivate(size_t l, char c)
: data(new std::vector<char>(l, c))
, offset(0)
@ -406,15 +400,7 @@ public:
{
}
ByteVectorPrivate &operator=(const ByteVectorPrivate &x)
{
if(&x != this)
data = x.data;
return *this;
}
RefCountPtr<std::vector<char> > data;
SHARED_PTR<std::vector<char> > data;
size_t offset;
size_t length;
};
@ -480,7 +466,7 @@ ByteVector::ByteVector(size_t size, char value)
}
ByteVector::ByteVector(const ByteVector &v)
: d(v.d)
: d(new ByteVectorPrivate(*v.d))
{
}
@ -489,15 +475,6 @@ ByteVector::ByteVector(const ByteVector &v, size_t offset, size_t length)
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
ByteVector::ByteVector(ByteVector &&v)
: d(std::move(v.d))
{
}
#endif
ByteVector::ByteVector(char c)
: d(new ByteVectorPrivate(1, c))
{
@ -515,6 +492,7 @@ ByteVector::ByteVector(const char *data)
ByteVector::~ByteVector()
{
delete d;
}
ByteVector &ByteVector::setData(const char *data, size_t length)
@ -641,8 +619,8 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
}
// new private data of appropriate size:
ByteVectorPrivate *newData = new ByteVectorPrivate(newSize, 0);
char *target = DATA(newData);
ByteVectorPrivate newData(newSize, '\0');
char *target = &(*newData.data)[0];
const char *source = DATA(d);
// copy modified data into new private data:
@ -662,7 +640,7 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
}
// replace private data:
d.reset(newData);
*d = newData;
return *this;
}
@ -708,7 +686,7 @@ ByteVector &ByteVector::append(char c)
ByteVector &ByteVector::clear()
{
detach();
*this = ByteVector();
*d = *ByteVector::null.d;
return *this;
}
@ -1071,30 +1049,20 @@ ByteVector ByteVector::operator+(const ByteVector &v) const
ByteVector &ByteVector::operator=(const ByteVector &v)
{
d = v.d;
*d = *v.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
ByteVector &ByteVector::operator=(ByteVector &&v)
{
d = std::move(v.d);
return *this;
}
#endif
ByteVector &ByteVector::operator=(char c)
{
d = ByteVector(c).d;
*this = ByteVector(c);
return *this;
}
ByteVector &ByteVector::operator=(const char *data)
{
d = ByteVector(data).d;
*this = ByteVector(data);
return *this;
}
@ -1119,9 +1087,6 @@ ByteVector ByteVector::toHex() const
void ByteVector::detach()
{
d->detach();
if(!d.unique())
d.reset(new ByteVectorPrivate(*(d->data), d->offset, d->length));
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,6 @@
#include "taglib_export.h"
#include "taglib.h"
#include "tsmartptr.h"
#include <vector>
#include <iostream>
@ -68,17 +67,6 @@ namespace TagLib {
*/
ByteVector(const ByteVector &v);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Constructs a byte vector equivalent to \a v.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
ByteVector(ByteVector &&v);
#endif
/*!
* Constructs a byte vector that is a copy of \a v.
*/
@ -502,17 +490,6 @@ namespace TagLib {
*/
ByteVector &operator=(const ByteVector &v);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a v into this ByteVector.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
ByteVector &operator=(ByteVector &&v);
#endif
/*!
* Copies ByteVector \a v.
*/
@ -551,7 +528,7 @@ namespace TagLib {
private:
class ByteVectorPrivate;
RefCountPtr<ByteVectorPrivate> d;
ByteVectorPrivate *d;
};
/*!

View File

@ -27,6 +27,7 @@
#include "tfilestream.h"
#include "tstring.h"
#include "tdebug.h"
#include "tsmartptr.h"
#include "tpropertymap.h"
#include "audioproperties.h"
@ -65,7 +66,7 @@ public:
}
private:
NonRefCountPtr<IOStream> p;
SCOPED_PTR<IOStream> p;
};
// FilePrivate implementation which doesn't take ownership of the stream.
@ -93,6 +94,7 @@ private:
File::~File()
{
delete d;
}
FileName File::name() const

View File

@ -278,13 +278,14 @@ namespace TagLib {
static size_t bufferSize();
private:
// Noncopyable. Derived classes as well.
File(const File &);
File &operator=(const File &);
class FilePrivateBase;
class ManagedFilePrivate;
class UnmanagedFilePrivate;
NonRefCountPtr<FilePrivateBase> d;
FilePrivateBase *d;
};
}

View File

@ -194,6 +194,8 @@ FileStream::~FileStream()
{
if(isOpen())
closeFile(d->file);
delete d;
}
FileName FileStream::name() const

View File

@ -142,7 +142,7 @@ namespace TagLib {
private:
class FileStreamPrivate;
NonRefCountPtr<FileStreamPrivate> d;
FileStreamPrivate *d;
};
}

View File

@ -158,6 +158,8 @@ namespace TagLib {
virtual void truncate(offset_t length) = 0;
private:
// Noncopyable. Derived classes as well.
IOStream(const IOStream &);
IOStream &operator=(const IOStream &);
};

View File

@ -27,7 +27,6 @@
#define TAGLIB_LIST_H
#include "taglib.h"
#include "tsmartptr.h"
#include <list>
namespace TagLib {
@ -70,17 +69,6 @@ namespace TagLib {
*/
List(const List<T> &l);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a l into this List.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
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.
@ -135,26 +123,6 @@ namespace TagLib {
*/
List<T> &append(const List<T> &l);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Appends \a item to the end of the list and returns a reference to the
* list.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
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.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
List<T> &append(List<T> &&l);
#endif
/*!
* Prepends \a item to the beginning list and returns a reference to the
* list.
@ -167,26 +135,6 @@ namespace TagLib {
*/
List<T> &prepend(const List<T> &l);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Prepends \a item to the beginning list and returns a reference to the
* list.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
List<T> &prepend(T &&item);
/*!
* Prepends all of the items in \a l to the beginning list and returns a
* reference to the list.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
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.
@ -275,17 +223,6 @@ namespace TagLib {
*/
List<T> &operator=(const List<T> &l);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a l into this List.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
List<T> &operator=(List<T> &&l);
#endif
/*!
* Compares this list with \a l and returns true if all of the elements are
* the same.
@ -308,7 +245,7 @@ namespace TagLib {
private:
#ifndef DO_NOT_DOCUMENT
template <class TP> class ListPrivate;
RefCountPtr<ListPrivate<T> > d;
ListPrivate<T> *d;
#endif
};

View File

@ -1,3 +1,4 @@
/***************************************************************************
copyright : (C) 2002 - 2008 by Scott Wheeler
email : wheeler@kde.org
@ -23,8 +24,8 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <config.h>
#include <algorithm>
#include "trefcounter.h"
namespace TagLib {
@ -36,34 +37,30 @@ namespace TagLib {
// template specialization. This is implemented in such a way that calling
// setAutoDelete() on non-pointer types will simply have no effect.
// A base for the generic and specialized private class types. New
// non-templatized members should be added here.
class ListPrivateBase
{
public:
ListPrivateBase() : autoDelete(false) {}
bool autoDelete;
};
// A generic implementation
template <class T>
template <class TP> class List<T>::ListPrivate : public ListPrivateBase
template <class TP> class List<T>::ListPrivate : public RefCounter
{
public:
ListPrivate() : ListPrivateBase() {}
ListPrivate(const std::list<TP> &l) : ListPrivateBase(), list(l) {}
ListPrivate()
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
ListPrivate(const std::list<TP> &l)
: list(l)
{
}
ListPrivate(std::list<TP> &&l) : ListPrivateBase(), list(l) {}
#endif
void clear() {
void clear()
{
std::list<TP>().swap(list);
}
void setAutoDelete(bool)
{
}
std::list<TP> list;
};
@ -71,38 +68,49 @@ public:
// setAutoDelete() functionality.
template <class T>
template <class TP> class List<T>::ListPrivate<TP *> : public ListPrivateBase
template <class TP> class List<T>::ListPrivate<TP *> : public RefCounter
{
public:
ListPrivate() : ListPrivateBase() {}
ListPrivate(const std::list<TP *> &l) : ListPrivateBase(), list(l) {}
ListPrivate()
: autoDelete(false)
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
ListPrivate(const std::list<TP *> &l)
: list(l)
, autoDelete(false)
{
}
ListPrivate(std::list<TP *> &&l) : ListPrivateBase(), list(l) {}
#endif
~ListPrivate() {
~ListPrivate()
{
deletePointers();
}
void clear() {
void clear()
{
deletePointers();
std::list<TP *>().swap(list);
}
void setAutoDelete(bool del)
{
autoDelete = del;
}
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;
void deletePointers()
{
if(autoDelete) {
typename std::list<TP *>::const_iterator it = list.begin();
for(; it != list.end(); ++it)
delete *it;
}
}
bool autoDelete;
};
////////////////////////////////////////////////////////////////////////////////
@ -111,29 +119,22 @@ private:
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)
: d(l.d)
{
d->ref();
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
template <class T>
List<T>::List(List<T> &&l)
: d(std::move(l.d))
{
}
#endif
template <class T>
List<T>::~List()
{
if(d->deref())
delete d;
}
template <class T>
@ -198,29 +199,6 @@ List<T> &List<T>::append(const List<T> &l)
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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)
{
@ -233,33 +211,10 @@ template <class T>
List<T> &List<T>::prepend(const List<T> &l)
{
detach();
d->list.insert(d->list.begin(), l.d->list.begin(), l.d->list.end());
d->list.insert(d->list.begin(), l.begin(), l.end());
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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(typename std::list<T>::reverse_iterator it = l.d->list.rbegin(); it != l.d->list.rend(); ++it)
d->list.push_front(std::move(*it));
return *this;
}
#endif
template <class T>
List<T> &List<T>::clear()
{
@ -329,7 +284,7 @@ const T &List<T>::back() const
template <class T>
void List<T>::setAutoDelete(bool autoDelete)
{
d->autoDelete = autoDelete;
d->setAutoDelete(autoDelete);
}
template <class T>
@ -364,21 +319,16 @@ const T &List<T>::operator[](size_t i) const
template <class T>
List<T> &List<T>::operator=(const List<T> &l)
{
if(&l == this)
return *this;
if(d->deref())
delete d;
d = l.d;
d->ref();
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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
{
@ -398,8 +348,11 @@ bool List<T>::operator!=(const List<T> &l) const
template <class T>
void List<T>::detach()
{
if(!d.unique())
d.reset(new ListPrivate<T>(d->list));
if(!d->unique()) {
d->deref();
d = new ListPrivate<T>(d->list);
}
}
} // namespace TagLib

View File

@ -27,7 +27,6 @@
#define TAGLIB_MAP_H
#include "taglib.h"
#include "tsmartptr.h"
#include <map>
namespace TagLib {
@ -42,7 +41,7 @@ namespace TagLib {
template <class Key, class T> class Map
{
public:
private:
#ifndef DO_NOT_DOCUMENT
#ifdef WANT_CLASS_INSTANTIATION_OF_MAP
// Some STL implementations get snippy over the use of the
@ -53,14 +52,18 @@ namespace TagLib {
// Not all the specializations of Map can use the class keyword
// (when T is not actually a class type), so don't apply this
// generally.
typedef typename std::map<class Key, class T>::iterator Iterator;
typedef typename std::map<class Key, class T>::const_iterator ConstIterator;
typedef std::map<class Key, class T> MapType;
#else
typedef typename std::map<Key, T>::iterator Iterator;
typedef typename std::map<Key, T>::const_iterator ConstIterator;
typedef std::map<Key, T> MapType;
#endif
#endif
public:
#ifndef DO_NOT_DOCUMENT
typedef typename MapType::iterator Iterator;
typedef typename MapType::const_iterator ConstIterator;
#endif
/*!
* Constructs an empty Map.
*/
@ -73,17 +76,6 @@ namespace TagLib {
*/
Map(const Map<Key, T> &m);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a m into this Map.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
Map(Map<Key, T> &&m);
#endif
/*!
* Destroys this instance of the Map.
*/
@ -119,18 +111,6 @@ namespace TagLib {
*/
Map<Key, T> &insert(const Key &key, const T &value);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Inserts \a value under \a key in the map. If a value for \a key already
* exists it will be overwritten.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
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.
@ -197,17 +177,6 @@ namespace TagLib {
*/
Map<Key, T> &operator=(const Map<Key, T> &m);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a m into this Map.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
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
@ -219,8 +188,7 @@ namespace TagLib {
private:
#ifndef DO_NOT_DOCUMENT
template <class KeyP, class TP> class MapPrivate;
RefCountPtr<MapPrivate<Key, T> > d;
MapPrivate<Key, T> *d;
#endif
};
}

View File

@ -23,6 +23,8 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "trefcounter.h"
namespace TagLib {
////////////////////////////////////////////////////////////////////////////////
@ -31,44 +33,21 @@ namespace TagLib {
template <class Key, class T>
template <class KeyP, class TP>
class Map<Key, T>::MapPrivate
class Map<Key, T>::MapPrivate : public RefCounter
{
public:
MapPrivate() {}
#ifdef WANT_CLASS_INSTANTIATION_OF_MAP
MapPrivate(const std::map<class KeyP, class TP> &m) : RefCounter(), map(m) {}
# ifdef TAGLIB_USE_MOVE_SEMANTICS
MapPrivate(std::map<class KeyP, class TP> &&m) : RefCounter(), map(m) {}
# endif
void clear() {
std::map<class KeyP, class TP>().swap(map);
MapPrivate()
: RefCounter()
{
}
std::map<class KeyP, class TP> map;
#else
MapPrivate(const std::map<KeyP, TP>& m) : map(m) {}
# ifdef TAGLIB_USE_MOVE_SEMANTICS
MapPrivate(std::map<KeyP, TP> &&m) : map(m) {}
# endif
void clear() {
std::map<KeyP, TP>().swap(map);
MapPrivate(const MapType &m)
: RefCounter()
, map(m)
{
}
std::map<KeyP, TP> map;
#endif
MapType map;
};
template <class Key, class T>
@ -78,24 +57,16 @@ Map<Key, T>::Map()
}
template <class Key, class T>
Map<Key, T>::Map(const Map<Key, T> &m)
: d(m.d)
Map<Key, T>::Map(const Map<Key, T> &m) : d(m.d)
{
d->ref();
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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()
{
if(d->deref())
delete d;
}
template <class Key, class T>
@ -132,18 +103,6 @@ Map<Key, T> &Map<Key, T>::insert(const Key &key, const T &value)
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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()
{
@ -217,21 +176,16 @@ 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)
{
if(&m == this)
return *this;
if(d->deref())
delete(d);
d = m.d;
d->ref();
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
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
////////////////////////////////////////////////////////////////////////////////
@ -239,8 +193,12 @@ Map<Key, T> &Map<Key, T>::operator=(Map<Key, T> &&m)
template <class Key, class T>
void Map<Key, T>::detach()
{
if(!d.unique())
d.reset(new MapPrivate<Key, T>(d->map));
if(!d->unique()) {
d->deref();
d = new MapPrivate<Key, T>(d->map);
}
}
} // namespace TagLib

View File

@ -23,14 +23,8 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "taglib_config.h"
#if !defined(TAGLIB_USE_STD_SHARED_PTR) \
&& !defined(TAGLIB_USE_TR1_SHARED_PTR) \
&& !defined(TAGLIB_USE_BOOST_SHARED_PTR)
#include "config.h"
#include "tsmartptr.h"
#include "trefcounter.h"
#if defined(HAVE_STD_ATOMIC)
# include <atomic>
@ -72,10 +66,10 @@
namespace TagLib
{
class CounterBase::CounterBasePrivate
class RefCounter::RefCounterPrivate
{
public:
CounterBasePrivate()
RefCounterPrivate()
: refCount(1)
{
}
@ -83,33 +77,28 @@ namespace TagLib
volatile ATOMIC_INT refCount;
};
CounterBase::CounterBase()
: d(new CounterBasePrivate())
RefCounter::RefCounter()
: d(new RefCounterPrivate())
{
}
CounterBase::~CounterBase()
RefCounter::~RefCounter()
{
delete d;
}
void CounterBase::addref()
{
void RefCounter::ref()
{
ATOMIC_INC(d->refCount);
}
void CounterBase::release()
{
if(ATOMIC_DEC(d->refCount) == 0) {
dispose();
delete this;
}
bool RefCounter::deref()
{
return (ATOMIC_DEC(d->refCount) == 0);
}
long CounterBase::use_count() const
{
return static_cast<long>(d->refCount);
bool RefCounter::unique() const
{
return (d->refCount == 1);
}
}
#endif

View File

@ -0,0 +1,54 @@
/***************************************************************************
copyright : (C) 2013 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_REFCOUNTER_H
#define TAGLIB_REFCOUNTER_H
#include "taglib.h"
#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
/*!
* \warning This <b>is not</b> part of the TagLib public API!
*/
namespace TagLib
{
class RefCounter
{
public:
RefCounter();
virtual ~RefCounter();
void ref();
bool deref();
bool unique() const;
private:
class RefCounterPrivate;
RefCounterPrivate *d;
};
}
#endif // DO_NOT_DOCUMENT
#endif

View File

@ -26,179 +26,64 @@
#ifndef TAGLIB_SMARTPTR_H
#define TAGLIB_SMARTPTR_H
#include "taglib_config.h"
#include <algorithm>
// This file is not a part of TagLib public interface. This is not installed.
#if defined(TAGLIB_USE_STD_SHARED_PTR)
# include <memory>
#elif defined(TAGLIB_USE_TR1_SHARED_PTR)
# include <tr1/memory>
#elif defined(TAGLIB_USE_BOOST_SHARED_PTR)
# include <boost/shared_ptr.hpp>
#endif
#if defined(TAGLIB_USE_STD_UNIQUE_PTR)
# include <memory>
#elif defined(TAGLIB_USE_BOOST_SCOPED_PTR)
# include <boost/scoped_ptr.hpp>
#endif
#include "config.h"
#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
/*!
* \warning This <b>is not</b> part of the TagLib public API!
*/
#if defined(HAVE_STD_SHARED_PTR)
# include <memory>
# define SHARED_PTR std::shared_ptr
#elif defined(HAVE_TR1_SHARED_PTR)
# include <tr1/memory>
# define SHARED_PTR std::tr1::shared_ptr
#elif defined(HAVE_BOOST_SHARED_PTR)
# include <boost/shared_ptr.hpp>
# define SHARED_PTR boost::shared_ptr
#else // HAVE_STD_SHARED_PTR
# include <algorithm>
# if defined(HAVE_GCC_ATOMIC)
# define ATOMIC_INT int
# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
# define ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1)
# elif defined(HAVE_WIN_ATOMIC)
# if !defined(NOMINMAX)
# define NOMINMAX
# endif
# include <windows.h>
# define ATOMIC_INT long
# define ATOMIC_INC(x) InterlockedIncrement(&x)
# define ATOMIC_DEC(x) InterlockedDecrement(&x)
# elif defined(HAVE_MAC_ATOMIC)
# include <libkern/OSAtomic.h>
# define ATOMIC_INT int32_t
# define ATOMIC_INC(x) OSAtomicIncrement32Barrier(&x)
# define ATOMIC_DEC(x) OSAtomicDecrement32Barrier(&x)
# elif defined(HAVE_IA64_ATOMIC)
# include <ia64intrin.h>
# define ATOMIC_INT int
# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
# define ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1)
# else
# define ATOMIC_INT int
# define ATOMIC_INC(x) (++x)
# define ATOMIC_DEC(x) (--x)
# endif
namespace TagLib
{
#if defined(TAGLIB_USE_STD_SHARED_PTR) \
|| defined(TAGLIB_USE_TR1_SHARED_PTR) \
|| defined(TAGLIB_USE_BOOST_SHARED_PTR)
// RefCountPtr<T> is just a thin wrapper of shared_ptr<T>.
// It will be optimized out by compilers and performs equivalent to them.
template <typename T>
class RefCountPtr
{
public:
RefCountPtr()
: sp()
{
}
template <typename U>
explicit RefCountPtr(U *p)
: sp(p)
{
}
RefCountPtr(const RefCountPtr<T> &x)
: sp(x.sp)
{
}
template <typename U>
RefCountPtr(const RefCountPtr<U> &x)
: sp(x.sp)
{
}
# ifdef TAGLIB_USE_MOVE_SEMANTICS
RefCountPtr(RefCountPtr<T> &&x)
: sp(std::move(x.sp))
{
}
template <typename U>
RefCountPtr(RefCountPtr<U> &&x)
: sp(std::move(x.sp))
{
}
# endif
T *get() const
{
return sp.get();
}
long use_count() const
{
return sp.use_count();
}
bool unique() const
{
return sp.unique();
}
template <typename U>
void reset(U *p)
{
sp.reset(p);
}
void reset()
{
sp.reset();
}
void swap(RefCountPtr<T> &x)
{
sp.swap(x.sp);
}
RefCountPtr<T> &operator=(const RefCountPtr<T> &x)
{
sp = x.sp;
return *this;
}
template <typename U>
RefCountPtr<T> &operator=(const RefCountPtr<U> &x)
{
sp = x.sp;
return *this;
}
# ifdef TAGLIB_USE_MOVE_SEMANTICS
RefCountPtr<T> &operator=(RefCountPtr<T> &&x)
{
sp = std::move(x.sp);
return *this;
}
template <typename U>
RefCountPtr<T> &operator=(RefCountPtr<U> &&x)
{
sp = std::move(x.sp);
return *this;
}
# endif
T& operator*() const
{
return sp.operator*();
}
T* operator->() const
{
return sp.operator->();
}
operator bool() const
{
return static_cast<bool>(sp);
}
bool operator!() const
{
return !static_cast<bool>(sp);
}
private:
template <typename U> friend class RefCountPtr;
# if defined(TAGLIB_USE_STD_SHARED_PTR)
std::shared_ptr<T> sp;
# elif defined(TAGLIB_USE_TR1_SHARED_PTR)
std::tr1::shared_ptr<T> sp;
# else
boost::shared_ptr<T> sp;
# endif
};
#else // TAGLIB_USE_STD_SHARED_PTR etc.
// Self-implements RefCountPtr<T> if shared_ptr<T> is not available.
// I STRONGLY RECOMMEND using standard shared_ptr<T> rather than this class.
@ -207,18 +92,37 @@ namespace TagLib
class CounterBase
{
public:
CounterBase();
virtual ~CounterBase();
CounterBase()
: refCount(1)
{
}
void addref();
void release();
long use_count() const;
virtual ~CounterBase()
{
}
void addref()
{
ATOMIC_INC(refCount);
}
void release()
{
if(ATOMIC_DEC(refCount) == 0) {
dispose();
delete this;
}
}
long use_count() const
{
return static_cast<long>(refCount);
}
virtual void dispose() = 0;
private:
class CounterBasePrivate;
CounterBasePrivate *d;
volatile ATOMIC_INT refCount;
};
// Counter impl class. Provides a dynamic deleter.
@ -380,83 +284,45 @@ namespace TagLib
template <typename U> friend class RefCountPtr;
};
#endif // TAGLIB_USE_STD_SHARED_PTR etc.
#if defined(TAGLIB_USE_STD_UNIQUE_PTR) || defined(TAGLIB_USE_BOOST_SCOPED_PTR)
// NonRefCountPtr<T> is just a thin wrapper of unique_ptr<T> or scoped_ptr<T>.
// It will be optimized out by compilers and performs equivalent to them.
template<typename T>
class NonRefCountPtr
template <typename T, typename U>
bool operator==(const RefCountPtr<T> &a, const RefCountPtr<U> &b)
{
public:
explicit NonRefCountPtr(T *p = 0)
: up(p)
{
}
return (a.get() == b.get());
}
~NonRefCountPtr()
{
}
template <typename T, typename U>
bool operator!=(const RefCountPtr<T> &a, const RefCountPtr<U> &b)
{
return (a.get() != b.get());
}
void reset(T *p = 0)
{
NonRefCountPtr<T>(p).swap(*this);
}
template <typename T>
void swap(RefCountPtr<T> &a, RefCountPtr<T> &b)
{
a.swap(b);
}
}
T &operator*() const
{
return up.operator*();
}
# define SHARED_PTR TagLib::RefCountPtr
T *operator->() const
{
return up.operator->();
}
#endif // HAVE_STD_SHARED_PTR etc.
T *get() const
{
return up.get();
}
#if defined(HAVE_STD_UNIQUE_PTR)
operator bool() const
{
return static_cast<bool>(up);
}
# include <memory>
# define SCOPED_PTR std::unique_ptr
bool operator!() const
{
return !static_cast<bool>(up);
}
#elif defined(HAVE_BOOST_SCOPED_PTR)
void swap(NonRefCountPtr &x)
{
up.swap(x.up);
}
# include <boost/scoped_ptr.hpp>
# define SCOPED_PTR boost::scoped_ptr
private:
// Noncopyable
NonRefCountPtr(const NonRefCountPtr &);
NonRefCountPtr &operator=(const NonRefCountPtr &);
void operator==(const NonRefCountPtr &) const;
void operator!=(const NonRefCountPtr &) const;
# if defined(TAGLIB_USE_STD_UNIQUE_PTR)
std::unique_ptr<T> up;
# else
boost::scoped_ptr<T> up;
# endif
};
#else // TAGLIB_USE_STD_UNIQUE_PTR
#else // HAVE_STD_UNIQUE_PTR
# include <algorithm>
namespace TagLib
{
// Self-implements NonRefCountPtr<T> if unique_ptr<T> is not available.
// I STRONGLY RECOMMEND using standard unique_ptr<T> rather than this class.
@ -522,34 +388,6 @@ namespace TagLib
T *px;
};
#endif // TAGLIB_USE_STD_UNIQUE_PTR
// Comparison operators for smart pointers.
template <typename T, typename U>
bool operator==(const RefCountPtr<T> &a, const RefCountPtr<U> &b)
{
return (a.get() == b.get());
}
template <typename T, typename U>
bool operator!=(const RefCountPtr<T> &a, const RefCountPtr<U> &b)
{
return (a.get() != b.get());
}
template <typename T, typename U>
bool operator==(const RefCountPtr<T> &a, U *b)
{
return (a.get() == b);
}
template <typename T, typename U>
bool operator!=(const RefCountPtr<T> &a, U *b)
{
return (a.get() != b);
}
template <typename T, typename U>
bool operator==(const NonRefCountPtr<T> &a, U *b)
{
@ -562,42 +400,17 @@ namespace TagLib
return (a.get() != b);
}
template <typename T, typename U>
bool operator==(T *a, const RefCountPtr<U> &b)
{
return (a == b.get());
}
template <typename T, typename U>
bool operator!=(T *a, const RefCountPtr<U> &b)
{
return (a != b.get());
}
template <typename T, typename U>
bool operator==(T *a, const NonRefCountPtr<U> &b)
{
return (a == b.get());
}
template <typename T, typename U>
bool operator!=(T *a, const NonRefCountPtr<U> &b)
{
return (a != b.get());
}
template <typename T>
void swap(RefCountPtr<T> &a, RefCountPtr<T> &b)
{
a.swap(b);
}
template <typename T>
void swap(NonRefCountPtr<T> &a, NonRefCountPtr<T> &b)
void swap(NonRefCountPtr<T> &a, NonRefCountPtr<T> &b)
{
a.swap(b);
}
}
# define SCOPED_PTR TagLib::NonRefCountPtr
#endif // HAVE_STD_UNIQUE_PTR etc.
#endif // DO_NOT_DOCUMENT
#endif

View File

@ -30,6 +30,7 @@
#include "tstring.h"
#include "tdebug.h"
#include "tstringlist.h"
#include "tsmartptr.h"
#include <iostream>
#include <cstdio>
@ -185,38 +186,30 @@ namespace TagLib {
class String::StringPrivate
{
public:
StringPrivate()
StringPrivate()
: data(new std::wstring())
{
}
StringPrivate(const std::wstring &s)
: data(s)
: data(new std::wstring(s))
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
StringPrivate(std::wstring &&s)
: data(s)
{
}
#endif
StringPrivate(size_t n, wchar_t c)
: data(n, c)
: data(new std::wstring(n, c))
{
}
/*!
* Stores string in UTF-16. The byte order depends on the CPU endian.
*/
std::wstring data;
SHARED_PTR<std::wstring> data;
/*!
* This is only used to hold the the most recent value of toCString().
*/
std::string cstring;
SHARED_PTR<std::string> cstring;
};
const String String::null;
@ -232,19 +225,10 @@ String::String()
}
String::String(const String &s)
: d(s.d)
: d(new StringPrivate(*s.d))
{
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
String::String(String &&s)
: d(std::move(s.d))
{
}
#endif
String::String(const std::string &s, Type t)
: d(new StringPrivate())
{
@ -325,6 +309,7 @@ String::String(const ByteVector &v, Type t)
String::~String()
{
delete d;
}
std::string String::to8Bit(bool unicode) const
@ -332,18 +317,18 @@ std::string String::to8Bit(bool unicode) const
std::string s;
if(!unicode) {
s.resize(d->data.size());
s.resize(d->data->size());
std::string::iterator targetIt = s.begin();
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*targetIt = static_cast<char>(*it);
++targetIt;
}
}
else {
s.resize(d->data.size() * 4 + 1);
s.resize(d->data->size() * 4 + 1);
UTF16toUTF8(&d->data[0], d->data.size(), &s[0], s.size());
UTF16toUTF8(&(*d->data)[0], d->data->size(), &s[0], s.size());
s.resize(::strlen(s.c_str()));
}
@ -352,43 +337,43 @@ std::string String::to8Bit(bool unicode) const
const std::wstring &String::toWString() const
{
return d->data;
return *d->data;
}
const char *String::toCString(bool unicode) const
{
d->cstring = to8Bit(unicode);
return d->cstring.c_str();
d->cstring.reset(new std::string(to8Bit(unicode)));
return d->cstring->c_str();
}
String::Iterator String::begin()
{
return d->data.begin();
return d->data->begin();
}
String::ConstIterator String::begin() const
{
return d->data.begin();
return d->data->begin();
}
String::Iterator String::end()
{
return d->data.end();
return d->data->end();
}
String::ConstIterator String::end() const
{
return d->data.end();
return d->data->end();
}
size_t String::find(const String &s, size_t offset) const
{
return d->data.find(s.d->data, offset);
return d->data->find(*s.d->data, offset);
}
size_t String::rfind(const String &s, size_t offset) const
{
return d->data.rfind(s.d->data, offset);
return d->data->rfind(*s.d->data, offset);
}
StringList String::split(const String &separator) const
@ -421,13 +406,13 @@ bool String::startsWith(const String &s) const
String String::substr(size_t position, size_t length) const
{
return String(d->data.substr(position, length));
return String(d->data->substr(position, length));
}
String &String::append(const String &s)
{
detach();
d->data += s.d->data;
*d->data += *s.d->data;
return *this;
}
@ -435,15 +420,10 @@ String String::upper() const
{
static const int shift = 'A' - 'a';
String s;
s.d->data.resize(d->data.size());
wchar_t *p = &s.d->data[0];
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); ++it) {
String s(*this);
for(Iterator it = s.begin(); it != s.end(); ++it) {
if(*it >= 'a' && *it <= 'z')
*p++ = *it + shift;
else
*p++ = *it;
*it = *it + shift;
}
return s;
@ -451,7 +431,7 @@ String String::upper() const
size_t String::size() const
{
return d->data.size();
return d->data->size();
}
size_t String::length() const
@ -461,7 +441,7 @@ size_t String::length() const
bool String::isEmpty() const
{
return d->data.empty();
return d->data->empty();
}
bool String::isNull() const
@ -478,7 +458,7 @@ ByteVector String::data(Type t) const
ByteVector v(size(), 0);
char *p = v.data();
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++)
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++)
*p++ = static_cast<char>(*it);
return v;
@ -487,7 +467,7 @@ ByteVector String::data(Type t) const
{
ByteVector v(size() * 4 + 1, 0);
UTF16toUTF8(&d->data[0], d->data.size(), v.data(), v.size());
UTF16toUTF8(&(*d->data)[0], d->data->size(), v.data(), v.size());
v.resize(::strlen(v.data()));
return v;
@ -503,7 +483,7 @@ ByteVector String::data(Type t) const
*p++ = '\xff';
*p++ = '\xfe';
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
}
@ -515,7 +495,7 @@ ByteVector String::data(Type t) const
ByteVector v(size() * 2, 0);
char *p = v.data();
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it >> 8);
*p++ = static_cast<char>(*it & 0xff);
}
@ -527,7 +507,7 @@ ByteVector String::data(Type t) const
ByteVector v(size() * 2, 0);
char *p = v.data();
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
}
@ -546,13 +526,13 @@ int String::toInt(bool *ok) const
{
int value = 0;
const size_t size = d->data.size();
const bool negative = size > 0 && d->data[0] == '-';
const size_t size = d->data->size();
const bool negative = size > 0 && (*d->data)[0] == '-';
const size_t start = negative ? 1 : 0;
size_t i = start;
for(; i < size && d->data[i] >= '0' && d->data[i] <= '9'; i++)
value = value * 10 + (d->data[i] - '0');
for(; i < size && (*d->data)[i] >= '0' && (*d->data)[i] <= '9'; i++)
value = value * 10 + ((*d->data)[i] - '0');
if(negative)
value = value * -1;
@ -565,8 +545,8 @@ int String::toInt(bool *ok) const
String String::stripWhiteSpace() const
{
std::wstring::const_iterator begin = d->data.begin();
std::wstring::const_iterator end = d->data.end();
std::wstring::const_iterator begin = d->data->begin();
std::wstring::const_iterator end = d->data->end();
while(begin != end &&
(*begin == '\t' || *begin == '\n' || *begin == '\f' ||
@ -591,7 +571,7 @@ String String::stripWhiteSpace() const
bool String::isLatin1() const
{
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
if(*it >= 256)
return false;
}
@ -600,7 +580,7 @@ bool String::isLatin1() const
bool String::isAscii() const
{
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
if(*it >= 128)
return false;
}
@ -638,22 +618,22 @@ String String::number(int n) // static
TagLib::wchar &String::operator[](size_t i)
{
detach();
return d->data[i];
return (*d->data)[i];
}
const TagLib::wchar &String::operator[](size_t i) const
{
return d->data[i];
return (*d->data)[i];
}
bool String::operator==(const String &s) const
{
return (d == s.d || d->data == s.d->data);
return (d->data == s.d->data || *d->data == *s.d->data);
}
bool String::operator==(const char *s) const
{
for(std::wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
if(*it != static_cast<uchar>(*s))
return false;
@ -665,7 +645,7 @@ bool String::operator==(const char *s) const
bool String::operator==(const wchar_t *s) const
{
return (d->data == s);
return (*d->data == s);
}
bool String::operator!=(const String &s) const
@ -677,7 +657,7 @@ String &String::operator+=(const String &s)
{
detach();
d->data += s.d->data;
*d->data += *s.d->data;
return *this;
}
@ -685,7 +665,7 @@ String &String::operator+=(const wchar_t *s)
{
detach();
d->data += s;
*d->data += *s;
return *this;
}
@ -694,7 +674,7 @@ String &String::operator+=(const char *s)
detach();
for(int i = 0; s[i] != 0; i++)
d->data += uchar(s[i]);
*d->data += uchar(s[i]);
return *this;
}
@ -702,7 +682,7 @@ String &String::operator+=(wchar_t c)
{
detach();
d->data += c;
*d->data += c;
return *this;
}
@ -710,29 +690,19 @@ String &String::operator+=(char c)
{
detach();
d->data += uchar(c);
*d->data += uchar(c);
return *this;
}
String &String::operator=(const String &s)
{
d = s.d;
*d = *s.d;
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
String &String::operator=(String &&s)
{
d = std::move(s.d);
return *this;
}
#endif
String &String::operator=(const std::string &s)
{
d.reset(new StringPrivate());
d->data.reset(new std::wstring());
copyFromLatin1(s.c_str(), s.length());
return *this;
@ -740,23 +710,13 @@ String &String::operator=(const std::string &s)
String &String::operator=(const std::wstring &s)
{
d.reset(new StringPrivate(s));
d->data.reset(new std::wstring(s));
return *this;
}
#ifdef TAGLIB_USE_MOVE_SEMANTICS
String &String::operator=(std::wstring &&s)
{
d.reset(new StringPrivate(s));
return *this;
}
#endif
String &String::operator=(const wchar_t *s)
{
d.reset(new StringPrivate());
d->data.reset(new std::wstring());
copyFromUTF16(s, ::wcslen(s), WCharByteOrder);
return *this;
@ -764,19 +724,19 @@ String &String::operator=(const wchar_t *s)
String &String::operator=(char c)
{
d.reset(new StringPrivate(1, static_cast<uchar>(c)));
d->data.reset(new std::wstring(1, c));
return *this;
}
String &String::operator=(wchar_t c)
{
d.reset(new StringPrivate(1, c));
d->data.reset(new std::wstring(1, c));
return *this;
}
String &String::operator=(const char *s)
{
d.reset(new StringPrivate());
d->data.reset(new std::wstring());
copyFromLatin1(s, ::strlen(s));
return *this;
@ -784,18 +744,18 @@ String &String::operator=(const char *s)
String &String::operator=(const ByteVector &v)
{
d.reset(new StringPrivate());
d->data.reset(new std::wstring());
copyFromLatin1(v.data(), v.size());
// If we hit a null in the ByteVector, shrink the string again.
d->data.resize(::wcslen(d->data.c_str()));
d->data->resize(::wcslen(d->data->c_str()));
return *this;
}
bool String::operator<(const String &s) const
{
return d->data < s.d->data;
return *d->data < *s.d->data;
}
////////////////////////////////////////////////////////////////////////////////
@ -804,8 +764,8 @@ bool String::operator<(const String &s) const
void String::detach()
{
if(!d.unique())
d.reset(new StringPrivate(d->data));
if(!d->data.unique())
d->data.reset(new std::wstring(*d->data));
}
////////////////////////////////////////////////////////////////////////////////
@ -814,18 +774,18 @@ void String::detach()
void String::copyFromLatin1(const char *s, size_t length)
{
d->data.resize(length);
d->data->resize(length);
for(size_t i = 0; i < length; ++i)
d->data[i] = static_cast<uchar>(s[i]);
(*d->data)[i] = static_cast<uchar>(s[i]);
}
void String::copyFromUTF8(const char *s, size_t length)
{
d->data.resize(length);
d->data->resize(length);
UTF8toUTF16(s, length, &d->data[0], d->data.size());
d->data.resize(::wcslen(d->data.c_str()));
UTF8toUTF16(s, length, &(*d->data)[0], d->data->size());
d->data->resize(::wcslen(d->data->c_str()));
}
void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
@ -847,12 +807,12 @@ void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
else
swap = (t != WCharByteOrder);
d->data.resize(length);
memcpy(&d->data[0], s, length * sizeof(wchar_t));
d->data->resize(length);
memcpy(&(*d->data)[0], s, length * sizeof(wchar_t));
if(swap) {
for(size_t i = 0; i < length; ++i)
d->data[i] = byteSwap(static_cast<ushort>(s[i]));
(*d->data)[i] = byteSwap(static_cast<ushort>(s[i]));
}
}
@ -884,9 +844,9 @@ void String::copyFromUTF16(const char *s, size_t length, Type t)
else
swap = (t != WCharByteOrder);
d->data.resize(length / 2);
d->data->resize(length / 2);
for(size_t i = 0; i < length / 2; ++i) {
d->data[i] = swap ? combine(*s, *(s + 1)) : combine(*(s + 1), *s);
(*d->data)[i] = swap ? combine(*s, *(s + 1)) : combine(*(s + 1), *s);
s += 2;
}
}

View File

@ -119,17 +119,6 @@ namespace TagLib {
*/
String(const String &s);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Constructs a String equivalent to \a s.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
String(String &&s);
#endif
/*!
* Makes a deep copy of the data in \a s.
*
@ -403,17 +392,6 @@ namespace TagLib {
*/
String &operator=(const String &s);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a s into this String.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
String &operator=(String &&s);
#endif
/*!
* Performs a deep copy of the data in \a s.
*/
@ -424,17 +402,6 @@ namespace TagLib {
*/
String &operator=(const std::wstring &s);
#ifdef TAGLIB_USE_MOVE_SEMANTICS
/*!
* Moves \a s into this String.
*
* \note Not available unless TAGLIB_USE_MOVE_SEMANTICS macro is defined.
*/
String &operator=(std::wstring &&s);
#endif
/*!
* Performs a deep copy of the data in \a s.
*/
@ -520,7 +487,7 @@ namespace TagLib {
static const Type WCharByteOrder;
class StringPrivate;
RefCountPtr<StringPrivate> d;
StringPrivate *d;
};
/*!

View File

@ -26,7 +26,7 @@ public:
void testSharedptrBasic()
{
int * ip = new int;
RefCountPtr<int> cp ( ip );
SHARED_PTR<int> cp ( ip );
CPPUNIT_ASSERT( ip == cp.get() );
CPPUNIT_ASSERT( cp.use_count() == 1 );
@ -36,7 +36,7 @@ public:
ck( static_cast<int*>(cp.get()), 54321 );
ck( static_cast<int*>(ip), *cp );
RefCountPtr<int> cp2 ( cp );
SHARED_PTR<int> cp2 ( cp );
CPPUNIT_ASSERT( ip == cp2.get() );
CPPUNIT_ASSERT( cp.use_count() == 2 );
CPPUNIT_ASSERT( cp2.use_count() == 2 );
@ -46,7 +46,7 @@ public:
ck( static_cast<int*>(cp2.get()), 54321 );
ck( static_cast<int*>(ip), *cp2 );
RefCountPtr<int> cp3 ( cp );
SHARED_PTR<int> cp3 ( cp );
CPPUNIT_ASSERT( cp.use_count() == 3 );
CPPUNIT_ASSERT( cp2.use_count() == 3 );
CPPUNIT_ASSERT( cp3.use_count() == 3 );
@ -76,16 +76,16 @@ public:
CPPUNIT_ASSERT( cp.use_count() == 3 );
CPPUNIT_ASSERT( *cp == 87654 );
RefCountPtr<int> cp4;
SHARED_PTR<int> cp4;
swap( cp2, cp4 );
CPPUNIT_ASSERT( cp4.use_count() == 3 );
CPPUNIT_ASSERT( *cp4 == 87654 );
CPPUNIT_ASSERT( cp2.get() == 0 );
std::set< RefCountPtr<int> > scp;
std::set< SHARED_PTR<int> > scp;
scp.insert(cp4);
CPPUNIT_ASSERT( scp.find(cp4) != scp.end() );
CPPUNIT_ASSERT( scp.find(cp4) == scp.find( RefCountPtr<int>(cp4) ) );
CPPUNIT_ASSERT( scp.find(cp4) == scp.find( SHARED_PTR<int>(cp4) ) );
}
private:
@ -130,7 +130,7 @@ public:
derivedDestructorCalled = false;
{
RefCountPtr<DummyBase> p1(new DummyDerived(100));
SHARED_PTR<DummyBase> p1(new DummyDerived(100));
CPPUNIT_ASSERT(p1->getValue() == 100);
}
@ -141,8 +141,8 @@ public:
derivedDestructorCalled = false;
{
RefCountPtr<DummyDerived> p1(new DummyDerived(100));
RefCountPtr<DummyBase> p2 = p1;
SHARED_PTR<DummyDerived> p1(new DummyDerived(100));
SHARED_PTR<DummyBase> p2 = p1;
CPPUNIT_ASSERT(p1->getValue() == 100);
CPPUNIT_ASSERT(p2->getValue() == 100);
@ -155,8 +155,8 @@ public:
derivedDestructorCalled = false;
{
RefCountPtr<DummyDerived> p1;
RefCountPtr<DummyBase> p2;
SHARED_PTR<DummyDerived> p1;
SHARED_PTR<DummyBase> p2;
p1.reset(new DummyDerived(100));
p2 = p1;
@ -171,7 +171,7 @@ public:
private:
class DummyIncomplete;
RefCountPtr<DummyIncomplete> pincomplete;
SHARED_PTR<DummyIncomplete> pincomplete;
class DummyIncomplete
{