Format taglib sources

This commit is contained in:
Jonas Kvinge
2020-06-13 19:02:42 +02:00
parent 72bff7fa35
commit 4ce099294c
224 changed files with 12905 additions and 15623 deletions

View File

@@ -33,25 +33,25 @@
#define TAGLIB_PATCH_VERSION 1
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__)
#define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
# define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
#else
#define TAGLIB_IGNORE_MISSING_DESTRUCTOR
# define TAGLIB_IGNORE_MISSING_DESTRUCTOR
#endif
#if (defined(_MSC_VER) && _MSC_VER >= 1600)
#define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long long>(x)
# define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long long>(x)
#else
#define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long>(x)
# define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long>(x)
#endif
#if __cplusplus >= 201402
#define TAGLIB_DEPRECATED [[deprecated]]
# define TAGLIB_DEPRECATED [[deprecated]]
#elif defined(__GNUC__) || defined(__clang__)
#define TAGLIB_DEPRECATED __attribute__((deprecated))
# define TAGLIB_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define TAGLIB_DEPRECATED __declspec(deprecated)
# define TAGLIB_DEPRECATED __declspec(deprecated)
#else
#define TAGLIB_DEPRECATED
# define TAGLIB_DEPRECATED
#endif
#include <string>
@@ -69,24 +69,24 @@
namespace Strawberry_TagLib {
namespace TagLib {
class String;
class String;
// These integer types are deprecated. Do not use them.
// These integer types are deprecated. Do not use them.
typedef wchar_t wchar; // Assumed to be sufficient to store a UTF-16 char.
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ulonglong;
typedef wchar_t wchar; // Assumed to be sufficient to store a UTF-16 char.
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ulonglong;
/*!
/*!
* Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3)
* so I'm providing something here that should be constant.
*/
typedef std::basic_string<wchar_t> wstring;
}
}
typedef std::basic_string<wchar_t> wstring;
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \mainpage TagLib

File diff suppressed because it is too large Load Diff

View File

@@ -35,164 +35,163 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! A byte vector
//! A byte vector
/*!
/*!
* This class provides a byte vector with some methods that are useful for
* tagging purposes. Many of the search functions are tailored to what is
* useful for finding tag related patterns in a data array.
*/
class TAGLIB_EXPORT ByteVector
{
public:
class TAGLIB_EXPORT ByteVector {
public:
#ifndef DO_NOT_DOCUMENT
typedef std::vector<char>::iterator Iterator;
typedef std::vector<char>::const_iterator ConstIterator;
typedef std::vector<char>::reverse_iterator ReverseIterator;
typedef std::vector<char>::const_reverse_iterator ConstReverseIterator;
typedef std::vector<char>::iterator Iterator;
typedef std::vector<char>::const_iterator ConstIterator;
typedef std::vector<char>::reverse_iterator ReverseIterator;
typedef std::vector<char>::const_reverse_iterator ConstReverseIterator;
#endif
/*!
/*!
* Constructs an empty byte vector.
*/
ByteVector();
ByteVector();
/*!
/*!
* Construct a vector of size \a size with all values set to \a value by
* default.
*/
ByteVector(unsigned int size, char value = 0);
ByteVector(unsigned int size, char value = 0);
/*!
/*!
* Constructs a byte vector that is a copy of \a v.
*/
ByteVector(const ByteVector &v);
ByteVector(const ByteVector &v);
/*!
/*!
* Constructs a byte vector that is a copy of \a v.
*/
ByteVector(const ByteVector &v, unsigned int offset, unsigned int length);
ByteVector(const ByteVector &v, unsigned int offset, unsigned int length);
/*!
/*!
* Constructs a byte vector that contains \a c.
*/
ByteVector(char c);
ByteVector(char c);
/*!
/*!
* Constructs a byte vector that copies \a data for up to \a length bytes.
*/
ByteVector(const char *data, unsigned int length);
ByteVector(const char *data, unsigned int length);
/*!
/*!
* Constructs a byte vector that copies \a data up to the first null
* byte. This is particularly useful for constructing byte arrays from
* string constants.
*
* \warning The behavior is undefined if \a data is not null terminated.
*/
ByteVector(const char *data);
ByteVector(const char *data);
/*!
/*!
* Destroys this ByteVector instance.
*/
virtual ~ByteVector();
virtual ~ByteVector();
/*!
/*!
* Sets the data for the byte array using the first \a length bytes of \a data
*/
ByteVector &setData(const char *data, unsigned int length);
ByteVector &setData(const char *data, unsigned int length);
/*!
/*!
* Sets the data for the byte array copies \a data up to the first null
* byte. The behavior is undefined if \a data is not null terminated.
*/
ByteVector &setData(const char *data);
ByteVector &setData(const char *data);
/*!
/*!
* Returns a pointer to the internal data structure.
*
* \warning Care should be taken when modifying this data structure as it is
* easy to corrupt the ByteVector when doing so. Specifically, while the
* data may be changed, its length may not be.
*/
char *data();
char *data();
/*!
/*!
* Returns a pointer to the internal data structure which may not be modified.
*/
const char *data() const;
const char *data() const;
/*!
/*!
* Returns a byte vector made up of the bytes starting at \a index and
* for \a length bytes. If \a length is not specified it will return the bytes
* from \a index to the end of the vector.
*/
ByteVector mid(unsigned int index, unsigned int length = 0xffffffff) const;
ByteVector mid(unsigned int index, unsigned int length = 0xffffffff) const;
/*!
/*!
* This essentially performs the same as operator[](), but instead of causing
* a runtime error if the index is out of bounds, it will return a null byte.
*/
char at(unsigned int index) const;
char at(unsigned int index) const;
/*!
/*!
* Searches the ByteVector for \a pattern starting at \a offset and returns
* the offset. Returns -1 if the pattern was not found. If \a byteAlign is
* specified the pattern will only be matched if it starts on a byte divisible
* by \a byteAlign (starting from \a offset).
*/
int find(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const;
int find(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const;
/*!
/*!
* Searches the char for \a c starting at \a offset and returns
* the offset. Returns \a -1 if the pattern was not found. If \a byteAlign is
* specified the pattern will only be matched if it starts on a byte divisible
* by \a byteAlign (starting from \a offset).
*/
int find(char c, unsigned int offset = 0, int byteAlign = 1) const;
int find(char c, unsigned int offset = 0, int byteAlign = 1) const;
/*!
/*!
* Searches the ByteVector for \a pattern starting from either the end of the
* vector or \a offset and returns the offset. Returns -1 if the pattern was
* not found. If \a byteAlign is specified the pattern will only be matched
* if it starts on a byte divisible by \a byteAlign (starting from \a offset).
*/
int rfind(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const;
int rfind(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const;
/*!
/*!
* Checks to see if the vector contains the \a pattern starting at position
* \a offset. Optionally, if you only want to search for part of the pattern
* you can specify an offset within the pattern to start from. Also, you can
* specify to only check for the first \a patternLength bytes of \a pattern with
* the \a patternLength argument.
*/
bool containsAt(const ByteVector &pattern, unsigned int offset,
unsigned int patternOffset = 0, unsigned int patternLength = 0xffffffff) const;
bool containsAt(const ByteVector &pattern, unsigned int offset,
unsigned int patternOffset = 0, unsigned int patternLength = 0xffffffff) const;
/*!
/*!
* Returns true if the vector starts with \a pattern.
*/
bool startsWith(const ByteVector &pattern) const;
bool startsWith(const ByteVector &pattern) const;
/*!
/*!
* Returns true if the vector ends with \a pattern.
*/
bool endsWith(const ByteVector &pattern) const;
bool endsWith(const ByteVector &pattern) const;
/*!
/*!
* Replaces \a oldByte with \a newByte and returns a reference to the
* ByteVector after the operation. This \e does modify the vector.
*/
ByteVector &replace(char oldByte, char newByte);
ByteVector &replace(char oldByte, char newByte);
/*!
/*!
* Replaces \a pattern with \a with and returns a reference to the ByteVector
* after the operation. This \e does modify the vector.
*/
ByteVector &replace(const ByteVector &pattern, const ByteVector &with);
ByteVector &replace(const ByteVector &pattern, const ByteVector &with);
/*!
/*!
* Checks for a partial match of \a pattern at the end of the vector. It
* returns the offset of the partial match within the vector, or -1 if the
* pattern is not found. This method is particularly useful when searching for
@@ -202,76 +201,76 @@ namespace TagLib {
* \note This will not match the complete pattern at the end of the string; use
* endsWith() for that.
*/
int endsWithPartialMatch(const ByteVector &pattern) const;
int endsWithPartialMatch(const ByteVector &pattern) const;
/*!
/*!
* Appends \a v to the end of the ByteVector.
*/
ByteVector &append(const ByteVector &v);
ByteVector &append(const ByteVector &v);
/*!
/*!
* Appends \a c to the end of the ByteVector.
*/
ByteVector &append(char c);
ByteVector &append(char c);
/*!
/*!
* Clears the data.
*/
ByteVector &clear();
ByteVector &clear();
/*!
/*!
* Returns the size of the array.
*/
unsigned int size() const;
unsigned int size() const;
/*!
/*!
* Resize the vector to \a size. If the vector is currently less than
* \a size, pad the remaining spaces with \a padding. Returns a reference
* to the resized vector.
*/
ByteVector &resize(unsigned int size, char padding = 0);
ByteVector &resize(unsigned int size, char padding = 0);
/*!
/*!
* Returns an Iterator that points to the front of the vector.
*/
Iterator begin();
Iterator begin();
/*!
/*!
* Returns a ConstIterator that points to the front of the vector.
*/
ConstIterator begin() const;
ConstIterator begin() const;
/*!
/*!
* Returns an Iterator that points to the back of the vector.
*/
Iterator end();
Iterator end();
/*!
/*!
* Returns a ConstIterator that points to the back of the vector.
*/
ConstIterator end() const;
ConstIterator end() const;
/*!
/*!
* Returns a ReverseIterator that points to the front of the vector.
*/
ReverseIterator rbegin();
ReverseIterator rbegin();
/*!
/*!
* Returns a ConstReverseIterator that points to the front of the vector.
*/
ConstReverseIterator rbegin() const;
ConstReverseIterator rbegin() const;
/*!
/*!
* Returns a ReverseIterator that points to the back of the vector.
*/
ReverseIterator rend();
ReverseIterator rend();
/*!
/*!
* Returns a ConstReverseIterator that points to the back of the vector.
*/
ConstReverseIterator rend() const;
ConstReverseIterator rend() const;
/*!
/*!
* Returns true if the vector is null.
*
* \note A vector may be empty without being null. So do not use this
@@ -281,26 +280,26 @@ namespace TagLib {
*
* \deprecated
*/
// BIC: remove
bool isNull() const;
// BIC: remove
bool isNull() const;
/*!
/*!
* Returns true if the ByteVector is empty.
*
* \see size()
* \see isNull()
*/
bool isEmpty() const;
bool isEmpty() const;
/*!
/*!
* Returns a CRC checksum of the byte vector's data.
*
* \note This uses an uncommon variant of CRC32 specializes in Ogg.
*/
// BIC: Remove or make generic.
unsigned int checksum() const;
// BIC: Remove or make generic.
unsigned int checksum() const;
/*!
/*!
* Converts the first 4 bytes of the vector to an unsigned integer.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -310,9 +309,9 @@ namespace TagLib {
*
* \see fromUInt()
*/
unsigned int toUInt(bool mostSignificantByteFirst = true) const;
unsigned int toUInt(bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the 4 bytes at \a offset of the vector to an unsigned integer.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -322,9 +321,9 @@ namespace TagLib {
*
* \see fromUInt()
*/
unsigned int toUInt(unsigned int offset, bool mostSignificantByteFirst = true) const;
unsigned int toUInt(unsigned int offset, bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the \a length bytes at \a offset of the vector to an unsigned
* integer. If \a length is larger than 4, the excess is ignored.
*
@@ -335,10 +334,10 @@ namespace TagLib {
*
* \see fromUInt()
*/
unsigned int toUInt(unsigned int offset, unsigned int length,
bool mostSignificantByteFirst = true) const;
unsigned int toUInt(unsigned int offset, unsigned int length,
bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the first 2 bytes of the vector to a (signed) short.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -347,9 +346,9 @@ namespace TagLib {
*
* \see fromShort()
*/
short toShort(bool mostSignificantByteFirst = true) const;
short toShort(bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the 2 bytes at \a offset of the vector to a (signed) short.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -358,9 +357,9 @@ namespace TagLib {
*
* \see fromShort()
*/
short toShort(unsigned int offset, bool mostSignificantByteFirst = true) const;
short toShort(unsigned int offset, bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the first 2 bytes of the vector to a unsigned short.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -369,9 +368,9 @@ namespace TagLib {
*
* \see fromShort()
*/
unsigned short toUShort(bool mostSignificantByteFirst = true) const;
unsigned short toUShort(bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the 2 bytes at \a offset of the vector to a unsigned short.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -380,9 +379,9 @@ namespace TagLib {
*
* \see fromShort()
*/
unsigned short toUShort(unsigned int offset, bool mostSignificantByteFirst = true) const;
unsigned short toUShort(unsigned int offset, bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the first 8 bytes of the vector to a (signed) long long.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -392,9 +391,9 @@ namespace TagLib {
*
* \see fromUInt()
*/
long long toLongLong(bool mostSignificantByteFirst = true) const;
long long toLongLong(bool mostSignificantByteFirst = true) const;
/*!
/*!
* Converts the 8 bytes at \a offset of the vector to a (signed) long long.
*
* If \a mostSignificantByteFirst is true this will operate left to right
@@ -404,49 +403,49 @@ namespace TagLib {
*
* \see fromUInt()
*/
long long toLongLong(unsigned int offset, bool mostSignificantByteFirst = true) const;
long long toLongLong(unsigned int offset, bool mostSignificantByteFirst = true) const;
/*
/*
* Converts the 4 bytes at \a offset of the vector to a float as an IEEE754
* 32-bit little-endian floating point number.
*/
float toFloat32LE(size_t offset) const;
float toFloat32LE(size_t offset) const;
/*
/*
* Converts the 4 bytes at \a offset of the vector to a float as an IEEE754
* 32-bit big-endian floating point number.
*/
float toFloat32BE(size_t offset) const;
float toFloat32BE(size_t offset) const;
/*
/*
* Converts the 8 bytes at \a offset of the vector to a double as an IEEE754
* 64-bit little-endian floating point number.
*/
double toFloat64LE(size_t offset) const;
double toFloat64LE(size_t offset) const;
/*
/*
* Converts the 8 bytes at \a offset of the vector to a double as an IEEE754
* 64-bit big-endian floating point number.
*/
double toFloat64BE(size_t offset) const;
double toFloat64BE(size_t offset) const;
/*
/*
* Converts the 10 bytes at \a offset of the vector to a long double as an
* IEEE754 80-bit little-endian floating point number.
*
* \note This may compromise the precision depends on the size of long double.
*/
long double toFloat80LE(size_t offset) const;
long double toFloat80LE(size_t offset) const;
/*
/*
* Converts the 10 bytes at \a offset of the vector to a long double as an
* IEEE754 80-bit big-endian floating point number.
*
* \note This may compromise the precision depends on the size of long double.
*/
long double toFloat80BE(size_t offset) const;
long double toFloat80BE(size_t offset) const;
/*!
/*!
* Creates a 4 byte ByteVector based on \a value. If
* \a mostSignificantByteFirst is true, then this will operate left to right
* in building the ByteVector. For example if \a mostSignificantByteFirst is
@@ -455,9 +454,9 @@ namespace TagLib {
*
* \see toUInt()
*/
static ByteVector fromUInt(unsigned int value, bool mostSignificantByteFirst = true);
static ByteVector fromUInt(unsigned int value, bool mostSignificantByteFirst = true);
/*!
/*!
* Creates a 2 byte ByteVector based on \a value. If
* \a mostSignificantByteFirst is true, then this will operate left to right
* in building the ByteVector. For example if \a mostSignificantByteFirst is
@@ -465,9 +464,9 @@ namespace TagLib {
*
* \see toShort()
*/
static ByteVector fromShort(short value, bool mostSignificantByteFirst = true);
static ByteVector fromShort(short value, bool mostSignificantByteFirst = true);
/*!
/*!
* Creates a 8 byte ByteVector based on \a value. If
* \a mostSignificantByteFirst is true, then this will operate left to right
* in building the ByteVector. For example if \a mostSignificantByteFirst is
@@ -476,117 +475,117 @@ namespace TagLib {
*
* \see toLongLong()
*/
static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true);
static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true);
/*!
/*!
* Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit
* little-endian floating point number.
*
* \see fromFloat32BE()
*/
static ByteVector fromFloat32LE(float value);
static ByteVector fromFloat32LE(float value);
/*!
/*!
* Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit
* big-endian floating point number.
*
* \see fromFloat32LE()
*/
static ByteVector fromFloat32BE(float value);
static ByteVector fromFloat32BE(float value);
/*!
/*!
* Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit
* little-endian floating point number.
*
* \see fromFloat64BE()
*/
static ByteVector fromFloat64LE(double value);
static ByteVector fromFloat64LE(double value);
/*!
/*!
* Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit
* big-endian floating point number.
*
* \see fromFloat64LE()
*/
static ByteVector fromFloat64BE(double value);
static ByteVector fromFloat64BE(double value);
/*!
/*!
* Returns a ByteVector based on the CString \a s.
*/
static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff);
static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff);
/*!
/*!
* Returns a const reference to the byte at \a index.
*/
const char &operator[](int index) const;
const char &operator[](int index) const;
/*!
/*!
* Returns a reference to the byte at \a index.
*/
char &operator[](int index);
char &operator[](int index);
/*!
/*!
* Returns true if this ByteVector and \a v are equal.
*/
bool operator==(const ByteVector &v) const;
bool operator==(const ByteVector &v) const;
/*!
/*!
* Returns true if this ByteVector and \a v are not equal.
*/
bool operator!=(const ByteVector &v) const;
bool operator!=(const ByteVector &v) const;
/*!
/*!
* Returns true if this ByteVector and the null terminated C string \a s
* contain the same data.
*/
bool operator==(const char *s) const;
bool operator==(const char *s) const;
/*!
/*!
* Returns true if this ByteVector and the null terminated C string \a s
* do not contain the same data.
*/
bool operator!=(const char *s) const;
bool operator!=(const char *s) const;
/*!
/*!
* Returns true if this ByteVector is less than \a v. The value of the
* vectors is determined by evaluating the character from left to right, and
* in the event one vector is a superset of the other, the size is used.
*/
bool operator<(const ByteVector &v) const;
bool operator<(const ByteVector &v) const;
/*!
/*!
* Returns true if this ByteVector is greater than \a v.
*/
bool operator>(const ByteVector &v) const;
bool operator>(const ByteVector &v) const;
/*!
/*!
* Returns a vector that is \a v appended to this vector.
*/
ByteVector operator+(const ByteVector &v) const;
ByteVector operator+(const ByteVector &v) const;
/*!
/*!
* Copies ByteVector \a v.
*/
ByteVector &operator=(const ByteVector &v);
ByteVector &operator=(const ByteVector &v);
/*!
/*!
* Copies a byte \a c.
*/
ByteVector &operator=(char c);
ByteVector &operator=(char c);
/*!
/*!
* Copies \a data up to the first null byte.
*
* \warning The behavior is undefined if \a data is not null terminated.
*/
ByteVector &operator=(const char *data);
ByteVector &operator=(const char *data);
/*!
/*!
* Exchanges the content of the ByteVector by the content of \a v.
*/
void swap(ByteVector &v);
void swap(ByteVector &v);
/*!
/*!
* A static, empty ByteVector which is convenient and fast (since returning
* an empty or "null" value does not require instantiating a new ByteVector).
*
@@ -595,38 +594,38 @@ namespace TagLib {
*
* \deprecated
*/
// BIC: remove
static ByteVector null;
// BIC: remove
static ByteVector null;
/*!
/*!
* Returns a hex-encoded copy of the byte vector.
*/
ByteVector toHex() const;
ByteVector toHex() const;
/*!
/*!
* Returns a base64 encoded copy of the byte vector
*/
ByteVector toBase64() const;
ByteVector toBase64() const;
/*!
/*!
* Decodes the base64 encoded byte vector.
*/
static ByteVector fromBase64(const ByteVector &);
static ByteVector fromBase64(const ByteVector &);
protected:
/*
protected:
/*
* If this ByteVector is being shared via implicit sharing, do a deep copy
* of the data and separate from the shared members. This should be called
* by all non-const subclass members.
*/
void detach();
void detach();
private:
class ByteVectorPrivate;
ByteVectorPrivate *d;
};
}
}
private:
class ByteVectorPrivate;
ByteVectorPrivate *d;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \relates Strawberry_TagLib::TagLib::ByteVector

View File

@@ -27,9 +27,7 @@
using namespace Strawberry_TagLib::TagLib;
class ByteVectorListPrivate
{
class ByteVectorListPrivate {
};
////////////////////////////////////////////////////////////////////////////////
@@ -37,22 +35,19 @@ class ByteVectorListPrivate
////////////////////////////////////////////////////////////////////////////////
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern,
int byteAlign)
{
int byteAlign) {
return split(v, pattern, byteAlign, 0);
}
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern,
int byteAlign, int max)
{
int byteAlign, int max) {
ByteVectorList l;
unsigned int previousOffset = 0;
for(int offset = v.find(pattern, 0, byteAlign);
offset != -1 && (max == 0 || max > int(l.size()) + 1);
offset = v.find(pattern, offset + pattern.size(), byteAlign))
{
if(offset - previousOffset >= 1)
for (int offset = v.find(pattern, 0, byteAlign);
offset != -1 && (max == 0 || max > int(l.size()) + 1);
offset = v.find(pattern, offset + pattern.size(), byteAlign)) {
if (offset - previousOffset >= 1)
l.append(v.mid(previousOffset, offset - previousOffset));
else
l.append(ByteVector());
@@ -60,7 +55,7 @@ ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &patt
previousOffset = offset + pattern.size();
}
if(previousOffset < v.size())
if (previousOffset < v.size())
l.append(v.mid(previousOffset, v.size() - previousOffset));
return l;
@@ -70,28 +65,22 @@ ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &patt
// public members
////////////////////////////////////////////////////////////////////////////////
ByteVectorList::ByteVectorList() :
List<ByteVector>(),
d(nullptr)
{
ByteVectorList::ByteVectorList() : List<ByteVector>(),
d(nullptr) {
}
ByteVectorList::~ByteVectorList()
{
ByteVectorList::~ByteVectorList() {
}
ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const
{
ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const {
ByteVector v;
ConstIterator it = begin();
while(it != end()) {
while (it != end()) {
v.append(*it);
it++;
if(it != end())
if (it != end())
v.append(separator);
}

View File

@@ -33,54 +33,53 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! A list of ByteVectors
//! A list of ByteVectors
/*!
/*!
* A List specialization with some handy features useful for ByteVectors.
*/
class TAGLIB_EXPORT ByteVectorList : public List<ByteVector>
{
public:
/*!
class TAGLIB_EXPORT ByteVectorList : public List<ByteVector> {
public:
/*!
* Construct an empty ByteVectorList.
*/
ByteVectorList();
ByteVectorList();
/*!
/*!
* Destroys this ByteVectorList instance.
*/
virtual ~ByteVectorList();
virtual ~ByteVectorList();
/*!
/*!
* Convert the ByteVectorList to a ByteVector separated by \a separator. By
* default a space is used.
*/
ByteVector toByteVector(const ByteVector &separator = " ") const;
ByteVector toByteVector(const ByteVector &separator = " ") const;
/*!
/*!
* Splits the ByteVector \a v into several strings at \a pattern. This will
* not include the pattern in the returned ByteVectors.
*/
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern,
int byteAlign = 1);
/*!
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern,
int byteAlign = 1);
/*!
* Splits the ByteVector \a v into several strings at \a pattern. This will
* not include the pattern in the returned ByteVectors. \a max is the
* maximum number of entries that will be separated. If \a max for instance
* is 2 then a maximum of 1 match will be found and the vector will be split
* on that match.
*/
// BIC: merge with the function above
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern,
int byteAlign, int max);
private:
class ByteVectorListPrivate;
ByteVectorListPrivate *d;
};
// BIC: merge with the function above
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern,
int byteAlign, int max);
}
}
private:
class ByteVectorListPrivate;
ByteVectorListPrivate *d;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -34,43 +34,35 @@
using namespace Strawberry_TagLib::TagLib;
class ByteVectorStream::ByteVectorStreamPrivate
{
public:
class ByteVectorStream::ByteVectorStreamPrivate {
public:
explicit ByteVectorStreamPrivate(const ByteVector &data);
ByteVector data;
long position;
};
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) :
data(_data),
position(0)
{
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) : data(_data),
position(0) {
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
ByteVectorStream::ByteVectorStream(const ByteVector &data) :
d(new ByteVectorStreamPrivate(data))
{
ByteVectorStream::ByteVectorStream(const ByteVector &data) : d(new ByteVectorStreamPrivate(data)) {
}
ByteVectorStream::~ByteVectorStream()
{
ByteVectorStream::~ByteVectorStream() {
delete d;
}
FileName ByteVectorStream::name() const
{
return FileName(""); // XXX do we need a name?
FileName ByteVectorStream::name() const {
return FileName(""); // XXX do we need a name?
}
ByteVector ByteVectorStream::readBlock(unsigned long length)
{
if(length == 0)
ByteVector ByteVectorStream::readBlock(unsigned long length) {
if (length == 0)
return ByteVector();
ByteVector v = d->data.mid(d->position, length);
@@ -78,25 +70,23 @@ ByteVector ByteVectorStream::readBlock(unsigned long length)
return v;
}
void ByteVectorStream::writeBlock(const ByteVector &data)
{
void ByteVectorStream::writeBlock(const ByteVector &data) {
unsigned int size = data.size();
if(long(d->position + size) > length()) {
if (long(d->position + size) > length()) {
truncate(d->position + size);
}
memcpy(d->data.data() + d->position, data.data(), size);
d->position += size;
}
void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
{
void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) {
long sizeDiff = data.size() - replace;
if(sizeDiff < 0) {
if (sizeDiff < 0) {
removeBlock(start + data.size(), -sizeDiff);
}
else if(sizeDiff > 0) {
else if (sizeDiff > 0) {
truncate(length() + sizeDiff);
unsigned long readPosition = start + replace;
unsigned long readPosition = start + replace;
unsigned long writePosition = start + data.size();
memmove(d->data.data() + writePosition, d->data.data() + readPosition, length() - sizeDiff - readPosition);
}
@@ -104,11 +94,10 @@ void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsig
writeBlock(data);
}
void ByteVectorStream::removeBlock(unsigned long start, unsigned long length)
{
void ByteVectorStream::removeBlock(unsigned long start, unsigned long length) {
unsigned long readPosition = start + length;
unsigned long writePosition = start;
if(readPosition < static_cast<unsigned long>(ByteVectorStream::length())) {
if (readPosition < static_cast<unsigned long>(ByteVectorStream::length())) {
unsigned long bytesToMove = ByteVectorStream::length() - readPosition;
memmove(d->data.data() + writePosition, d->data.data() + readPosition, bytesToMove);
writePosition += bytesToMove;
@@ -117,51 +106,43 @@ void ByteVectorStream::removeBlock(unsigned long start, unsigned long length)
truncate(writePosition);
}
bool ByteVectorStream::readOnly() const
{
bool ByteVectorStream::readOnly() const {
return false;
}
bool ByteVectorStream::isOpen() const
{
bool ByteVectorStream::isOpen() const {
return true;
}
void ByteVectorStream::seek(long offset, Position p)
{
switch(p) {
case Beginning:
d->position = offset;
break;
case Current:
d->position += offset;
break;
case End:
d->position = length() + offset; // offset is expected to be negative
break;
void ByteVectorStream::seek(long offset, Position p) {
switch (p) {
case Beginning:
d->position = offset;
break;
case Current:
d->position += offset;
break;
case End:
d->position = length() + offset; // offset is expected to be negative
break;
}
}
void ByteVectorStream::clear()
{
void ByteVectorStream::clear() {
}
long ByteVectorStream::tell() const
{
long ByteVectorStream::tell() const {
return d->position;
}
long ByteVectorStream::length()
{
long ByteVectorStream::length() {
return d->data.size();
}
void ByteVectorStream::truncate(long length)
{
void ByteVectorStream::truncate(long length) {
d->data.resize(length);
}
ByteVector *ByteVectorStream::data()
{
ByteVector *ByteVectorStream::data() {
return &d->data;
}

View File

@@ -34,37 +34,36 @@
namespace Strawberry_TagLib {
namespace TagLib {
class String;
class Tag;
class AudioProperties;
class String;
class Tag;
class AudioProperties;
//! In-memory Stream class using ByteVector for its storage.
//! In-memory Stream class using ByteVector for its storage.
class TAGLIB_EXPORT ByteVectorStream : public IOStream
{
public:
/*!
class TAGLIB_EXPORT ByteVectorStream : public IOStream {
public:
/*!
* Construct a File object and opens the \a file. \a file should be a
* be a C-string in the local file system encoding.
*/
ByteVectorStream(const ByteVector &data);
ByteVectorStream(const ByteVector &data);
/*!
/*!
* Destroys this ByteVectorStream instance.
*/
virtual ~ByteVectorStream();
virtual ~ByteVectorStream();
/*!
/*!
* Returns the file name in the local file system encoding.
*/
FileName name() const;
FileName name() const;
/*!
/*!
* Reads a block of size \a length at the current get pointer.
*/
ByteVector readBlock(unsigned long length);
ByteVector readBlock(unsigned long length);
/*!
/*!
* Attempts to write the block \a data at the current get pointer. If the
* file is currently only opened read only -- i.e. readOnly() returns true --
* this attempts to reopen the file in read/write mode.
@@ -73,75 +72,74 @@ namespace TagLib {
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
void writeBlock(const ByteVector &data);
void writeBlock(const ByteVector &data);
/*!
/*!
* Insert \a data at position \a start in the file overwriting \a replace
* bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file
* after the insertion point.
*/
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
/*!
/*!
* Removes a block of the file starting a \a start and continuing for
* \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file
* after the removed portion.
*/
void removeBlock(unsigned long start = 0, unsigned long length = 0);
void removeBlock(unsigned long start = 0, unsigned long length = 0);
/*!
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
bool readOnly() const;
bool readOnly() const;
/*!
/*!
* Since the file can currently only be opened as an argument to the
* constructor (sort-of by design), this returns if that open succeeded.
*/
bool isOpen() const;
bool isOpen() const;
/*!
/*!
* Move the I/O pointer to \a offset in the file from position \a p. This
* defaults to seeking from the beginning of the file.
*
* \see Position
*/
void seek(long offset, Position p = Beginning);
void seek(long offset, Position p = Beginning);
/*!
/*!
* Reset the end-of-file and error flags on the file.
*/
void clear();
void clear();
/*!
/*!
* Returns the current offset within the file.
*/
long tell() const;
long tell() const;
/*!
/*!
* Returns the length of the file.
*/
long length();
long length();
/*!
/*!
* Truncates the file to a \a length.
*/
void truncate(long length);
void truncate(long length);
ByteVector *data();
ByteVector *data();
protected:
protected:
private:
class ByteVectorStreamPrivate;
ByteVectorStreamPrivate *d;
};
private:
class ByteVectorStreamPrivate;
ByteVectorStreamPrivate *d;
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -24,43 +24,40 @@
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
#include "tdebug.h"
#include "tstring.h"
#include "tdebuglistener.h"
#include "tutils.h"
# include "tdebug.h"
# include "tstring.h"
# include "tdebuglistener.h"
# include "tutils.h"
#include <bitset>
#include <cstdio>
#include <cstdarg>
# include <bitset>
# include <cstdio>
# include <cstdarg>
namespace Strawberry_TagLib {
namespace TagLib
{
// The instance is defined in tdebuglistener.cpp.
extern DebugListener *debugListener;
namespace TagLib {
// The instance is defined in tdebuglistener.cpp.
extern DebugListener *debugListener;
void debug(const String &s)
{
debugListener->printMessage("TagLib: " + s + "\n");
}
void debug(const String &s) {
debugListener->printMessage("TagLib: " + s + "\n");
}
void debugData(const ByteVector &v)
{
for(unsigned int i = 0; i < v.size(); ++i) {
const std::string bits = std::bitset<8>(v[i]).to_string();
const String msg = Utils::formatString(
"*** [%u] - char '%c' - int %d, 0x%02x, 0b%s\n",
i, v[i], v[i], v[i], bits.c_str());
void debugData(const ByteVector &v) {
for (unsigned int i = 0; i < v.size(); ++i) {
const std::string bits = std::bitset<8>(v[i]).to_string();
const String msg = Utils::formatString(
"*** [%u] - char '%c' - int %d, 0x%02x, 0b%s\n",
i, v[i], v[i], v[i], bits.c_str());
debugListener->printMessage(msg);
}
debugListener->printMessage(msg);
}
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -29,13 +29,13 @@
namespace Strawberry_TagLib {
namespace TagLib {
class String;
class ByteVector;
class String;
class ByteVector;
#ifndef DO_NOT_DOCUMENT
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
# if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
/*!
/*!
* A simple function that outputs the debug messages to the listener.
* The default listener redirects the messages to \a stderr when NDEBUG is
* not defined.
@@ -46,9 +46,9 @@ namespace TagLib {
*
* \internal
*/
void debug(const String &s);
void debug(const String &s);
/*!
/*!
* For debugging binary data.
*
* \warning Do not use this outside of TagLib, it could lead to undefined
@@ -57,14 +57,14 @@ namespace TagLib {
*
* \internal
*/
void debugData(const ByteVector &v);
void debugData(const ByteVector &v);
#else
# else
#define debug(x) ((void)0)
#define debugData(x) ((void)0)
# define debug(x) ((void)0)
# define debugData(x) ((void)0)
#endif
# endif
}
}

View File

@@ -29,59 +29,52 @@
#include <bitset>
#ifdef _WIN32
# include <windows.h>
# include <windows.h>
#endif
using namespace Strawberry_TagLib::TagLib;
namespace
{
class DefaultListener : public DebugListener
{
public:
virtual void printMessage(const String &msg)
{
namespace {
class DefaultListener : public DebugListener {
public:
virtual void printMessage(const String &msg) {
#ifdef _WIN32
const wstring wstr = msg.toWString();
const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if(len != 0) {
std::vector<char> buf(len);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL);
const wstring wstr = msg.toWString();
const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if (len != 0) {
std::vector<char> buf(len);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL);
std::cerr << std::string(&buf[0]);
}
std::cerr << std::string(&buf[0]);
}
#else
std::cerr << msg;
std::cerr << msg;
#endif
}
};
#endif
}
};
DefaultListener defaultListener;
}
DefaultListener defaultListener;
} // namespace
namespace Strawberry_TagLib {
namespace TagLib
{
DebugListener *debugListener = &defaultListener;
namespace TagLib {
DebugListener *debugListener = &defaultListener;
DebugListener::DebugListener()
{
}
DebugListener::~DebugListener()
{
}
void setDebugListener(DebugListener *listener)
{
if(listener)
debugListener = listener;
else
debugListener = &defaultListener;
}
DebugListener::DebugListener() {
}
DebugListener::~DebugListener() {
}
void setDebugListener(DebugListener *listener) {
if (listener)
debugListener = listener;
else
debugListener = &defaultListener;
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -30,36 +30,34 @@
#include "tstring.h"
namespace Strawberry_TagLib {
namespace TagLib
{
//! An abstraction for the listener to the debug messages.
namespace TagLib {
//! An abstraction for the listener to the debug messages.
/*!
/*!
* This class enables you to handle the debug messages in your preferred
* way by subclassing this class, reimplementing printMessage() and setting
* your reimplementation as the default with setDebugListener().
*
* \see setDebugListener()
*/
class TAGLIB_EXPORT DebugListener
{
public:
DebugListener();
virtual ~DebugListener();
class TAGLIB_EXPORT DebugListener {
public:
DebugListener();
virtual ~DebugListener();
/*!
/*!
* When overridden in a derived class, redirects \a msg to your preferred
* channel such as stderr, Windows debugger or so forth.
*/
virtual void printMessage(const String &msg) = 0;
virtual void printMessage(const String &msg) = 0;
private:
// Noncopyable
DebugListener(const DebugListener &);
DebugListener &operator=(const DebugListener &);
};
private:
// Noncopyable
DebugListener(const DebugListener &);
DebugListener &operator=(const DebugListener &);
};
/*!
/*!
* Sets the listener that decides how the debug messages are redirected.
* If the parameter \a listener is null, the previous listener is released
* and default stderr listener is restored.
@@ -69,8 +67,8 @@ namespace TagLib
*
* \see DebugListener
*/
TAGLIB_EXPORT void setDebugListener(DebugListener *listener);
}
}
TAGLIB_EXPORT void setDebugListener(DebugListener *listener);
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -30,18 +30,18 @@
#include "tpropertymap.h"
#ifdef _WIN32
# include <windows.h>
# include <io.h>
# include <windows.h>
# include <io.h>
#else
# include <stdio.h>
# include <unistd.h>
# include <stdio.h>
# include <unistd.h>
#endif
#ifndef R_OK
# define R_OK 4
# define R_OK 4
#endif
#ifndef W_OK
# define W_OK 2
# define W_OK 2
#endif
#include "asffile.h"
@@ -68,21 +68,18 @@
using namespace Strawberry_TagLib::TagLib;
class File::FilePrivate
{
public:
FilePrivate(IOStream *_stream, bool _owner) :
stream(_stream),
streamOwner(_owner),
valid(true) {}
class File::FilePrivate {
public:
FilePrivate(IOStream* _stream, bool _owner) : stream(_stream),
streamOwner(_owner),
valid(true) {}
~FilePrivate()
{
if(streamOwner)
~FilePrivate() {
if (streamOwner)
delete stream;
}
IOStream *stream;
IOStream* stream;
bool streamOwner;
bool valid;
};
@@ -91,166 +88,154 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
File::File(const FileName fileName) :
d(new FilePrivate(new FileStream(fileName), true))
{
File::File(const FileName fileName) : d(new FilePrivate(new FileStream(fileName), true)) {
}
File::File(IOStream *stream) :
d(new FilePrivate(stream, false))
{
File::File(IOStream* stream) : d(new FilePrivate(stream, false)) {
}
File::~File()
{
File::~File() {
delete d;
}
FileName File::name() const
{
FileName File::name() const {
return d->stream->name();
}
PropertyMap File::properties() const
{
PropertyMap File::properties() const {
// ugly workaround until this method is virtual
if(dynamic_cast<const APE::File* >(this))
return dynamic_cast<const APE::File* >(this)->properties();
if(dynamic_cast<const FLAC::File* >(this))
return dynamic_cast<const FLAC::File* >(this)->properties();
if(dynamic_cast<const IT::File* >(this))
return dynamic_cast<const IT::File* >(this)->properties();
if(dynamic_cast<const Mod::File* >(this))
return dynamic_cast<const Mod::File* >(this)->properties();
if(dynamic_cast<const MPC::File* >(this))
return dynamic_cast<const MPC::File* >(this)->properties();
if(dynamic_cast<const MPEG::File* >(this))
return dynamic_cast<const MPEG::File* >(this)->properties();
if(dynamic_cast<const Ogg::FLAC::File* >(this))
return dynamic_cast<const Ogg::FLAC::File* >(this)->properties();
if(dynamic_cast<const Ogg::Speex::File* >(this))
return dynamic_cast<const Ogg::Speex::File* >(this)->properties();
if(dynamic_cast<const Ogg::Opus::File* >(this))
return dynamic_cast<const Ogg::Opus::File* >(this)->properties();
if(dynamic_cast<const Ogg::Vorbis::File* >(this))
return dynamic_cast<const Ogg::Vorbis::File* >(this)->properties();
if(dynamic_cast<const RIFF::AIFF::File* >(this))
return dynamic_cast<const RIFF::AIFF::File* >(this)->properties();
if(dynamic_cast<const RIFF::WAV::File* >(this))
return dynamic_cast<const RIFF::WAV::File* >(this)->properties();
if(dynamic_cast<const S3M::File* >(this))
return dynamic_cast<const S3M::File* >(this)->properties();
if(dynamic_cast<const TrueAudio::File* >(this))
return dynamic_cast<const TrueAudio::File* >(this)->properties();
if(dynamic_cast<const WavPack::File* >(this))
return dynamic_cast<const WavPack::File* >(this)->properties();
if(dynamic_cast<const XM::File* >(this))
return dynamic_cast<const XM::File* >(this)->properties();
if(dynamic_cast<const MP4::File* >(this))
return dynamic_cast<const MP4::File* >(this)->properties();
if(dynamic_cast<const ASF::File* >(this))
return dynamic_cast<const ASF::File* >(this)->properties();
if(dynamic_cast<const DSF::File* >(this))
return dynamic_cast<const DSF::File* >(this)->properties();
if(dynamic_cast<const DSDIFF::File* >(this))
return dynamic_cast<const DSDIFF::File* >(this)->properties();
if (dynamic_cast<const APE::File*>(this))
return dynamic_cast<const APE::File*>(this)->properties();
if (dynamic_cast<const FLAC::File*>(this))
return dynamic_cast<const FLAC::File*>(this)->properties();
if (dynamic_cast<const IT::File*>(this))
return dynamic_cast<const IT::File*>(this)->properties();
if (dynamic_cast<const Mod::File*>(this))
return dynamic_cast<const Mod::File*>(this)->properties();
if (dynamic_cast<const MPC::File*>(this))
return dynamic_cast<const MPC::File*>(this)->properties();
if (dynamic_cast<const MPEG::File*>(this))
return dynamic_cast<const MPEG::File*>(this)->properties();
if (dynamic_cast<const Ogg::FLAC::File*>(this))
return dynamic_cast<const Ogg::FLAC::File*>(this)->properties();
if (dynamic_cast<const Ogg::Speex::File*>(this))
return dynamic_cast<const Ogg::Speex::File*>(this)->properties();
if (dynamic_cast<const Ogg::Opus::File*>(this))
return dynamic_cast<const Ogg::Opus::File*>(this)->properties();
if (dynamic_cast<const Ogg::Vorbis::File*>(this))
return dynamic_cast<const Ogg::Vorbis::File*>(this)->properties();
if (dynamic_cast<const RIFF::AIFF::File*>(this))
return dynamic_cast<const RIFF::AIFF::File*>(this)->properties();
if (dynamic_cast<const RIFF::WAV::File*>(this))
return dynamic_cast<const RIFF::WAV::File*>(this)->properties();
if (dynamic_cast<const S3M::File*>(this))
return dynamic_cast<const S3M::File*>(this)->properties();
if (dynamic_cast<const TrueAudio::File*>(this))
return dynamic_cast<const TrueAudio::File*>(this)->properties();
if (dynamic_cast<const WavPack::File*>(this))
return dynamic_cast<const WavPack::File*>(this)->properties();
if (dynamic_cast<const XM::File*>(this))
return dynamic_cast<const XM::File*>(this)->properties();
if (dynamic_cast<const MP4::File*>(this))
return dynamic_cast<const MP4::File*>(this)->properties();
if (dynamic_cast<const ASF::File*>(this))
return dynamic_cast<const ASF::File*>(this)->properties();
if (dynamic_cast<const DSF::File*>(this))
return dynamic_cast<const DSF::File*>(this)->properties();
if (dynamic_cast<const DSDIFF::File*>(this))
return dynamic_cast<const DSDIFF::File*>(this)->properties();
return tag()->properties();
}
void File::removeUnsupportedProperties(const StringList &properties)
{
void File::removeUnsupportedProperties(const StringList& properties) {
// here we only consider those formats that could possibly contain
// unsupported properties
if(dynamic_cast<APE::File* >(this))
dynamic_cast<APE::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<FLAC::File* >(this))
dynamic_cast<FLAC::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<MPC::File* >(this))
dynamic_cast<MPC::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<MPEG::File* >(this))
dynamic_cast<MPEG::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<Ogg::Vorbis::File* >(this))
dynamic_cast<Ogg::Vorbis::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<RIFF::AIFF::File* >(this))
dynamic_cast<RIFF::AIFF::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<RIFF::WAV::File* >(this))
dynamic_cast<RIFF::WAV::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<TrueAudio::File* >(this))
dynamic_cast<TrueAudio::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<WavPack::File* >(this))
dynamic_cast<WavPack::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<MP4::File* >(this))
dynamic_cast<MP4::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<ASF::File* >(this))
dynamic_cast<ASF::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<DSF::File* >(this))
dynamic_cast<DSF::File* >(this)->removeUnsupportedProperties(properties);
else if(dynamic_cast<DSDIFF::File* >(this))
dynamic_cast<DSDIFF::File* >(this)->removeUnsupportedProperties(properties);
if (dynamic_cast<APE::File*>(this))
dynamic_cast<APE::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<FLAC::File*>(this))
dynamic_cast<FLAC::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<MPC::File*>(this))
dynamic_cast<MPC::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<MPEG::File*>(this))
dynamic_cast<MPEG::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<Ogg::Vorbis::File*>(this))
dynamic_cast<Ogg::Vorbis::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<RIFF::AIFF::File*>(this))
dynamic_cast<RIFF::AIFF::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<RIFF::WAV::File*>(this))
dynamic_cast<RIFF::WAV::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<TrueAudio::File*>(this))
dynamic_cast<TrueAudio::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<WavPack::File*>(this))
dynamic_cast<WavPack::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<MP4::File*>(this))
dynamic_cast<MP4::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<ASF::File*>(this))
dynamic_cast<ASF::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<DSF::File*>(this))
dynamic_cast<DSF::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<DSDIFF::File*>(this))
dynamic_cast<DSDIFF::File*>(this)->removeUnsupportedProperties(properties);
else
tag()->removeUnsupportedProperties(properties);
}
PropertyMap File::setProperties(const PropertyMap &properties)
{
if(dynamic_cast<APE::File* >(this))
return dynamic_cast<APE::File* >(this)->setProperties(properties);
else if(dynamic_cast<FLAC::File* >(this))
return dynamic_cast<FLAC::File* >(this)->setProperties(properties);
else if(dynamic_cast<IT::File* >(this))
return dynamic_cast<IT::File* >(this)->setProperties(properties);
else if(dynamic_cast<Mod::File* >(this))
return dynamic_cast<Mod::File* >(this)->setProperties(properties);
else if(dynamic_cast<MPC::File* >(this))
return dynamic_cast<MPC::File* >(this)->setProperties(properties);
else if(dynamic_cast<MPEG::File* >(this))
return dynamic_cast<MPEG::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::FLAC::File* >(this))
return dynamic_cast<Ogg::FLAC::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::Speex::File* >(this))
return dynamic_cast<Ogg::Speex::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::Opus::File* >(this))
return dynamic_cast<Ogg::Opus::File* >(this)->setProperties(properties);
else if(dynamic_cast<Ogg::Vorbis::File* >(this))
return dynamic_cast<Ogg::Vorbis::File* >(this)->setProperties(properties);
else if(dynamic_cast<RIFF::AIFF::File* >(this))
return dynamic_cast<RIFF::AIFF::File* >(this)->setProperties(properties);
else if(dynamic_cast<RIFF::WAV::File* >(this))
return dynamic_cast<RIFF::WAV::File* >(this)->setProperties(properties);
else if(dynamic_cast<S3M::File* >(this))
return dynamic_cast<S3M::File* >(this)->setProperties(properties);
else if(dynamic_cast<TrueAudio::File* >(this))
return dynamic_cast<TrueAudio::File* >(this)->setProperties(properties);
else if(dynamic_cast<WavPack::File* >(this))
return dynamic_cast<WavPack::File* >(this)->setProperties(properties);
else if(dynamic_cast<XM::File* >(this))
return dynamic_cast<XM::File* >(this)->setProperties(properties);
else if(dynamic_cast<MP4::File* >(this))
return dynamic_cast<MP4::File* >(this)->setProperties(properties);
else if(dynamic_cast<ASF::File* >(this))
return dynamic_cast<ASF::File* >(this)->setProperties(properties);
else if(dynamic_cast<DSF::File* >(this))
return dynamic_cast<DSF::File* >(this)->setProperties(properties);
else if(dynamic_cast<DSDIFF::File* >(this))
return dynamic_cast<DSDIFF::File* >(this)->setProperties(properties);
PropertyMap File::setProperties(const PropertyMap& properties) {
if (dynamic_cast<APE::File*>(this))
return dynamic_cast<APE::File*>(this)->setProperties(properties);
else if (dynamic_cast<FLAC::File*>(this))
return dynamic_cast<FLAC::File*>(this)->setProperties(properties);
else if (dynamic_cast<IT::File*>(this))
return dynamic_cast<IT::File*>(this)->setProperties(properties);
else if (dynamic_cast<Mod::File*>(this))
return dynamic_cast<Mod::File*>(this)->setProperties(properties);
else if (dynamic_cast<MPC::File*>(this))
return dynamic_cast<MPC::File*>(this)->setProperties(properties);
else if (dynamic_cast<MPEG::File*>(this))
return dynamic_cast<MPEG::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::FLAC::File*>(this))
return dynamic_cast<Ogg::FLAC::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::Speex::File*>(this))
return dynamic_cast<Ogg::Speex::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::Opus::File*>(this))
return dynamic_cast<Ogg::Opus::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::Vorbis::File*>(this))
return dynamic_cast<Ogg::Vorbis::File*>(this)->setProperties(properties);
else if (dynamic_cast<RIFF::AIFF::File*>(this))
return dynamic_cast<RIFF::AIFF::File*>(this)->setProperties(properties);
else if (dynamic_cast<RIFF::WAV::File*>(this))
return dynamic_cast<RIFF::WAV::File*>(this)->setProperties(properties);
else if (dynamic_cast<S3M::File*>(this))
return dynamic_cast<S3M::File*>(this)->setProperties(properties);
else if (dynamic_cast<TrueAudio::File*>(this))
return dynamic_cast<TrueAudio::File*>(this)->setProperties(properties);
else if (dynamic_cast<WavPack::File*>(this))
return dynamic_cast<WavPack::File*>(this)->setProperties(properties);
else if (dynamic_cast<XM::File*>(this))
return dynamic_cast<XM::File*>(this)->setProperties(properties);
else if (dynamic_cast<MP4::File*>(this))
return dynamic_cast<MP4::File*>(this)->setProperties(properties);
else if (dynamic_cast<ASF::File*>(this))
return dynamic_cast<ASF::File*>(this)->setProperties(properties);
else if (dynamic_cast<DSF::File*>(this))
return dynamic_cast<DSF::File*>(this)->setProperties(properties);
else if (dynamic_cast<DSDIFF::File*>(this))
return dynamic_cast<DSDIFF::File*>(this)->setProperties(properties);
else
return tag()->setProperties(properties);
}
ByteVector File::readBlock(unsigned long length)
{
ByteVector File::readBlock(unsigned long length) {
return d->stream->readBlock(length);
}
void File::writeBlock(const ByteVector &data)
{
void File::writeBlock(const ByteVector& data) {
d->stream->writeBlock(data);
}
long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before)
{
if(!d->stream || pattern.size() > bufferSize())
return -1;
long File::find(const ByteVector& pattern, long fromOffset, const ByteVector& before) {
if (!d->stream || pattern.size() > bufferSize())
return -1;
// The position in the file that the current buffer starts at.
@@ -290,21 +275,21 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
// then check for "before". The order is important because it gives priority
// to "real" matches.
for(buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
for (buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
// (1) previous partial match
if(previousPartialMatch >= 0 && int(bufferSize()) > previousPartialMatch) {
if (previousPartialMatch >= 0 && int(bufferSize()) > previousPartialMatch) {
const int patternOffset = (bufferSize() - previousPartialMatch);
if(buffer.containsAt(pattern, 0, patternOffset)) {
if (buffer.containsAt(pattern, 0, patternOffset)) {
seek(originalPosition);
return bufferOffset - bufferSize() + previousPartialMatch;
}
}
if(!before.isEmpty() && beforePreviousPartialMatch >= 0 && int(bufferSize()) > beforePreviousPartialMatch) {
if (!before.isEmpty() && beforePreviousPartialMatch >= 0 && int(bufferSize()) > beforePreviousPartialMatch) {
const int beforeOffset = (bufferSize() - beforePreviousPartialMatch);
if(buffer.containsAt(before, 0, beforeOffset)) {
if (buffer.containsAt(before, 0, beforeOffset)) {
seek(originalPosition);
return -1;
}
@@ -313,12 +298,12 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
// (2) pattern contained in current buffer
long location = buffer.find(pattern);
if(location >= 0) {
if (location >= 0) {
seek(originalPosition);
return bufferOffset + location;
}
if(!before.isEmpty() && buffer.find(before) >= 0) {
if (!before.isEmpty() && buffer.find(before) >= 0) {
seek(originalPosition);
return -1;
}
@@ -327,7 +312,7 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
previousPartialMatch = buffer.endsWithPartialMatch(pattern);
if(!before.isEmpty())
if (!before.isEmpty())
beforePreviousPartialMatch = buffer.endsWithPartialMatch(before);
bufferOffset += bufferSize();
@@ -343,10 +328,9 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
}
long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before)
{
if(!d->stream || pattern.size() > bufferSize())
return -1;
long File::rfind(const ByteVector& pattern, long fromOffset, const ByteVector& before) {
if (!d->stream || pattern.size() > bufferSize())
return -1;
// The position in the file that the current buffer starts at.
@@ -367,7 +351,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
// Start the search at the offset.
if(fromOffset == 0)
if (fromOffset == 0)
fromOffset = length();
long bufferLength = bufferSize();
@@ -375,9 +359,9 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
// See the notes in find() for an explanation of this algorithm.
while(true) {
while (true) {
if(bufferOffset > bufferLength) {
if (bufferOffset > bufferLength) {
bufferOffset -= bufferLength;
}
else {
@@ -387,7 +371,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
seek(bufferOffset);
buffer = readBlock(bufferLength);
if(buffer.isEmpty())
if (buffer.isEmpty())
break;
// TODO: (1) previous partial match
@@ -395,12 +379,12 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
// (2) pattern contained in current buffer
const long location = buffer.rfind(pattern);
if(location >= 0) {
if (location >= 0) {
seek(originalPosition);
return bufferOffset + location;
}
if(!before.isEmpty() && buffer.find(before) >= 0) {
if (!before.isEmpty() && buffer.find(before) >= 0) {
seek(originalPosition);
return -1;
}
@@ -417,58 +401,47 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
return -1;
}
void File::insert(const ByteVector &data, unsigned long start, unsigned long replace)
{
void File::insert(const ByteVector& data, unsigned long start, unsigned long replace) {
d->stream->insert(data, start, replace);
}
void File::removeBlock(unsigned long start, unsigned long length)
{
void File::removeBlock(unsigned long start, unsigned long length) {
d->stream->removeBlock(start, length);
}
bool File::readOnly() const
{
bool File::readOnly() const {
return d->stream->readOnly();
}
bool File::isOpen() const
{
bool File::isOpen() const {
return d->stream->isOpen();
}
bool File::isValid() const
{
bool File::isValid() const {
return isOpen() && d->valid;
}
void File::seek(long offset, Position p)
{
void File::seek(long offset, Position p) {
d->stream->seek(offset, IOStream::Position(p));
}
void File::truncate(long length)
{
void File::truncate(long length) {
d->stream->truncate(length);
}
void File::clear()
{
void File::clear() {
d->stream->clear();
}
long File::tell() const
{
long File::tell() const {
return d->stream->tell();
}
long File::length()
{
long File::length() {
return d->stream->length();
}
bool File::isReadable(const char *file)
{
bool File::isReadable(const char* file) {
#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later
@@ -479,11 +452,9 @@ bool File::isReadable(const char *file)
return access(file, R_OK) == 0;
#endif
}
bool File::isWritable(const char *file)
{
bool File::isWritable(const char* file) {
#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later
@@ -494,20 +465,16 @@ bool File::isWritable(const char *file)
return access(file, W_OK) == 0;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
unsigned int File::bufferSize()
{
unsigned int File::bufferSize() {
return 1024;
}
void File::setValid(bool valid)
{
void File::setValid(bool valid) {
d->valid = valid;
}

View File

@@ -35,68 +35,67 @@
namespace Strawberry_TagLib {
namespace TagLib {
class String;
class Tag;
class AudioProperties;
class PropertyMap;
class String;
class Tag;
class AudioProperties;
class PropertyMap;
//! A file class with some useful methods for tag manipulation
//! A file class with some useful methods for tag manipulation
/*!
/*!
* This class is a basic file class with some methods that are particularly
* useful for tag editors. It has methods to take advantage of
* ByteVector and a binary search method for finding patterns in a file.
*/
class TAGLIB_EXPORT File
{
public:
/*!
class TAGLIB_EXPORT File {
public:
/*!
* Position in the file used for seeking.
*/
enum Position {
//! Seek from the beginning of the file.
Beginning,
//! Seek from the current position in the file.
Current,
//! Seek from the end of the file.
End
};
enum Position {
//! Seek from the beginning of the file.
Beginning,
//! Seek from the current position in the file.
Current,
//! Seek from the end of the file.
End
};
/*!
/*!
* Specify which tags to strip either explicitly, or on save.
*/
enum StripTags {
StripNone, //<! Don't strip any tags
StripOthers //<! Strip all tags not explicitly referenced in method call
};
enum StripTags {
StripNone, //<! Don't strip any tags
StripOthers //<! Strip all tags not explicitly referenced in method call
};
/*!
/*!
* Used to specify if when saving files, if values between different tag
* types should be syncronized.
*/
enum DuplicateTags {
Duplicate, //<! Syncronize values between different tag types
DoNotDuplicate //<! Do not syncronize values between different tag types
};
enum DuplicateTags {
Duplicate, //<! Syncronize values between different tag types
DoNotDuplicate //<! Do not syncronize values between different tag types
};
/*!
/*!
* Destroys this File instance.
*/
virtual ~File();
virtual ~File();
/*!
/*!
* Returns the file name in the local file system encoding.
*/
FileName name() const;
FileName name() const;
/*!
/*!
* Returns a pointer to this file's tag. This should be reimplemented in
* the concrete subclasses.
*/
virtual Tag *tag() const = 0;
virtual Tag *tag() const = 0;
/*!
/*!
* Exports the tags of the file as dictionary mapping (human readable) tag
* names (uppercase Strings) to StringLists of tag values. Calls the according
* specialization in the File subclasses.
@@ -108,17 +107,17 @@ namespace TagLib {
* tag) only the most "modern" one will be exported (ID3v2 in this case).
* BIC: Will be made virtual in future releases.
*/
PropertyMap properties() const;
PropertyMap properties() const;
/*!
/*!
* Removes unsupported properties, or a subset of them, from the file's metadata.
* The parameter \a properties must contain only entries from
* properties().unsupportedData().
* BIC: Will be mad virtual in future releases.
*/
void removeUnsupportedProperties(const StringList& properties);
void removeUnsupportedProperties(const StringList &properties);
/*!
/*!
* Sets the tags of this File to those specified in \a properties. Calls the
* according specialization method in the subclasses of File to do the translation
* into the format-specific details.
@@ -132,16 +131,16 @@ namespace TagLib {
* See the documentation of the subclass implementations for detailed descriptions.
* BIC: will become pure virtual in the future
*/
PropertyMap setProperties(const PropertyMap &properties);
PropertyMap setProperties(const PropertyMap &properties);
/*!
/*!
* Returns a pointer to this file's audio properties. This should be
* reimplemented in the concrete subclasses. If no audio properties were
* read then this will return a null pointer.
*/
virtual AudioProperties *audioProperties() const = 0;
virtual AudioProperties *audioProperties() const = 0;
/*!
/*!
* Save the file and its associated tags. This should be reimplemented in
* the concrete subclasses. Returns true if the save succeeds.
*
@@ -151,14 +150,14 @@ namespace TagLib {
* must insure that you are only doing writes to a particular file from one
* of them.
*/
virtual bool save() = 0;
virtual bool save() = 0;
/*!
/*!
* Reads a block of size \a length at the current get pointer.
*/
ByteVector readBlock(unsigned long length);
ByteVector readBlock(unsigned long length);
/*!
/*!
* Attempts to write the block \a data at the current get pointer. If the
* file is currently only opened read only -- i.e. readOnly() returns true --
* this attempts to reopen the file in read/write mode.
@@ -167,9 +166,9 @@ namespace TagLib {
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
void writeBlock(const ByteVector &data);
void writeBlock(const ByteVector &data);
/*!
/*!
* Returns the offset in the file that \a pattern occurs at or -1 if it can
* not be found. If \a before is set, the search will only continue until the
* pattern \a before is found. This is useful for tagging purposes to search
@@ -181,11 +180,11 @@ namespace TagLib {
* \note This has the practical limitation that \a pattern can not be longer
* than the buffer size used by readBlock(). Currently this is 1024 bytes.
*/
long find(const ByteVector &pattern,
long fromOffset = 0,
const ByteVector &before = ByteVector());
long find(const ByteVector &pattern,
long fromOffset = 0,
const ByteVector &before = ByteVector());
/*!
/*!
* Returns the offset in the file that \a pattern occurs at or -1 if it can
* not be found. If \a before is set, the search will only continue until the
* pattern \a before is found. This is useful for tagging purposes to search
@@ -197,93 +196,93 @@ namespace TagLib {
* \note This has the practical limitation that \a pattern can not be longer
* than the buffer size used by readBlock(). Currently this is 1024 bytes.
*/
long rfind(const ByteVector &pattern,
long fromOffset = 0,
const ByteVector &before = ByteVector());
long rfind(const ByteVector &pattern,
long fromOffset = 0,
const ByteVector &before = ByteVector());
/*!
/*!
* Insert \a data at position \a start in the file overwriting \a replace
* bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file
* after the insertion point.
*/
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
/*!
/*!
* Removes a block of the file starting a \a start and continuing for
* \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file
* after the removed portion.
*/
void removeBlock(unsigned long start = 0, unsigned long length = 0);
void removeBlock(unsigned long start = 0, unsigned long length = 0);
/*!
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
bool readOnly() const;
bool readOnly() const;
/*!
/*!
* Since the file can currently only be opened as an argument to the
* constructor (sort-of by design), this returns if that open succeeded.
*/
bool isOpen() const;
bool isOpen() const;
/*!
/*!
* Returns true if the file is open and readable.
*/
bool isValid() const;
bool isValid() const;
/*!
/*!
* Move the I/O pointer to \a offset in the file from position \a p. This
* defaults to seeking from the beginning of the file.
*
* \see Position
*/
void seek(long offset, Position p = Beginning);
void seek(long offset, Position p = Beginning);
/*!
/*!
* Reset the end-of-file and error flags on the file.
*/
void clear();
void clear();
/*!
/*!
* Returns the current offset within the file.
*/
long tell() const;
long tell() const;
/*!
/*!
* Returns the length of the file.
*/
long length();
long length();
/*!
/*!
* Returns true if \a file can be opened for reading. If the file does not
* exist, this will return false.
*
* \deprecated
*/
TAGLIB_DEPRECATED static bool isReadable(const char *file);
TAGLIB_DEPRECATED static bool isReadable(const char *file);
/*!
/*!
* Returns true if \a file can be opened for writing.
*
* \deprecated
*/
TAGLIB_DEPRECATED static bool isWritable(const char *name);
TAGLIB_DEPRECATED static bool isWritable(const char *name);
protected:
/*!
protected:
/*!
* Construct a File object and opens the \a file. \a file should be a
* be a C-string in the local file system encoding.
*
* \note Constructor is protected since this class should only be
* instantiated through subclasses.
*/
File(FileName file);
File(FileName file);
/*!
/*!
* Construct a File object and use the \a stream instance.
*
* \note TagLib will *not* take ownership of the stream, the caller is
@@ -292,34 +291,34 @@ namespace TagLib {
* \note Constructor is protected since this class should only be
* instantiated through subclasses.
*/
File(IOStream *stream);
File(IOStream *stream);
/*!
/*!
* Marks the file as valid or invalid.
*
* \see isValid()
*/
void setValid(bool valid);
void setValid(bool valid);
/*!
/*!
* Truncates the file to a \a length.
*/
void truncate(long length);
void truncate(long length);
/*!
/*!
* Returns the buffer size that is used for internal buffering.
*/
static unsigned int bufferSize();
static unsigned int bufferSize();
private:
File(const File &);
File &operator=(const File &);
private:
File(const File &);
File &operator=(const File &);
class FilePrivate;
FilePrivate *d;
};
class FilePrivate;
FilePrivate *d;
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -28,112 +28,96 @@
#include "tdebug.h"
#ifdef _WIN32
# include <windows.h>
# include <windows.h>
#else
# include <stdio.h>
# include <unistd.h>
# include <stdio.h>
# include <unistd.h>
#endif
using namespace Strawberry_TagLib::TagLib;
namespace
{
namespace {
#ifdef _WIN32
// Uses Win32 native API instead of POSIX API to reduce the resource consumption.
// Uses Win32 native API instead of POSIX API to reduce the resource consumption.
typedef FileName FileNameHandle;
typedef HANDLE FileHandle;
typedef FileName FileNameHandle;
typedef HANDLE FileHandle;
const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE;
const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE;
FileHandle openFile(const FileName &path, bool readOnly)
{
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
FileHandle openFile(const FileName &path, bool readOnly) {
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
#if defined (PLATFORM_WINRT)
return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
#else
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
#endif
}
FileHandle openFile(const int, bool)
{
return InvalidFileHandle;
}
void closeFile(FileHandle file)
{
CloseHandle(file);
}
size_t readFile(FileHandle file, ByteVector &buffer)
{
DWORD length;
if(ReadFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
return static_cast<size_t>(length);
else
return 0;
}
size_t writeFile(FileHandle file, const ByteVector &buffer)
{
DWORD length;
if(WriteFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
return static_cast<size_t>(length);
else
return 0;
}
#else // _WIN32
struct FileNameHandle : public std::string
{
explicit FileNameHandle(FileName name) : std::string(name) {}
operator FileName () const { return c_str(); }
};
typedef FILE* FileHandle;
const FileHandle InvalidFileHandle = 0;
FileHandle openFile(const FileName &path, bool readOnly)
{
return fopen(path, readOnly ? "rb" : "rb+");
}
FileHandle openFile(const int fileDescriptor, bool readOnly)
{
return fdopen(fileDescriptor, readOnly ? "rb" : "rb+");
}
void closeFile(FileHandle file)
{
fclose(file);
}
size_t readFile(FileHandle file, ByteVector &buffer)
{
return fread(buffer.data(), sizeof(char), buffer.size(), file);
}
size_t writeFile(FileHandle file, const ByteVector &buffer)
{
return fwrite(buffer.data(), sizeof(char), buffer.size(), file);
}
#endif // _WIN32
# if defined(PLATFORM_WINRT)
return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
# else
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
# endif
}
class FileStream::FileStreamPrivate
{
public:
FileHandle openFile(const int, bool) {
return InvalidFileHandle;
}
void closeFile(FileHandle file) {
CloseHandle(file);
}
size_t readFile(FileHandle file, ByteVector &buffer) {
DWORD length;
if (ReadFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
return static_cast<size_t>(length);
else
return 0;
}
size_t writeFile(FileHandle file, const ByteVector &buffer) {
DWORD length;
if (WriteFile(file, buffer.data(), static_cast<DWORD>(buffer.size()), &length, NULL))
return static_cast<size_t>(length);
else
return 0;
}
#else // _WIN32
struct FileNameHandle : public std::string {
explicit FileNameHandle(FileName name) : std::string(name) {}
operator FileName() const { return c_str(); }
};
typedef FILE *FileHandle;
const FileHandle InvalidFileHandle = 0;
FileHandle openFile(const FileName &path, bool readOnly) {
return fopen(path, readOnly ? "rb" : "rb+");
}
FileHandle openFile(const int fileDescriptor, bool readOnly) {
return fdopen(fileDescriptor, readOnly ? "rb" : "rb+");
}
void closeFile(FileHandle file) {
fclose(file);
}
size_t readFile(FileHandle file, ByteVector &buffer) {
return fread(buffer.data(), sizeof(char), buffer.size(), file);
}
size_t writeFile(FileHandle file, const ByteVector &buffer) {
return fwrite(buffer.data(), sizeof(char), buffer.size(), file);
}
#endif // _WIN32
} // namespace
class FileStream::FileStreamPrivate {
public:
explicit FileStreamPrivate(const FileName &fileName)
: file(InvalidFileHandle)
, name(fileName)
, readOnly(true)
{
: file(InvalidFileHandle), name(fileName), readOnly(true) {
}
FileHandle file;
@@ -146,68 +130,63 @@ public:
////////////////////////////////////////////////////////////////////////////////
FileStream::FileStream(FileName fileName, bool openReadOnly)
: d(new FileStreamPrivate(fileName))
{
: d(new FileStreamPrivate(fileName)) {
// First try with read / write mode, if that fails, fall back to read only.
if(!openReadOnly)
if (!openReadOnly)
d->file = openFile(fileName, false);
if(d->file != InvalidFileHandle)
if (d->file != InvalidFileHandle)
d->readOnly = false;
else
d->file = openFile(fileName, true);
if(d->file == InvalidFileHandle)
# ifdef _WIN32
if (d->file == InvalidFileHandle)
#ifdef _WIN32
debug("Could not open file " + fileName.toString());
# else
#else
debug("Could not open file " + String(static_cast<const char *>(d->name)));
# endif
#endif
}
FileStream::FileStream(int fileDescriptor, bool openReadOnly)
: d(new FileStreamPrivate(""))
{
: d(new FileStreamPrivate("")) {
// First try with read / write mode, if that fails, fall back to read only.
if(!openReadOnly)
if (!openReadOnly)
d->file = openFile(fileDescriptor, false);
if(d->file != InvalidFileHandle)
if (d->file != InvalidFileHandle)
d->readOnly = false;
else
d->file = openFile(fileDescriptor, true);
if(d->file == InvalidFileHandle)
if (d->file == InvalidFileHandle)
debug("Could not open file using file descriptor");
}
FileStream::~FileStream()
{
if(isOpen())
FileStream::~FileStream() {
if (isOpen())
closeFile(d->file);
delete d;
}
FileName FileStream::name() const
{
FileName FileStream::name() const {
return d->name;
}
ByteVector FileStream::readBlock(unsigned long length)
{
if(!isOpen()) {
ByteVector FileStream::readBlock(unsigned long length) {
if (!isOpen()) {
debug("FileStream::readBlock() -- invalid file.");
return ByteVector();
}
if(length == 0)
if (length == 0)
return ByteVector();
const unsigned long streamLength = static_cast<unsigned long>(FileStream::length());
if(length > bufferSize() && length > streamLength)
if (length > bufferSize() && length > streamLength)
length = streamLength;
ByteVector buffer(static_cast<unsigned int>(length));
@@ -218,14 +197,13 @@ ByteVector FileStream::readBlock(unsigned long length)
return buffer;
}
void FileStream::writeBlock(const ByteVector &data)
{
if(!isOpen()) {
void FileStream::writeBlock(const ByteVector &data) {
if (!isOpen()) {
debug("FileStream::writeBlock() -- invalid file.");
return;
}
if(readOnly()) {
if (readOnly()) {
debug("FileStream::writeBlock() -- read only file.");
return;
}
@@ -233,24 +211,23 @@ void FileStream::writeBlock(const ByteVector &data)
writeFile(d->file, data);
}
void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
{
if(!isOpen()) {
void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) {
if (!isOpen()) {
debug("FileStream::insert() -- invalid file.");
return;
}
if(readOnly()) {
if (readOnly()) {
debug("FileStream::insert() -- read only file.");
return;
}
if(data.size() == replace) {
if (data.size() == replace) {
seek(start);
writeBlock(data);
return;
}
else if(data.size() < replace) {
else if (data.size() < replace) {
seek(start);
writeBlock(data);
removeBlock(start + data.size(), replace - data.size());
@@ -269,7 +246,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
unsigned long bufferLength = bufferSize();
while(data.size() - replace > bufferLength)
while (data.size() - replace > bufferLength)
bufferLength += bufferSize();
// Set where to start the reading and writing.
@@ -280,7 +257,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
ByteVector buffer = data;
ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
while(true) {
while (true) {
// Seek to the current read position and read the data that we're about
// to overwrite. Appropriately increment the readPosition.
@@ -292,7 +269,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
// Check to see if we just read the last block. We need to call clear()
// if we did so that the last write succeeds.
if(bytesRead < bufferLength)
if (bytesRead < bufferLength)
clear();
// Seek to the write position and write our buffer. Increment the
@@ -303,7 +280,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
// We hit the end of the file.
if(bytesRead == 0)
if (bytesRead == 0)
break;
writePosition += buffer.size();
@@ -314,9 +291,8 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
}
}
void FileStream::removeBlock(unsigned long start, unsigned long length)
{
if(!isOpen()) {
void FileStream::removeBlock(unsigned long start, unsigned long length) {
if (!isOpen()) {
debug("FileStream::removeBlock() -- invalid file.");
return;
}
@@ -328,7 +304,7 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
ByteVector buffer(static_cast<unsigned int>(bufferLength));
for(unsigned int bytesRead = -1; bytesRead != 0;) {
for (unsigned int bytesRead = -1; bytesRead != 0;) {
seek(readPosition);
bytesRead = static_cast<unsigned int>(readFile(d->file, buffer));
readPosition += bytesRead;
@@ -336,7 +312,7 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
// Check to see if we just read the last block. We need to call clear()
// if we did so that the last write succeeds.
if(bytesRead < buffer.size()) {
if (bytesRead < buffer.size()) {
clear();
buffer.resize(bytesRead);
}
@@ -350,26 +326,23 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
truncate(writePosition);
}
bool FileStream::readOnly() const
{
bool FileStream::readOnly() const {
return d->readOnly;
}
bool FileStream::isOpen() const
{
bool FileStream::isOpen() const {
return (d->file != InvalidFileHandle);
}
void FileStream::seek(long offset, Position p)
{
if(!isOpen()) {
void FileStream::seek(long offset, Position p) {
if (!isOpen()) {
debug("FileStream::seek() -- invalid file.");
return;
}
#ifdef _WIN32
if(p != Beginning && p != Current && p != End) {
if (p != Beginning && p != Current && p != End) {
debug("FileStream::seek() -- Invalid Position value.");
return;
}
@@ -377,26 +350,26 @@ void FileStream::seek(long offset, Position p)
LARGE_INTEGER liOffset;
liOffset.QuadPart = offset;
if(!SetFilePointerEx(d->file, liOffset, NULL, static_cast<DWORD>(p))) {
if (!SetFilePointerEx(d->file, liOffset, NULL, static_cast<DWORD>(p))) {
debug("FileStream::seek() -- Failed to set the file pointer.");
}
#else
int whence;
switch(p) {
case Beginning:
whence = SEEK_SET;
break;
case Current:
whence = SEEK_CUR;
break;
case End:
whence = SEEK_END;
break;
default:
debug("FileStream::seek() -- Invalid Position value.");
return;
switch (p) {
case Beginning:
whence = SEEK_SET;
break;
case Current:
whence = SEEK_CUR;
break;
case End:
whence = SEEK_END;
break;
default:
debug("FileStream::seek() -- Invalid Position value.");
return;
}
fseek(d->file, offset, whence);
@@ -404,8 +377,7 @@ void FileStream::seek(long offset, Position p)
#endif
}
void FileStream::clear()
{
void FileStream::clear() {
#ifdef _WIN32
// NOP
@@ -417,15 +389,14 @@ void FileStream::clear()
#endif
}
long FileStream::tell() const
{
long FileStream::tell() const {
#ifdef _WIN32
const LARGE_INTEGER zero = {};
LARGE_INTEGER position;
if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
position.QuadPart <= LONG_MAX) {
if (SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
position.QuadPart <= LONG_MAX) {
return static_cast<long>(position.QuadPart);
}
else {
@@ -440,9 +411,8 @@ long FileStream::tell() const
#endif
}
long FileStream::length()
{
if(!isOpen()) {
long FileStream::length() {
if (!isOpen()) {
debug("FileStream::length() -- invalid file.");
return 0;
}
@@ -451,7 +421,7 @@ long FileStream::length()
LARGE_INTEGER fileSize;
if(GetFileSizeEx(d->file, &fileSize) && fileSize.QuadPart <= LONG_MAX) {
if (GetFileSizeEx(d->file, &fileSize) && fileSize.QuadPart <= LONG_MAX) {
return static_cast<long>(fileSize.QuadPart);
}
else {
@@ -477,15 +447,14 @@ long FileStream::length()
// protected members
////////////////////////////////////////////////////////////////////////////////
void FileStream::truncate(long length)
{
void FileStream::truncate(long length) {
#ifdef _WIN32
const long currentPos = tell();
seek(length);
if(!SetEndOfFile(d->file)) {
if (!SetEndOfFile(d->file)) {
debug("FileStream::truncate() -- Failed to truncate the file.");
}
@@ -495,13 +464,12 @@ void FileStream::truncate(long length)
fflush(d->file);
const int error = ftruncate(fileno(d->file), length);
if(error != 0)
if (error != 0)
debug("FileStream::truncate() -- Coundn't truncate the file.");
#endif
}
unsigned int FileStream::bufferSize()
{
unsigned int FileStream::bufferSize() {
return 1024;
}

View File

@@ -34,48 +34,47 @@
namespace Strawberry_TagLib {
namespace TagLib {
class String;
class Tag;
class AudioProperties;
class String;
class Tag;
class AudioProperties;
//! A file class with some useful methods for tag manipulation
//! A file class with some useful methods for tag manipulation
/*!
/*!
* This class is a basic file class with some methods that are particularly
* useful for tag editors. It has methods to take advantage of
* ByteVector and a binary search method for finding patterns in a file.
*/
class TAGLIB_EXPORT FileStream : public IOStream
{
public:
/*!
class TAGLIB_EXPORT FileStream : public IOStream {
public:
/*!
* Construct a File object and opens the \a file. \a file should be a
* be a C-string in the local file system encoding.
*/
FileStream(FileName file, bool openReadOnly = false);
FileStream(FileName file, bool openReadOnly = false);
/*!
/*!
* Construct a File object and opens the \a file using file descriptor.
*/
FileStream(int fileDescriptor, bool openReadOnly = false);
FileStream(int fileDescriptor, bool openReadOnly = false);
/*!
/*!
* Destroys this FileStream instance.
*/
virtual ~FileStream();
virtual ~FileStream();
/*!
/*!
* Returns the file name in the local file system encoding.
*/
FileName name() const;
FileName name() const;
/*!
/*!
* Reads a block of size \a length at the current get pointer.
*/
ByteVector readBlock(unsigned long length);
ByteVector readBlock(unsigned long length);
/*!
/*!
* Attempts to write the block \a data at the current get pointer. If the
* file is currently only opened read only -- i.e. readOnly() returns true --
* this attempts to reopen the file in read/write mode.
@@ -84,78 +83,77 @@ namespace TagLib {
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
void writeBlock(const ByteVector &data);
void writeBlock(const ByteVector &data);
/*!
/*!
* Insert \a data at position \a start in the file overwriting \a replace
* bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file
* after the insertion point.
*/
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
/*!
/*!
* Removes a block of the file starting a \a start and continuing for
* \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file
* after the removed portion.
*/
void removeBlock(unsigned long start = 0, unsigned long length = 0);
void removeBlock(unsigned long start = 0, unsigned long length = 0);
/*!
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
bool readOnly() const;
bool readOnly() const;
/*!
/*!
* Since the file can currently only be opened as an argument to the
* constructor (sort-of by design), this returns if that open succeeded.
*/
bool isOpen() const;
bool isOpen() const;
/*!
/*!
* Move the I/O pointer to \a offset in the file from position \a p. This
* defaults to seeking from the beginning of the file.
*
* \see Position
*/
void seek(long offset, Position p = Beginning);
void seek(long offset, Position p = Beginning);
/*!
/*!
* Reset the end-of-file and error flags on the file.
*/
void clear();
void clear();
/*!
/*!
* Returns the current offset within the file.
*/
long tell() const;
long tell() const;
/*!
/*!
* Returns the length of the file.
*/
long length();
long length();
/*!
/*!
* Truncates the file to a \a length.
*/
void truncate(long length);
void truncate(long length);
protected:
/*!
protected:
/*!
* Returns the buffer size that is used for internal buffering.
*/
static unsigned int bufferSize();
static unsigned int bufferSize();
private:
class FileStreamPrivate;
FileStreamPrivate *d;
};
private:
class FileStreamPrivate;
FileStreamPrivate *d;
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -24,8 +24,8 @@
***************************************************************************/
#ifdef _WIN32
# include <windows.h>
# include <tstring.h>
# include <windows.h>
# include <tstring.h>
#endif
#include "tiostream.h"
@@ -34,63 +34,50 @@ using namespace Strawberry_TagLib::TagLib;
#ifdef _WIN32
namespace
{
std::wstring ansiToUnicode(const char *str)
{
const int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
if(len == 0)
return std::wstring();
namespace {
std::wstring ansiToUnicode(const char *str) {
const int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
if (len == 0)
return std::wstring();
std::wstring wstr(len - 1, L'\0');
MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], len);
std::wstring wstr(len - 1, L'\0');
MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], len);
return wstr;
}
return wstr;
}
} // namespace
// m_name is no longer used, but kept for backward compatibility.
FileName::FileName(const wchar_t *name) :
m_name(),
m_wname(name)
{
FileName::FileName(const wchar_t *name) : m_name(),
m_wname(name) {
}
FileName::FileName(const char *name) :
m_name(),
m_wname(ansiToUnicode(name))
{
FileName::FileName(const char *name) : m_name(),
m_wname(ansiToUnicode(name)) {
}
FileName::FileName(const FileName &name) :
m_name(),
m_wname(name.m_wname)
{
FileName::FileName(const FileName &name) : m_name(),
m_wname(name.m_wname) {
}
FileName::operator const wchar_t *() const
{
FileName::operator const wchar_t *() const {
return m_wname.c_str();
}
FileName::operator const char *() const
{
FileName::operator const char *() const {
return m_name.c_str();
}
const std::wstring &FileName::wstr() const
{
const std::wstring &FileName::wstr() const {
return m_wname;
}
const std::string &FileName::str() const
{
const std::string &FileName::str() const {
return m_name;
}
String FileName::toString() const
{
String FileName::toString() const {
return String(m_wname.c_str());
}
@@ -100,15 +87,11 @@ String FileName::toString() const
// public members
////////////////////////////////////////////////////////////////////////////////
IOStream::IOStream()
{
IOStream::IOStream() {
}
IOStream::~IOStream()
{
IOStream::~IOStream() {
}
void IOStream::clear()
{
void IOStream::clear() {
}

View File

@@ -34,65 +34,63 @@ namespace Strawberry_TagLib {
namespace TagLib {
#ifdef _WIN32
class TAGLIB_EXPORT FileName
{
public:
FileName(const wchar_t *name);
FileName(const char *name);
class TAGLIB_EXPORT FileName {
public:
FileName(const wchar_t *name);
FileName(const char *name);
FileName(const FileName &name);
FileName(const FileName &name);
operator const wchar_t *() const;
operator const char *() const;
operator const wchar_t *() const;
operator const char *() const;
const std::wstring &wstr() const;
const std::string &str() const;
const std::wstring &wstr() const;
const std::string &str() const;
String toString() const;
String toString() const;
private:
const std::string m_name;
const std::wstring m_wname;
};
private:
const std::string m_name;
const std::wstring m_wname;
};
#else
typedef const char *FileName;
typedef const char *FileName;
#endif
//! An abstract class that provides operations on a sequence of bytes
//! An abstract class that provides operations on a sequence of bytes
class TAGLIB_EXPORT IOStream
{
public:
/*!
class TAGLIB_EXPORT IOStream {
public:
/*!
* Position in the file used for seeking.
*/
enum Position {
//! Seek from the beginning of the file.
Beginning,
//! Seek from the current position in the file.
Current,
//! Seek from the end of the file.
End
};
enum Position {
//! Seek from the beginning of the file.
Beginning,
//! Seek from the current position in the file.
Current,
//! Seek from the end of the file.
End
};
IOStream();
IOStream();
/*!
/*!
* Destroys this IOStream instance.
*/
virtual ~IOStream();
virtual ~IOStream();
/*!
/*!
* Returns the stream name in the local file system encoding.
*/
virtual FileName name() const = 0;
virtual FileName name() const = 0;
/*!
/*!
* Reads a block of size \a length at the current get pointer.
*/
virtual ByteVector readBlock(unsigned long length) = 0;
virtual ByteVector readBlock(unsigned long length) = 0;
/*!
/*!
* Attempts to write the block \a data at the current get pointer. If the
* file is currently only opened read only -- i.e. readOnly() returns true --
* this attempts to reopen the file in read/write mode.
@@ -101,72 +99,72 @@ namespace TagLib {
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
virtual void writeBlock(const ByteVector &data) = 0;
virtual void writeBlock(const ByteVector &data) = 0;
/*!
/*!
* Insert \a data at position \a start in the file overwriting \a replace
* bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file
* after the insertion point.
*/
virtual void insert(const ByteVector &data,
unsigned long start = 0, unsigned long replace = 0) = 0;
virtual void insert(const ByteVector &data,
unsigned long start = 0, unsigned long replace = 0) = 0;
/*!
/*!
* Removes a block of the file starting a \a start and continuing for
* \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file
* after the removed portion.
*/
virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0;
virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0;
/*!
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
virtual bool readOnly() const = 0;
virtual bool readOnly() const = 0;
/*!
/*!
* Since the file can currently only be opened as an argument to the
* constructor (sort-of by design), this returns if that open succeeded.
*/
virtual bool isOpen() const = 0;
virtual bool isOpen() const = 0;
/*!
/*!
* Move the I/O pointer to \a offset in the stream from position \a p. This
* defaults to seeking from the beginning of the stream.
*
* \see Position
*/
virtual void seek(long offset, Position p = Beginning) = 0;
virtual void seek(long offset, Position p = Beginning) = 0;
/*!
/*!
* Reset the end-of-stream and error flags on the stream.
*/
virtual void clear();
virtual void clear();
/*!
/*!
* Returns the current offset within the stream.
*/
virtual long tell() const = 0;
virtual long tell() const = 0;
/*!
/*!
* Returns the length of the stream.
*/
virtual long length() = 0;
virtual long length() = 0;
/*!
/*!
* Truncates the stream to a \a length.
*/
virtual void truncate(long length) = 0;
virtual void truncate(long length) = 0;
private:
IOStream(const IOStream &);
IOStream &operator=(const IOStream &);
};
private:
IOStream(const IOStream &);
IOStream &operator=(const IOStream &);
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -33,9 +33,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! A generic, implicitly shared list.
//! A generic, implicitly shared list.
/*!
/*!
* This is basic generic list that's somewhere between a std::list and a
* QValueList. This class is implicitly shared. For example:
*
@@ -51,155 +51,154 @@ namespace TagLib {
* only \e then will the data be copied.
*/
template <class T> class List
{
public:
template<class T> class List {
public:
#ifndef DO_NOT_DOCUMENT
typedef typename std::list<T>::iterator Iterator;
typedef typename std::list<T>::const_iterator ConstIterator;
typedef typename std::list<T>::iterator Iterator;
typedef typename std::list<T>::const_iterator ConstIterator;
#endif
/*!
/*!
* Constructs an empty list.
*/
List();
List();
/*!
/*!
* 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.
*/
List(const List<T> &l);
List(const List<T> &l);
/*!
/*!
* Destroys this List instance. If auto deletion is enabled and this list
* contains a pointer type all of the members are also deleted.
*/
virtual ~List();
virtual ~List();
/*!
/*!
* Returns an STL style iterator to the beginning of the list. See
* std::list::const_iterator for the semantics.
*/
Iterator begin();
Iterator begin();
/*!
/*!
* Returns an STL style constant iterator to the beginning of the list. See
* std::list::iterator for the semantics.
*/
ConstIterator begin() const;
ConstIterator begin() const;
/*!
/*!
* Returns an STL style iterator to the end of the list. See
* std::list::iterator for the semantics.
*/
Iterator end();
Iterator end();
/*!
/*!
* Returns an STL style constant iterator to the end of the list. See
* std::list::const_iterator for the semantics.
*/
ConstIterator end() const;
ConstIterator end() const;
/*!
/*!
* Inserts a copy of \a value before \a it.
*/
Iterator insert(Iterator it, const T &value);
Iterator insert(Iterator it, const T &value);
/*!
/*!
* Inserts the \a value into the list. This assumes that the list is
* currently sorted. If \a unique is true then the value will not
* be inserted if it is already in the list.
*/
List<T> &sortedInsert(const T &value, bool unique = false);
List<T> &sortedInsert(const T &value, bool unique = false);
/*!
/*!
* Appends \a item to the end of the list and returns a reference to the
* list.
*/
List<T> &append(const T &item);
List<T> &append(const T &item);
/*!
/*!
* Appends all of the values in \a l to the end of the list and returns a
* reference to the list.
*/
List<T> &append(const List<T> &l);
List<T> &append(const List<T> &l);
/*!
/*!
* Prepends \a item to the beginning list and returns a reference to the
* list.
*/
List<T> &prepend(const T &item);
List<T> &prepend(const T &item);
/*!
/*!
* Prepends all of the items in \a l to the beginning list and returns a
* reference to the list.
*/
List<T> &prepend(const List<T> &l);
List<T> &prepend(const List<T> &l);
/*!
/*!
* Clears the list. If auto deletion is enabled and this list contains a
* pointer type the members are also deleted.
*
* \see setAutoDelete()
*/
List<T> &clear();
List<T> &clear();
/*!
/*!
* Returns the number of elements in the list.
*
* \see isEmpty()
*/
unsigned int size() const;
unsigned int size() const;
/*!
/*!
* Returns whether or not the list is empty.
*
* \see size()
*/
bool isEmpty() const;
bool isEmpty() const;
/*!
/*!
* Find the first occurrence of \a value.
*/
Iterator find(const T &value);
Iterator find(const T &value);
/*!
/*!
* Find the first occurrence of \a value.
*/
ConstIterator find(const T &value) const;
ConstIterator find(const T &value) const;
/*!
/*!
* Returns true if the list contains \a value.
*/
bool contains(const T &value) const;
bool contains(const T &value) const;
/*!
/*!
* Erase the item at \a it from the list.
*/
Iterator erase(Iterator it);
Iterator erase(Iterator it);
/*!
/*!
* Returns a reference to the first item in the list.
*/
const T &front() const;
const T &front() const;
/*!
/*!
* Returns a reference to the first item in the list.
*/
T &front();
T &front();
/*!
/*!
* Returns a reference to the last item in the list.
*/
const T &back() const;
const T &back() const;
/*!
/*!
* Returns a reference to the last item in the list.
*/
T &back();
T &back();
/*!
/*!
* Auto delete the members of the list when the last reference to the list
* passes out of scope. This will have no effect on lists which do not
* contain a pointer type.
@@ -207,62 +206,62 @@ namespace TagLib {
* \note This relies on partial template instantiation -- most modern C++
* compilers should now support this.
*/
void setAutoDelete(bool autoDelete);
void setAutoDelete(bool autoDelete);
/*!
/*!
* Returns a reference to item \a i in the list.
*
* \warning This method is slow. Use iterators to loop through the list.
*/
T &operator[](unsigned int i);
T &operator[](unsigned int i);
/*!
/*!
* Returns a const reference to item \a i in the list.
*
* \warning This method is slow. Use iterators to loop through the list.
*/
const T &operator[](unsigned int i) const;
const T &operator[](unsigned int i) const;
/*!
/*!
* 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.
*/
List<T> &operator=(const List<T> &l);
List<T> &operator=(const List<T> &l);
/*!
/*!
* Exchanges the content of this list by the content of \a l.
*/
void swap(List<T> &l);
void swap(List<T> &l);
/*!
/*!
* Compares this list with \a l and returns true if all of the elements are
* the same.
*/
bool operator==(const List<T> &l) const;
bool operator==(const List<T> &l) const;
/*!
/*!
* Compares this list with \a l and returns true if the lists differ.
*/
bool operator!=(const List<T> &l) const;
bool operator!=(const List<T> &l) const;
protected:
/*
protected:
/*
* If this List is being shared via implicit sharing, do a deep copy of the
* data and separate from the shared members. This should be called by all
* non-const subclass members.
*/
void detach();
void detach();
private:
private:
#ifndef DO_NOT_DOCUMENT
template <class TP> class ListPrivate;
ListPrivate<T> *d;
template<class TP> class ListPrivate;
ListPrivate<T> *d;
#endif
};
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
// Since GCC doesn't support the "export" keyword, we have to include the
// implementation.

View File

@@ -33,170 +33,169 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! A generic, implicitly shared map.
//! A generic, implicitly shared map.
/*!
/*!
* This implements a standard map container that associates a key with a value
* and has fast key-based lookups. This map is also implicitly shared making
* it suitable for pass-by-value usage.
*/
template <class Key, class T> class Map
{
public:
template<class Key, class T> class Map {
public:
#ifndef DO_NOT_DOCUMENT
#ifdef WANT_CLASS_INSTANTIATION_OF_MAP
// Some STL implementations get snippy over the use of the
// class keyword to distinguish different templates; Sun Studio
// in particular finds multiple specializations in certain rare
// cases and complains about that. GCC doesn't seem to mind,
// and uses the typedefs further below without the class keyword.
// 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;
#else
typedef typename std::map<Key, T>::iterator Iterator;
typedef typename std::map<Key, T>::const_iterator ConstIterator;
#endif
# ifdef WANT_CLASS_INSTANTIATION_OF_MAP
// Some STL implementations get snippy over the use of the
// class keyword to distinguish different templates; Sun Studio
// in particular finds multiple specializations in certain rare
// cases and complains about that. GCC doesn't seem to mind,
// and uses the typedefs further below without the class keyword.
// 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;
# else
typedef typename std::map<Key, T>::iterator Iterator;
typedef typename std::map<Key, T>::const_iterator ConstIterator;
# endif
#endif
/*!
/*!
* Constructs an empty Map.
*/
Map();
Map();
/*!
/*!
* Make a shallow, implicitly shared, copy of \a m. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
Map(const Map<Key, T> &m);
Map(const Map<Key, T> &m);
/*!
/*!
* Destroys this instance of the Map.
*/
virtual ~Map();
virtual ~Map();
/*!
/*!
* Returns an STL style iterator to the beginning of the map. See
* std::map::iterator for the semantics.
*/
Iterator begin();
Iterator begin();
/*!
/*!
* Returns an STL style iterator to the beginning of the map. See
* std::map::const_iterator for the semantics.
*/
ConstIterator begin() const;
ConstIterator begin() const;
/*!
/*!
* Returns an STL style iterator to the end of the map. See
* std::map::iterator for the semantics.
*/
Iterator end();
Iterator end();
/*!
/*!
* Returns an STL style iterator to the end of the map. See
* std::map::const_iterator for the semantics.
*/
ConstIterator end() const;
ConstIterator end() const;
/*!
/*!
* Inserts \a value under \a key in the map. If a value for \a key already
* exists it will be overwritten.
*/
Map<Key, T> &insert(const Key &key, const T &value);
Map<Key, T> &insert(const Key &key, const T &value);
/*!
/*!
* Removes all of the elements from elements from the map. This however
* will not delete pointers if the mapped type is a pointer type.
*/
Map<Key, T> &clear();
Map<Key, T> &clear();
/*!
/*!
* The number of elements in the map.
*
* \see isEmpty()
*/
unsigned int size() const;
unsigned int size() const;
/*!
/*!
* Returns true if the map is empty.
*
* \see size()
*/
bool isEmpty() const;
bool isEmpty() const;
/*!
/*!
* Find the first occurrence of \a key.
*/
Iterator find(const Key &key);
Iterator find(const Key &key);
/*!
/*!
* Find the first occurrence of \a key.
*/
ConstIterator find(const Key &key) const;
ConstIterator find(const Key &key) const;
/*!
/*!
* Returns true if the map contains an instance of \a key.
*/
bool contains(const Key &key) const;
bool contains(const Key &key) const;
/*!
/*!
* Erase the item at \a it from the list.
*/
Map<Key, T> &erase(Iterator it);
Map<Key, T> &erase(Iterator it);
/*!
/*!
* Erase the item with \a key from the list.
*/
Map<Key, T> &erase(const Key &key);
Map<Key, T> &erase(const Key &key);
/*!
/*!
* Returns a reference to the value associated with \a key.
*
* \note This has undefined behavior if the key is not present in the map.
*/
const T &operator[](const Key &key) const;
const T &operator[](const Key &key) const;
/*!
/*!
* Returns a reference to the value associated with \a key.
*
* \note This has undefined behavior if the key is not present in the map.
*/
T &operator[](const Key &key);
T &operator[](const Key &key);
/*!
/*!
* Make a shallow, implicitly shared, copy of \a m. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
Map<Key, T> &operator=(const Map<Key, T> &m);
Map<Key, T> &operator=(const Map<Key, T> &m);
/*!
/*!
* Exchanges the content of this map by the content of \a m.
*/
void swap(Map<Key, T> &m);
void swap(Map<Key, T> &m);
protected:
/*
protected:
/*
* If this List is being shared via implicit sharing, do a deep copy of the
* data and separate from the shared members. This should be called by all
* non-const subclass members.
*/
void detach();
void detach();
private:
private:
#ifndef DO_NOT_DOCUMENT
template <class KeyP, class TP> class MapPrivate;
MapPrivate<Key, T> *d;
template<class KeyP, class TP> class MapPrivate;
MapPrivate<Key, T> *d;
#endif
};
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
// Since GCC doesn't support the "export" keyword, we have to include the
// implementation.

View File

@@ -32,14 +32,13 @@ PropertyMap::PropertyMap() : SimplePropertyMap() {}
PropertyMap::PropertyMap(const SimplePropertyMap &m) {
for(SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it){
for (SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it) {
String key = it->first.upper();
if(!key.isEmpty())
if (!key.isEmpty())
insert(it->first, it->second);
else
unsupported.append(it->first);
}
}
PropertyMap::~PropertyMap() {}
@@ -48,41 +47,35 @@ bool PropertyMap::insert(const String &key, const StringList &values) {
String realKey = key.upper();
Iterator result = SimplePropertyMap::find(realKey);
if(result == end())
if (result == end())
SimplePropertyMap::insert(realKey, values);
else
SimplePropertyMap::operator[](realKey).append(values);
return true;
}
bool PropertyMap::replace(const String &key, const StringList &values)
{
bool PropertyMap::replace(const String &key, const StringList &values) {
String realKey = key.upper();
SimplePropertyMap::erase(realKey);
SimplePropertyMap::insert(realKey, values);
return true;
}
PropertyMap::Iterator PropertyMap::find(const String &key)
{
PropertyMap::Iterator PropertyMap::find(const String &key) {
return SimplePropertyMap::find(key.upper());
}
PropertyMap::ConstIterator PropertyMap::find(const String &key) const
{
PropertyMap::ConstIterator PropertyMap::find(const String &key) const {
return SimplePropertyMap::find(key.upper());
}
bool PropertyMap::contains(const String &key) const
{
bool PropertyMap::contains(const String &key) const {
return SimplePropertyMap::contains(key.upper());
}
bool PropertyMap::contains(const PropertyMap &other) const
{
for(ConstIterator it = other.begin(); it != other.end(); ++it) {
if(!SimplePropertyMap::contains(it->first))
bool PropertyMap::contains(const PropertyMap &other) const {
for (ConstIterator it = other.begin(); it != other.end(); ++it) {
if (!SimplePropertyMap::contains(it->first))
return false;
if ((*this)[it->first] != it->second)
return false;
@@ -90,84 +83,73 @@ bool PropertyMap::contains(const PropertyMap &other) const
return true;
}
PropertyMap &PropertyMap::erase(const String &key)
{
PropertyMap &PropertyMap::erase(const String &key) {
SimplePropertyMap::erase(key.upper());
return *this;
}
PropertyMap &PropertyMap::erase(const PropertyMap &other)
{
for(ConstIterator it = other.begin(); it != other.end(); ++it)
PropertyMap &PropertyMap::erase(const PropertyMap &other) {
for (ConstIterator it = other.begin(); it != other.end(); ++it)
erase(it->first);
return *this;
}
PropertyMap &PropertyMap::merge(const PropertyMap &other)
{
for(PropertyMap::ConstIterator it = other.begin(); it != other.end(); ++it)
PropertyMap &PropertyMap::merge(const PropertyMap &other) {
for (PropertyMap::ConstIterator it = other.begin(); it != other.end(); ++it)
insert(it->first, it->second);
unsupported.append(other.unsupported);
return *this;
}
const StringList &PropertyMap::operator[](const String &key) const
{
const StringList &PropertyMap::operator[](const String &key) const {
return SimplePropertyMap::operator[](key.upper());
}
StringList &PropertyMap::operator[](const String &key)
{
StringList &PropertyMap::operator[](const String &key) {
return SimplePropertyMap::operator[](key.upper());
}
bool PropertyMap::operator==(const PropertyMap &other) const
{
for(ConstIterator it = other.begin(); it != other.end(); ++it) {
bool PropertyMap::operator==(const PropertyMap &other) const {
for (ConstIterator it = other.begin(); it != other.end(); ++it) {
ConstIterator thisFind = find(it->first);
if( thisFind == end() || (thisFind->second != it->second) )
if (thisFind == end() || (thisFind->second != it->second))
return false;
}
for(ConstIterator it = begin(); it != end(); ++it) {
for (ConstIterator it = begin(); it != end(); ++it) {
ConstIterator otherFind = other.find(it->first);
if( otherFind == other.end() || (otherFind->second != it->second) )
if (otherFind == other.end() || (otherFind->second != it->second))
return false;
}
return unsupported == other.unsupported;
}
bool PropertyMap::operator!=(const PropertyMap &other) const
{
bool PropertyMap::operator!=(const PropertyMap &other) const {
return !(*this == other);
}
String PropertyMap::toString() const
{
String PropertyMap::toString() const {
String ret;
for(ConstIterator it = begin(); it != end(); ++it)
ret += it->first+"="+it->second.toString(", ") + "\n";
if(!unsupported.isEmpty())
for (ConstIterator it = begin(); it != end(); ++it)
ret += it->first + "=" + it->second.toString(", ") + "\n";
if (!unsupported.isEmpty())
ret += "Unsupported Data: " + unsupported.toString(", ") + "\n";
return ret;
}
void PropertyMap::removeEmpty()
{
void PropertyMap::removeEmpty() {
PropertyMap m;
for(ConstIterator it = begin(); it != end(); ++it) {
if(!it->second.isEmpty())
for (ConstIterator it = begin(); it != end(); ++it) {
if (!it->second.isEmpty())
m.insert(it->first, it->second);
}
*this = m;
}
StringList &PropertyMap::unsupportedData()
{
StringList &PropertyMap::unsupportedData() {
return unsupported;
}
const StringList &PropertyMap::unsupportedData() const
{
const StringList &PropertyMap::unsupportedData() const {
return unsupported;
}

View File

@@ -32,11 +32,11 @@
namespace Strawberry_TagLib {
namespace TagLib {
typedef Map<String,StringList> SimplePropertyMap;
typedef Map<String, StringList> SimplePropertyMap;
//! A map for format-independent <key,valuelist> tag representations.
//! A map for format-independent <key,valuelist> tag representations.
/*!
/*!
* This map implements a generic representation of textual audio metadata
* ("tags") realized as pairs of a case-insensitive key
* and a nonempty list of corresponding values, each value being an arbitrary
@@ -106,108 +106,106 @@ namespace TagLib {
*
*/
class TAGLIB_EXPORT PropertyMap: public SimplePropertyMap
{
public:
class TAGLIB_EXPORT PropertyMap : public SimplePropertyMap {
public:
typedef SimplePropertyMap::Iterator Iterator;
typedef SimplePropertyMap::ConstIterator ConstIterator;
typedef SimplePropertyMap::Iterator Iterator;
typedef SimplePropertyMap::ConstIterator ConstIterator;
PropertyMap();
PropertyMap();
/*!
/*!
* Creates a PropertyMap initialized from a SimplePropertyMap. Copies all
* entries from \a m that have valid keys.
* Invalid keys will be appended to the unsupportedData() list.
*/
PropertyMap(const SimplePropertyMap &m);
PropertyMap(const SimplePropertyMap &m);
virtual ~PropertyMap();
virtual ~PropertyMap();
/*!
/*!
* Inserts \a values under \a key in the map. If \a key already exists,
* then \a values will be appended to the existing StringList.
* The returned value indicates success, i.e. whether \a key is a
* valid key.
*/
bool insert(const String &key, const StringList &values);
bool insert(const String &key, const StringList &values);
/*!
/*!
* Replaces any existing values for \a key with the given \a values,
* and simply insert them if \a key did not exist before.
* The returned value indicates success, i.e. whether \a key is a
* valid key.
*/
bool replace(const String &key, const StringList &values);
bool replace(const String &key, const StringList &values);
/*!
/*!
* Find the first occurrence of \a key.
*/
Iterator find(const String &key);
Iterator find(const String &key);
/*!
/*!
* Find the first occurrence of \a key.
*/
ConstIterator find(const String &key) const;
ConstIterator find(const String &key) const;
/*!
/*!
* Returns true if the map contains values for \a key.
*/
bool contains(const String &key) const;
bool contains(const String &key) const;
/*!
/*!
* Returns true if this map contains all keys of \a other
* and the values coincide for that keys. Does not take
* the unsupportedData list into account.
*/
bool contains(const PropertyMap &other) const;
bool contains(const PropertyMap &other) const;
/*!
/*!
* Erase the \a key and its values from the map.
*/
PropertyMap &erase(const String &key);
PropertyMap &erase(const String &key);
/*!
/*!
* Erases from this map all keys that appear in \a other.
*/
PropertyMap &erase(const PropertyMap &other);
PropertyMap &erase(const PropertyMap &other);
/*!
/*!
* Merge the contents of \a other into this PropertyMap.
* If a key is contained in both maps, the values of the second
* are appended to that of the first.
* The unsupportedData() lists are concatenated as well.
*/
PropertyMap &merge(const PropertyMap &other);
PropertyMap &merge(const PropertyMap &other);
/*!
/*!
* Returns a reference to the value associated with \a key.
*
* \note: If \a key is not contained in the map, an empty
* StringList is returned without error.
*/
const StringList &operator[](const String &key) const;
const StringList &operator[](const String &key) const;
/*!
/*!
* Returns a reference to the value associated with \a key.
*
* \note: If \a key is not contained in the map, an empty
* StringList is returned. You can also directly add entries
* by using this function as an lvalue.
*/
StringList &operator[](const String &key);
StringList &operator[](const String &key);
/*!
/*!
* Returns true if and only if \other has the same contents as this map.
*/
bool operator==(const PropertyMap &other) const;
bool operator==(const PropertyMap &other) const;
/*!
/*!
* Returns false if and only \other has the same contents as this map.
*/
bool operator!=(const PropertyMap &other) const;
bool operator!=(const PropertyMap &other) const;
/*!
/*!
* If a PropertyMap is read from a File object using File::properties(),
* the StringList returned from this function will represent metadata
* that could not be parsed into the PropertyMap representation. This could
@@ -216,22 +214,20 @@ namespace TagLib {
* those unsupported elements if you call File::setProperties() with the
* same PropertyMap as argument.
*/
StringList &unsupportedData();
const StringList &unsupportedData() const;
StringList &unsupportedData();
const StringList &unsupportedData() const;
/*!
/*!
* Removes all entries which have an empty value list.
*/
void removeEmpty();
void removeEmpty();
String toString() const;
String toString() const;
private:
private:
StringList unsupported;
};
StringList unsupported;
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif /* TAGLIB_PROPERTYMAP_H_ */

View File

@@ -24,80 +24,71 @@
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif
#include "trefcounter.h"
#if defined(HAVE_STD_ATOMIC)
# include <atomic>
# define ATOMIC_INT std::atomic_int
# define ATOMIC_INC(x) (++x)
# define ATOMIC_DEC(x) (--x)
# include <atomic>
# define ATOMIC_INT std::atomic_int
# define ATOMIC_INC(x) (++x)
# define ATOMIC_DEC(x) (--x)
#elif 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)
# 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)
# 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)
# 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)
# 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)
# define ATOMIC_INT int
# define ATOMIC_INC(x) (++x)
# define ATOMIC_DEC(x) (--x)
#endif
namespace Strawberry_TagLib {
namespace TagLib
{
namespace TagLib {
class RefCounter::RefCounterPrivate
{
public:
RefCounterPrivate() :
refCount(1) {}
class RefCounter::RefCounterPrivate {
public:
RefCounterPrivate() : refCount(1) {}
volatile ATOMIC_INT refCount;
};
volatile ATOMIC_INT refCount;
};
RefCounter::RefCounter() :
d(new RefCounterPrivate())
{
}
RefCounter::~RefCounter()
{
delete d;
}
void RefCounter::ref()
{
ATOMIC_INC(d->refCount);
}
bool RefCounter::deref()
{
return (ATOMIC_DEC(d->refCount) == 0);
}
int RefCounter::count() const
{
return static_cast<int>(d->refCount);
}
RefCounter::RefCounter() : d(new RefCounterPrivate()) {
}
RefCounter::~RefCounter() {
delete d;
}
void RefCounter::ref() {
ATOMIC_INC(d->refCount);
}
bool RefCounter::deref() {
return (ATOMIC_DEC(d->refCount) == 0);
}
int RefCounter::count() const {
return static_cast<int>(d->refCount);
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -39,17 +39,14 @@
# endif
# include <windows.h>
# define TAGLIB_ATOMIC_WIN
#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \
&& (defined(__i386__) || defined(__i486__) || defined(__i586__) || \
defined(__i686__) || defined(__x86_64) || defined(__ia64)) \
&& !defined(__INTEL_COMPILER)
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) && (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64) || defined(__ia64)) && !defined(__INTEL_COMPILER)
# define TAGLIB_ATOMIC_GCC
#elif defined(__ia64) && defined(__INTEL_COMPILER)
# include <ia64intrin.h>
# define TAGLIB_ATOMIC_GCC
#endif
#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
/*!
* \internal
* This is just used as a base class for shared classes in TagLib.
@@ -57,60 +54,68 @@
* \warning This <b>is not</b> part of the TagLib public API!
*/
namespace Strawberry_TagLib {
namespace TagLib
{
namespace TagLib {
class TAGLIB_EXPORT RefCounter
{
public:
RefCounter();
virtual ~RefCounter();
class TAGLIB_EXPORT RefCounter {
public:
RefCounter();
virtual ~RefCounter();
void ref();
bool deref();
int count() const;
void ref();
bool deref();
int count() const;
private:
class RefCounterPrivate;
RefCounterPrivate *d;
};
private:
class RefCounterPrivate;
RefCounterPrivate *d;
};
// BIC this old class is needed by tlist.tcc and tmap.tcc
class RefCounterOld
{
public:
RefCounterOld() : refCount(1) {}
// BIC this old class is needed by tlist.tcc and tmap.tcc
class RefCounterOld {
public:
RefCounterOld() : refCount(1) {}
#ifdef TAGLIB_ATOMIC_MAC
void ref() { OSAtomicIncrement32Barrier(const_cast<int32_t*>(&refCount)); }
bool deref() { return ! OSAtomicDecrement32Barrier(const_cast<int32_t*>(&refCount)); }
int32_t count() { return refCount; }
private:
volatile int32_t refCount;
#elif defined(TAGLIB_ATOMIC_WIN)
void ref() { InterlockedIncrement(&refCount); }
bool deref() { return ! InterlockedDecrement(&refCount); }
long count() { return refCount; }
private:
volatile long refCount;
#elif defined(TAGLIB_ATOMIC_GCC)
void ref() { __sync_add_and_fetch(&refCount, 1); }
bool deref() { return ! __sync_sub_and_fetch(&refCount, 1); }
int count() { return refCount; }
private:
volatile int refCount;
#else
void ref() { refCount++; }
bool deref() { return ! --refCount; }
int count() { return refCount; }
private:
unsigned int refCount;
# ifdef TAGLIB_ATOMIC_MAC
void ref() {
OSAtomicIncrement32Barrier(const_cast<int32_t *>(&refCount));
}
bool deref() { return !OSAtomicDecrement32Barrier(const_cast<int32_t *>(&refCount)); }
int32_t count() { return refCount; }
private:
volatile int32_t refCount;
# elif defined(TAGLIB_ATOMIC_WIN)
void ref() {
InterlockedIncrement(&refCount);
}
bool deref() { return !InterlockedDecrement(&refCount); }
long count() { return refCount; }
private:
volatile long refCount;
# elif defined(TAGLIB_ATOMIC_GCC)
void ref() {
__sync_add_and_fetch(&refCount, 1);
}
bool deref() { return !__sync_sub_and_fetch(&refCount, 1); }
int count() { return refCount; }
private:
volatile int refCount;
# else
void ref() {
refCount++;
}
bool deref() { return !--refCount; }
int count() { return refCount; }
private:
unsigned int refCount;
# endif
};
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif // DO_NOT_DOCUMENT
#endif
};
}
}
#endif // DO_NOT_DOCUMENT
#endif

View File

@@ -35,115 +35,105 @@
#include "tstring.h"
namespace
{
using namespace Strawberry_TagLib::TagLib;
namespace {
using namespace Strawberry_TagLib::TagLib;
// Returns the native format of std::wstring.
String::Type wcharByteOrder()
{
if(Utils::systemByteOrder() == Utils::LittleEndian)
return String::UTF16LE;
else
return String::UTF16BE;
}
// Returns the native format of std::wstring.
String::Type wcharByteOrder() {
if (Utils::systemByteOrder() == Utils::LittleEndian)
return String::UTF16LE;
else
return String::UTF16BE;
}
// Converts a Latin-1 string into UTF-16(without BOM/CPU byte order)
// and copies it to the internal buffer.
void copyFromLatin1(std::wstring &data, const char *s, size_t length)
{
data.resize(length);
// Converts a Latin-1 string into UTF-16(without BOM/CPU byte order)
// and copies it to the internal buffer.
void copyFromLatin1(std::wstring &data, const char *s, size_t length) {
data.resize(length);
for(size_t i = 0; i < length; ++i)
data[i] = static_cast<unsigned char>(s[i]);
}
for (size_t i = 0; i < length; ++i)
data[i] = static_cast<unsigned char>(s[i]);
}
// Converts a UTF-8 string into UTF-16(without BOM/CPU byte order)
// and copies it to the internal buffer.
void copyFromUTF8(std::wstring &data, const char *s, size_t length)
{
data.resize(length);
// Converts a UTF-8 string into UTF-16(without BOM/CPU byte order)
// and copies it to the internal buffer.
void copyFromUTF8(std::wstring &data, const char *s, size_t length) {
data.resize(length);
try {
const std::wstring::iterator dstEnd = utf8::utf8to16(s, s + length, data.begin());
data.resize(dstEnd - data.begin());
}
catch(const utf8::exception &e) {
const String message(e.what());
debug("String::copyFromUTF8() - UTF8-CPP error: " + message);
data.clear();
}
}
// Helper functions to read a UTF-16 character from an array.
template <typename T>
unsigned short nextUTF16(const T **p);
template <>
unsigned short nextUTF16<wchar_t>(const wchar_t **p)
{
return static_cast<unsigned short>(*(*p)++);
}
template <>
unsigned short nextUTF16<char>(const char **p)
{
union {
unsigned short w;
char c[2];
} u;
u.c[0] = *(*p)++;
u.c[1] = *(*p)++;
return u.w;
}
// Converts a UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
// UTF-16(without BOM/CPU byte order) and copies it to the internal buffer.
template <typename T>
void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t)
{
bool swap;
if(t == String::UTF16) {
if(length < 1) {
debug("String::copyFromUTF16() - Invalid UTF16 string. Too short to have a BOM.");
return;
}
const unsigned short bom = nextUTF16(&s);
if(bom == 0xfeff)
swap = false; // Same as CPU endian. No need to swap bytes.
else if(bom == 0xfffe)
swap = true; // Not same as CPU endian. Need to swap bytes.
else {
debug("String::copyFromUTF16() - Invalid UTF16 string. BOM is broken.");
return;
}
length--;
}
else {
swap = (t != wcharByteOrder());
}
data.resize(length);
for(size_t i = 0; i < length; ++i) {
const unsigned short c = nextUTF16(&s);
if(swap)
data[i] = Utils::byteSwap(c);
else
data[i] = c;
}
try {
const std::wstring::iterator dstEnd = utf8::utf8to16(s, s + length, data.begin());
data.resize(dstEnd - data.begin());
} catch (const utf8::exception &e) {
const String message(e.what());
debug("String::copyFromUTF8() - UTF8-CPP error: " + message);
data.clear();
}
}
// Helper functions to read a UTF-16 character from an array.
template<typename T>
unsigned short nextUTF16(const T **p);
template<>
unsigned short nextUTF16<wchar_t>(const wchar_t **p) {
return static_cast<unsigned short>(*(*p)++);
}
template<>
unsigned short nextUTF16<char>(const char **p) {
union {
unsigned short w;
char c[2];
} u;
u.c[0] = *(*p)++;
u.c[1] = *(*p)++;
return u.w;
}
// Converts a UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
// UTF-16(without BOM/CPU byte order) and copies it to the internal buffer.
template<typename T>
void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t) {
bool swap;
if (t == String::UTF16) {
if (length < 1) {
debug("String::copyFromUTF16() - Invalid UTF16 string. Too short to have a BOM.");
return;
}
const unsigned short bom = nextUTF16(&s);
if (bom == 0xfeff)
swap = false; // Same as CPU endian. No need to swap bytes.
else if (bom == 0xfffe)
swap = true; // Not same as CPU endian. Need to swap bytes.
else {
debug("String::copyFromUTF16() - Invalid UTF16 string. BOM is broken.");
return;
}
length--;
}
else {
swap = (t != wcharByteOrder());
}
data.resize(length);
for (size_t i = 0; i < length; ++i) {
const unsigned short c = nextUTF16(&s);
if (swap)
data[i] = Utils::byteSwap(c);
else
data[i] = c;
}
}
} // namespace
namespace Strawberry_TagLib {
namespace TagLib {
class String::StringPrivate : public RefCounter
{
public:
StringPrivate() :
RefCounter() {}
class String::StringPrivate : public RefCounter {
public:
StringPrivate() : RefCounter() {}
/*!
* Stores string in UTF-16. The byte order depends on the CPU endian.
@@ -162,33 +152,25 @@ String String::null;
// public members
////////////////////////////////////////////////////////////////////////////////
String::String() :
d(new StringPrivate())
{
String::String() : d(new StringPrivate()) {
}
String::String(const String &s) :
d(s.d)
{
String::String(const String &s) : d(s.d) {
d->ref();
}
String::String(const std::string &s, Type t) :
d(new StringPrivate())
{
if(t == Latin1)
String::String(const std::string &s, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, s.c_str(), s.length());
else if(t == String::UTF8)
else if (t == String::UTF8)
copyFromUTF8(d->data, s.c_str(), s.length());
else {
debug("String::String() -- std::string should not contain UTF16.");
}
}
String::String(const wstring &s, Type t) :
d(new StringPrivate())
{
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
String::String(const wstring &s, Type t) : d(new StringPrivate()) {
if (t == UTF16 || t == UTF16BE || t == UTF16LE) {
// This looks ugly but needed for the compatibility with TagLib1.8.
// Should be removed in TabLib2.0.
if (t == UTF16BE)
@@ -203,10 +185,8 @@ String::String(const wstring &s, Type t) :
}
}
String::String(const wchar_t *s, Type t) :
d(new StringPrivate())
{
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
String::String(const wchar_t *s, Type t) : d(new StringPrivate()) {
if (t == UTF16 || t == UTF16BE || t == UTF16LE) {
// This looks ugly but needed for the compatibility with TagLib1.8.
// Should be removed in TabLib2.0.
if (t == UTF16BE)
@@ -221,49 +201,41 @@ String::String(const wchar_t *s, Type t) :
}
}
String::String(const char *s, Type t) :
d(new StringPrivate())
{
if(t == Latin1)
String::String(const char *s, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, s, ::strlen(s));
else if(t == String::UTF8)
else if (t == String::UTF8)
copyFromUTF8(d->data, s, ::strlen(s));
else {
debug("String::String() -- const char * should not contain UTF16.");
}
}
String::String(wchar_t c, Type t) :
d(new StringPrivate())
{
if(t == UTF16 || t == UTF16BE || t == UTF16LE)
String::String(wchar_t c, Type t) : d(new StringPrivate()) {
if (t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(d->data, &c, 1, t);
else {
debug("String::String() -- wchar_t should not contain Latin1 or UTF-8.");
}
}
String::String(char c, Type t) :
d(new StringPrivate())
{
if(t == Latin1)
String::String(char c, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, &c, 1);
else if(t == String::UTF8)
else if (t == String::UTF8)
copyFromUTF8(d->data, &c, 1);
else {
debug("String::String() -- char should not contain UTF16.");
}
}
String::String(const ByteVector &v, Type t) :
d(new StringPrivate())
{
if(v.isEmpty())
String::String(const ByteVector &v, Type t) : d(new StringPrivate()) {
if (v.isEmpty())
return;
if(t == Latin1)
if (t == Latin1)
copyFromLatin1(d->data, v.data(), v.size());
else if(t == UTF8)
else if (t == UTF8)
copyFromUTF8(d->data, v.data(), v.size());
else
copyFromUTF16(d->data, v.data(), v.size() / 2, t);
@@ -274,72 +246,60 @@ String::String(const ByteVector &v, Type t) :
////////////////////////////////////////////////////////////////////////////////
String::~String()
{
if(d->deref())
String::~String() {
if (d->deref())
delete d;
}
std::string String::to8Bit(bool unicode) const
{
std::string String::to8Bit(bool unicode) const {
const ByteVector v = data(unicode ? UTF8 : Latin1);
return std::string(v.data(), v.size());
}
Strawberry_TagLib::TagLib::wstring String::toWString() const
{
Strawberry_TagLib::TagLib::wstring String::toWString() const {
return d->data;
}
const char *String::toCString(bool unicode) const
{
const char *String::toCString(bool unicode) const {
d->cstring = to8Bit(unicode);
return d->cstring.c_str();
}
const wchar_t *String::toCWString() const
{
const wchar_t *String::toCWString() const {
return d->data.c_str();
}
String::Iterator String::begin()
{
String::Iterator String::begin() {
detach();
return d->data.begin();
}
String::ConstIterator String::begin() const
{
String::ConstIterator String::begin() const {
return d->data.begin();
}
String::Iterator String::end()
{
String::Iterator String::end() {
detach();
return d->data.end();
}
String::ConstIterator String::end() const
{
String::ConstIterator String::end() const {
return d->data.end();
}
int String::find(const String &s, int offset) const
{
int String::find(const String &s, int offset) const {
return static_cast<int>(d->data.find(s.d->data, offset));
}
int String::rfind(const String &s, int offset) const
{
int String::rfind(const String &s, int offset) const {
return static_cast<int>(d->data.rfind(s.d->data, offset));
}
StringList String::split(const String &separator) const
{
StringList String::split(const String &separator) const {
StringList list;
for(int index = 0;;) {
for (int index = 0;;) {
int sep = find(separator, index);
if(sep < 0) {
if (sep < 0) {
list.append(substr(index, size() - index));
break;
}
@@ -351,42 +311,37 @@ StringList String::split(const String &separator) const
return list;
}
bool String::startsWith(const String &s) const
{
if(s.length() > length())
bool String::startsWith(const String &s) const {
if (s.length() > length())
return false;
return substr(0, s.length()) == s;
}
String String::substr(unsigned int position, unsigned int n) const
{
if(position == 0 && n >= size())
String String::substr(unsigned int position, unsigned int n) const {
if (position == 0 && n >= size())
return *this;
else
return String(d->data.substr(position, n));
}
String &String::append(const String &s)
{
String &String::append(const String &s) {
detach();
d->data += s.d->data;
return *this;
}
String & String::clear()
{
String &String::clear() {
*this = String();
return *this;
}
String String::upper() const
{
String String::upper() const {
String s;
s.d->data.reserve(size());
for(ConstIterator it = begin(); it != end(); ++it) {
if(*it >= 'a' && *it <= 'z')
for (ConstIterator it = begin(); it != end(); ++it) {
if (*it >= 'a' && *it <= 'z')
s.d->data.push_back(*it + 'A' - 'a');
else
s.d->data.push_back(*it);
@@ -395,49 +350,40 @@ String String::upper() const
return s;
}
unsigned int String::size() const
{
unsigned int String::size() const {
return static_cast<unsigned int>(d->data.size());
}
unsigned int String::length() const
{
unsigned int String::length() const {
return size();
}
bool String::isEmpty() const
{
bool String::isEmpty() const {
return d->data.empty();
}
bool String::isNull() const
{
bool String::isNull() const {
return d == null.d;
}
ByteVector String::data(Type t) const
{
switch(t)
{
case Latin1:
{
ByteVector String::data(Type t) const {
switch (t) {
case Latin1: {
ByteVector v(size(), 0);
char *p = v.data();
for(ConstIterator it = begin(); it != end(); ++it)
for (ConstIterator it = begin(); it != end(); ++it)
*p++ = static_cast<char>(*it);
return v;
}
case UTF8:
{
case UTF8: {
ByteVector v(size() * 4, 0);
try {
const ByteVector::Iterator dstEnd = utf8::utf16to8(begin(), end(), v.begin());
v.resize(static_cast<unsigned int>(dstEnd - v.begin()));
}
catch(const utf8::exception &e) {
} catch (const utf8::exception &e) {
const String message(e.what());
debug("String::data() - UTF8-CPP error: " + message);
v.clear();
@@ -445,8 +391,7 @@ ByteVector String::data(Type t) const
return v;
}
case UTF16:
{
case UTF16: {
ByteVector v(2 + size() * 2, 0);
char *p = v.data();
@@ -455,59 +400,54 @@ ByteVector String::data(Type t) const
*p++ = '\xff';
*p++ = '\xfe';
for(ConstIterator it = begin(); it != end(); ++it) {
for (ConstIterator it = begin(); it != end(); ++it) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
}
return v;
}
case UTF16BE:
{
case UTF16BE: {
ByteVector v(size() * 2, 0);
char *p = v.data();
for(ConstIterator it = begin(); it != end(); ++it) {
for (ConstIterator it = begin(); it != end(); ++it) {
*p++ = static_cast<char>(*it >> 8);
*p++ = static_cast<char>(*it & 0xff);
}
return v;
}
case UTF16LE:
{
case UTF16LE: {
ByteVector v(size() * 2, 0);
char *p = v.data();
for(ConstIterator it = begin(); it != end(); ++it) {
for (ConstIterator it = begin(); it != end(); ++it) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
}
return v;
}
default:
{
default: {
debug("String::data() - Invalid Type value.");
return ByteVector();
}
}
}
int String::toInt() const
{
int String::toInt() const {
return toInt(0);
}
int String::toInt(bool *ok) const
{
int String::toInt(bool *ok) const {
const wchar_t *begin = d->data.c_str();
wchar_t *end;
errno = 0;
const long value = ::wcstol(begin, &end, 10);
// Has wcstol() consumed the entire string and not overflowed?
if(ok) {
if (ok) {
*ok = (errno == 0 && end > begin && *end == L'\0');
*ok = (*ok && value > INT_MIN && value < INT_MAX);
}
@@ -515,186 +455,160 @@ int String::toInt(bool *ok) const
return static_cast<int>(value);
}
String String::stripWhiteSpace() const
{
String String::stripWhiteSpace() const {
static const wchar_t *WhiteSpaceChars = L"\t\n\f\r ";
const size_t pos1 = d->data.find_first_not_of(WhiteSpaceChars);
if(pos1 == std::wstring::npos)
if (pos1 == std::wstring::npos)
return String();
const size_t pos2 = d->data.find_last_not_of(WhiteSpaceChars);
return substr(static_cast<unsigned int>(pos1), static_cast<unsigned int>(pos2 - pos1 + 1));
}
bool String::isLatin1() const
{
for(ConstIterator it = begin(); it != end(); ++it) {
if(*it >= 256)
bool String::isLatin1() const {
for (ConstIterator it = begin(); it != end(); ++it) {
if (*it >= 256)
return false;
}
return true;
}
bool String::isAscii() const
{
for(ConstIterator it = begin(); it != end(); ++it) {
if(*it >= 128)
bool String::isAscii() const {
for (ConstIterator it = begin(); it != end(); ++it) {
if (*it >= 128)
return false;
}
return true;
}
String String::number(int n) // static
String String::number(int n) // static
{
return Utils::formatString("%d", n);
}
wchar_t &String::operator[](int i)
{
wchar_t &String::operator[](int i) {
detach();
return d->data[i];
}
const wchar_t &String::operator[](int i) const
{
const wchar_t &String::operator[](int i) const {
return d->data[i];
}
bool String::operator==(const String &s) const
{
bool String::operator==(const String &s) const {
return (d == s.d || d->data == s.d->data);
}
bool String::operator!=(const String &s) const
{
bool String::operator!=(const String &s) const {
return !(*this == s);
}
bool String::operator==(const char *s) const
{
bool String::operator==(const char *s) const {
const wchar_t *p = toCWString();
while(*p != L'\0' || *s != '\0') {
if(*p++ != static_cast<unsigned char>(*s++))
while (*p != L'\0' || *s != '\0') {
if (*p++ != static_cast<unsigned char>(*s++))
return false;
}
return true;
}
bool String::operator!=(const char *s) const
{
bool String::operator!=(const char *s) const {
return !(*this == s);
}
bool String::operator==(const wchar_t *s) const
{
bool String::operator==(const wchar_t *s) const {
return (d->data == s);
}
bool String::operator!=(const wchar_t *s) const
{
bool String::operator!=(const wchar_t *s) const {
return !(*this == s);
}
String &String::operator+=(const String &s)
{
String &String::operator+=(const String &s) {
detach();
d->data += s.d->data;
return *this;
}
String &String::operator+=(const wchar_t *s)
{
String &String::operator+=(const wchar_t *s) {
detach();
d->data += s;
return *this;
}
String &String::operator+=(const char *s)
{
String &String::operator+=(const char *s) {
detach();
for(int i = 0; s[i] != 0; i++)
for (int i = 0; s[i] != 0; i++)
d->data += static_cast<unsigned char>(s[i]);
return *this;
}
String &String::operator+=(wchar_t c)
{
String &String::operator+=(wchar_t c) {
detach();
d->data += c;
return *this;
}
String &String::operator+=(char c)
{
String &String::operator+=(char c) {
detach();
d->data += static_cast<unsigned char>(c);
return *this;
}
String &String::operator=(const String &s)
{
String &String::operator=(const String &s) {
String(s).swap(*this);
return *this;
}
String &String::operator=(const std::string &s)
{
String &String::operator=(const std::string &s) {
String(s).swap(*this);
return *this;
}
String &String::operator=(const wstring &s)
{
String &String::operator=(const wstring &s) {
String(s).swap(*this);
return *this;
}
String &String::operator=(const wchar_t *s)
{
String &String::operator=(const wchar_t *s) {
String(s).swap(*this);
return *this;
}
String &String::operator=(char c)
{
String &String::operator=(char c) {
String(c).swap(*this);
return *this;
}
String &String::operator=(wchar_t c)
{
String &String::operator=(wchar_t c) {
String(c, wcharByteOrder()).swap(*this);
return *this;
}
String &String::operator=(const char *s)
{
String &String::operator=(const char *s) {
String(s).swap(*this);
return *this;
}
String &String::operator=(const ByteVector &v)
{
String &String::operator=(const ByteVector &v) {
String(v).swap(*this);
return *this;
}
void String::swap(String &s)
{
void String::swap(String &s) {
using std::swap;
swap(d, s.d);
}
bool String::operator<(const String &s) const
{
bool String::operator<(const String &s) const {
return (d->data < s.d->data);
}
@@ -702,9 +616,8 @@ bool String::operator<(const String &s) const
// protected members
////////////////////////////////////////////////////////////////////////////////
void String::detach()
{
if(d->count() > 1)
void String::detach() {
if (d->count() > 1)
String(d->data.c_str()).swap(*this);
}
@@ -713,37 +626,32 @@ void String::detach()
////////////////////////////////////////////////////////////////////////////////
const String::Type String::WCharByteOrder = wcharByteOrder();
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
////////////////////////////////////////////////////////////////////////////////
// related non-member functions
////////////////////////////////////////////////////////////////////////////////
const Strawberry_TagLib::TagLib::String operator+(const Strawberry_TagLib::TagLib::String &s1, const Strawberry_TagLib::TagLib::String &s2)
{
const Strawberry_TagLib::TagLib::String operator+(const Strawberry_TagLib::TagLib::String &s1, const Strawberry_TagLib::TagLib::String &s2) {
Strawberry_TagLib::TagLib::String s(s1);
s.append(s2);
return s;
}
const Strawberry_TagLib::TagLib::String operator+(const char *s1, const Strawberry_TagLib::TagLib::String &s2)
{
const Strawberry_TagLib::TagLib::String operator+(const char *s1, const Strawberry_TagLib::TagLib::String &s2) {
Strawberry_TagLib::TagLib::String s(s1);
s.append(s2);
return s;
}
const Strawberry_TagLib::TagLib::String operator+(const Strawberry_TagLib::TagLib::String &s1, const char *s2)
{
const Strawberry_TagLib::TagLib::String operator+(const Strawberry_TagLib::TagLib::String &s1, const char *s2) {
Strawberry_TagLib::TagLib::String s(s1);
s.append(s2);
return s;
}
std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::String &str)
{
std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::String &str) {
s << str.to8Bit();
return s;
}

View File

@@ -43,9 +43,9 @@
*/
#if defined(QT_VERSION) && (QT_VERSION >= 0x040000)
#define QStringToTString(s) Strawberry_TagLib::TagLib::String(s.toUtf8().data(), Strawberry_TagLib::TagLib::String::UTF8)
# define QStringToTString(s) Strawberry_TagLib::TagLib::String(s.toUtf8().data(), Strawberry_TagLib::TagLib::String::UTF8)
#else
#define QStringToTString(s) Strawberry_TagLib::TagLib::String(s.utf8().data(), Strawberry_TagLib::TagLib::String::UTF8)
# define QStringToTString(s) Strawberry_TagLib::TagLib::String(s.utf8().data(), Strawberry_TagLib::TagLib::String::UTF8)
#endif
/*!
@@ -63,11 +63,11 @@
namespace Strawberry_TagLib {
namespace TagLib {
class StringList;
class StringList;
//! A \e wide string class suitable for unicode.
//! A \e wide string class suitable for unicode.
/*!
/*!
* This is an implicitly shared \e wide string. For storage it uses
* TagLib::wstring, but as this is an <i>implementation detail</i> this of
* course could change. Strings are stored internally as UTF-16(without BOM/
@@ -82,130 +82,128 @@ namespace TagLib {
* possible encodings, which are the four supported by the ID3v2 standard.
*/
class TAGLIB_EXPORT String
{
public:
class TAGLIB_EXPORT String {
public:
#ifndef DO_NOT_DOCUMENT
typedef Strawberry_TagLib::TagLib::wstring::iterator Iterator;
typedef Strawberry_TagLib::TagLib::wstring::const_iterator ConstIterator;
typedef Strawberry_TagLib::TagLib::wstring::iterator Iterator;
typedef Strawberry_TagLib::TagLib::wstring::const_iterator ConstIterator;
#endif
/**
/**
* The four types of string encodings supported by the ID3v2 specification.
* ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8.
*/
enum Type {
/*!
enum Type {
/*!
* IS08859-1, or <i>Latin1</i> encoding. 8 bit characters.
*/
Latin1 = 0,
/*!
Latin1 = 0,
/*!
* UTF16 with a <i>byte order mark</i>. 16 bit characters.
*/
UTF16 = 1,
/*!
UTF16 = 1,
/*!
* UTF16 <i>big endian</i>. 16 bit characters. This is the encoding used
* internally by TagLib.
*/
UTF16BE = 2,
/*!
UTF16BE = 2,
/*!
* UTF8 encoding. Characters are usually 8 bits but can be up to 32.
*/
UTF8 = 3,
/*!
UTF8 = 3,
/*!
* UTF16 <i>little endian</i>. 16 bit characters.
*/
UTF16LE = 4
};
UTF16LE = 4
};
/*!
/*!
* Constructs an empty String.
*/
String();
String();
/*!
/*!
* Make a shallow, implicitly shared, copy of \a s. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
String(const String &s);
String(const String &s);
/*!
/*!
* Makes a deep copy of the data in \a s.
*
* \note This should only be used with the 8-bit codecs Latin1 and UTF8, when
* used with other codecs it will simply print a warning and exit.
*/
String(const std::string &s, Type t = Latin1);
String(const std::string &s, Type t = Latin1);
/*!
/*!
* Makes a deep copy of the data in \a s.
*
* /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless
* of the CPU byte order. If UTF16BE, it will not be swapped. This behavior
* will be changed in TagLib2.0.
*/
String(const wstring &s, Type t = UTF16BE);
String(const wstring &s, Type t = UTF16BE);
/*!
/*!
* Makes a deep copy of the data in \a s.
*
* /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless
* of the CPU byte order. If UTF16BE, it will not be swapped. This behavior
* will be changed in TagLib2.0.
*/
String(const wchar_t *s, Type t = UTF16BE);
String(const wchar_t *s, Type t = UTF16BE);
/*!
/*!
* Makes a deep copy of the data in \a c.
*
* \note This should only be used with the 8-bit codecs Latin1 and UTF8, when
* used with other codecs it will simply print a warning and exit.
*/
String(char c, Type t = Latin1);
String(char c, Type t = Latin1);
/*!
/*!
* Makes a deep copy of the data in \a c.
*/
String(wchar_t c, Type t = Latin1);
String(wchar_t c, Type t = Latin1);
/*!
/*!
* Makes a deep copy of the data in \a s.
*
* \note This should only be used with the 8-bit codecs Latin1 and UTF8, when
* used with other codecs it will simply print a warning and exit.
*/
String(const char *s, Type t = Latin1);
String(const char *s, Type t = Latin1);
/*!
/*!
* Makes a deep copy of the data in \a v.
*/
String(const ByteVector &v, Type t = Latin1);
String(const ByteVector &v, Type t = Latin1);
/*!
/*!
* Destroys this String instance.
*/
virtual ~String();
virtual ~String();
/*!
/*!
* Returns a deep copy of this String as an std::string. The returned string
* is encoded in UTF8 if \a unicode is true, otherwise Latin1.
*
* \see toCString()
*/
std::string to8Bit(bool unicode = false) const;
std::string to8Bit(bool unicode = false) const;
/*!
/*!
* Returns a deep copy of this String as a wstring. The returned string is
* encoded in UTF-16 (without BOM/CPU byte order), not UTF-32 even if wchar_t
* is 32-bit wide.
*
* \see toCWString()
*/
wstring toWString() const;
wstring toWString() const;
/*!
/*!
* Creates and returns a standard C-style (null-terminated) version of this
* String. The returned string is encoded in UTF8 if \a unicode is true,
* otherwise Latin1.
@@ -223,9 +221,9 @@ namespace TagLib {
*
* \see to8Bit()
*/
const char *toCString(bool unicode = false) const;
const char *toCString(bool unicode = false) const;
/*!
/*!
* Returns a standard C-style (null-terminated) wide character version of
* this String. The returned string is encoded in UTF-16 (without BOM/CPU byte
* order), not UTF-32 even if wchar_t is 32-bit wide.
@@ -241,95 +239,95 @@ namespace TagLib {
*
* \see toWString()
*/
const wchar_t *toCWString() const;
const wchar_t *toCWString() const;
/*!
/*!
* Returns an iterator pointing to the beginning of the string.
*/
Iterator begin();
Iterator begin();
/*!
/*!
* Returns a const iterator pointing to the beginning of the string.
*/
ConstIterator begin() const;
ConstIterator begin() const;
/*!
/*!
* Returns an iterator pointing to the end of the string (the position
* after the last character).
*/
Iterator end();
Iterator end();
/*!
/*!
* Returns a const iterator pointing to the end of the string (the position
* after the last character).
*/
ConstIterator end() const;
ConstIterator end() const;
/*!
/*!
* Finds the first occurrence of pattern \a s in this string starting from
* \a offset. If the pattern is not found, -1 is returned.
*/
int find(const String &s, int offset = 0) const;
int find(const String &s, int offset = 0) const;
/*!
/*!
* Finds the last occurrence of pattern \a s in this string, searched backwards,
* either from the end of the string or starting from \a offset. If the pattern
* is not found, -1 is returned.
*/
int rfind(const String &s, int offset = -1) const;
int rfind(const String &s, int offset = -1) const;
/*!
/*!
* Splits the string on each occurrence of \a separator.
*/
StringList split(const String &separator = " ") const;
StringList split(const String &separator = " ") const;
/*!
/*!
* Returns true if the strings starts with the substring \a s.
*/
bool startsWith(const String &s) const;
bool startsWith(const String &s) const;
/*!
/*!
* Extract a substring from this string starting at \a position and
* continuing for \a n characters.
*/
String substr(unsigned int position, unsigned int n = 0xffffffff) const;
String substr(unsigned int position, unsigned int n = 0xffffffff) const;
/*!
/*!
* Append \a s to the current string and return a reference to the current
* string.
*/
String &append(const String &s);
String &append(const String &s);
/*!
/*!
* Clears the string.
*/
String &clear();
String &clear();
/*!
/*!
* Returns an upper case version of the string.
*
* \warning This only works for the characters in US-ASCII, i.e. A-Z.
*/
String upper() const;
String upper() const;
/*!
/*!
* Returns the size of the string.
*/
unsigned int size() const;
unsigned int size() const;
/*!
/*!
* Returns the length of the string. Equivalent to size().
*/
unsigned int length() const;
unsigned int length() const;
/*!
/*!
* Returns true if the string is empty.
*
* \see isNull()
*/
bool isEmpty() const;
bool isEmpty() const;
/*!
/*!
* Returns true if this string is null -- i.e. it is a copy of the
* String::null string.
*
@@ -340,10 +338,10 @@ namespace TagLib {
*
* \deprecated
*/
// BIC: remove
bool isNull() const;
// BIC: remove
bool isNull() const;
/*!
/*!
* Returns a ByteVector containing the string's data. If \a t is Latin1 or
* UTF8, this will return a vector of 8 bit characters, otherwise it will use
* 16 bit characters.
@@ -353,171 +351,171 @@ namespace TagLib {
*
* \note The returned data is not null terminated.
*/
ByteVector data(Type t) const;
ByteVector data(Type t) const;
/*!
/*!
* Convert the string to an integer.
*
* Returns the integer if the conversion was successful or 0 if the
* string does not represent a number.
*/
// BIC: merge with the method below
int toInt() const;
// BIC: merge with the method below
int toInt() const;
/*!
/*!
* Convert the string to an integer.
*
* If the conversion was successful, it sets the value of \a *ok to
* true and returns the integer. Otherwise it sets \a *ok to false
* and the result is undefined.
*/
int toInt(bool *ok) const;
int toInt(bool *ok) const;
/*!
/*!
* Returns a string with the leading and trailing whitespace stripped.
*/
String stripWhiteSpace() const;
String stripWhiteSpace() const;
/*!
/*!
* Returns true if the file only uses characters required by Latin1.
*/
bool isLatin1() const;
bool isLatin1() const;
/*!
/*!
* Returns true if the file only uses characters required by (7-bit) ASCII.
*/
bool isAscii() const;
bool isAscii() const;
/*!
/*!
* Converts the base-10 integer \a n to a string.
*/
static String number(int n);
static String number(int n);
/*!
/*!
* Returns a reference to the character at position \a i.
*/
wchar_t &operator[](int i);
wchar_t &operator[](int i);
/*!
/*!
* Returns a const reference to the character at position \a i.
*/
const wchar_t &operator[](int i) const;
const wchar_t &operator[](int i) const;
/*!
/*!
* Compares each character of the String with each character of \a s and
* returns true if the strings match.
*/
bool operator==(const String &s) const;
bool operator==(const String &s) const;
/*!
/*!
* Compares each character of the String with each character of \a s and
* returns false if the strings match.
*/
bool operator!=(const String &s) const;
bool operator!=(const String &s) const;
/*!
/*!
* Compares each character of the String with each character of \a s and
* returns true if the strings match.
*/
bool operator==(const char *s) const;
bool operator==(const char *s) const;
/*!
/*!
* Compares each character of the String with each character of \a s and
* returns false if the strings match.
*/
bool operator!=(const char *s) const;
bool operator!=(const char *s) const;
/*!
/*!
* Compares each character of the String with each character of \a s and
* returns true if the strings match.
*/
bool operator==(const wchar_t *s) const;
bool operator==(const wchar_t *s) const;
/*!
/*!
* Compares each character of the String with each character of \a s and
* returns false if the strings match.
*/
bool operator!=(const wchar_t *s) const;
bool operator!=(const wchar_t *s) const;
/*!
/*!
* Appends \a s to the end of the String.
*/
String &operator+=(const String &s);
String &operator+=(const String &s);
/*!
/*!
* Appends \a s to the end of the String.
*/
String &operator+=(const wchar_t* s);
String &operator+=(const wchar_t *s);
/*!
/*!
* Appends \a s to the end of the String.
*/
String &operator+=(const char* s);
String &operator+=(const char *s);
/*!
/*!
* Appends \a s to the end of the String.
*/
String &operator+=(wchar_t c);
String &operator+=(wchar_t c);
/*!
/*!
* Appends \a c to the end of the String.
*/
String &operator+=(char c);
String &operator+=(char c);
/*!
/*!
* Performs a shallow, implicitly shared, copy of \a s, overwriting the
* String's current data.
*/
String &operator=(const String &s);
String &operator=(const String &s);
/*!
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(const std::string &s);
String &operator=(const std::string &s);
/*!
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(const wstring &s);
String &operator=(const wstring &s);
/*!
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(const wchar_t *s);
String &operator=(const wchar_t *s);
/*!
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(char c);
String &operator=(char c);
/*!
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(wchar_t c);
String &operator=(wchar_t c);
/*!
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(const char *s);
String &operator=(const char *s);
/*!
/*!
* Performs a deep copy of the data in \a v.
*/
String &operator=(const ByteVector &v);
String &operator=(const ByteVector &v);
/*!
/*!
* Exchanges the content of the String by the content of \a s.
*/
void swap(String &s);
void swap(String &s);
/*!
/*!
* To be able to use this class in a Map, this operator needed to be
* implemented. Returns true if \a s is less than this string in a byte-wise
* comparison.
*/
bool operator<(const String &s) const;
bool operator<(const String &s) const;
/*!
/*!
* A null string provided for convenience.
*
* \warning Do not modify this variable. It will mess up the internal state
@@ -525,31 +523,31 @@ namespace TagLib {
*
* \deprecated
*/
// BIC: remove
static String null;
// BIC: remove
static String null;
protected:
/*!
protected:
/*!
* If this String is being shared via implicit sharing, do a deep copy of the
* data and separate from the shared members. This should be called by all
* non-const subclass members.
*/
void detach();
void detach();
private:
/*!
private:
/*!
* \deprecated This variable is no longer used, but NEVER remove this. It
* may lead to a linkage error.
*/
// BIC: remove
TAGLIB_DEPRECATED static const Type WCharByteOrder;
// BIC: remove
TAGLIB_DEPRECATED static const Type WCharByteOrder;
class StringPrivate;
StringPrivate *d;
};
class StringPrivate;
StringPrivate *d;
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \relates TagLib::String

View File

@@ -27,21 +27,18 @@
using namespace Strawberry_TagLib::TagLib;
class StringListPrivate
{
class StringListPrivate {
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
StringList StringList::split(const String &s, const String &pattern)
{
StringList StringList::split(const String &s, const String &pattern) {
StringList l;
int previousOffset = 0;
for(int offset = s.find(pattern); offset != -1; offset = s.find(pattern, offset + 1)) {
for (int offset = s.find(pattern); offset != -1; offset = s.find(pattern, offset + 1)) {
l.append(s.substr(previousOffset, offset - previousOffset));
previousOffset = offset + 1;
}
@@ -55,58 +52,47 @@ StringList StringList::split(const String &s, const String &pattern)
// public members
////////////////////////////////////////////////////////////////////////////////
StringList::StringList() :
List<String>(),
d(nullptr)
{
StringList::StringList() : List<String>(),
d(nullptr) {
}
StringList::StringList(const String &s) :
List<String>(),
d(nullptr)
{
StringList::StringList(const String &s) : List<String>(),
d(nullptr) {
append(s);
}
StringList::StringList(const ByteVectorList &bl, String::Type t) : List<String>()
{
StringList::StringList(const ByteVectorList &bl, String::Type t) : List<String>() {
ByteVectorList::ConstIterator i = bl.begin();
for(;i != bl.end(); i++) {
for (; i != bl.end(); i++) {
append(String(*i, t));
}
}
StringList::~StringList()
{
StringList::~StringList() {
}
String StringList::toString(const String &separator) const
{
String StringList::toString(const String &separator) const {
String s;
ConstIterator it = begin();
ConstIterator itEnd = end();
while(it != itEnd) {
while (it != itEnd) {
s += *it;
it++;
if(it != itEnd)
if (it != itEnd)
s += separator;
}
return s;
}
StringList &StringList::append(const String &s)
{
StringList &StringList::append(const String &s) {
List<String>::append(s);
return *this;
}
StringList &StringList::append(const StringList &l)
{
StringList &StringList::append(const StringList &l) {
List<String>::append(l);
return *this;
}
@@ -115,8 +101,7 @@ StringList &StringList::append(const StringList &l)
// related functions
////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &s, const StringList &l)
{
std::ostream &operator<<(std::ostream &s, const StringList &l) {
s << l.toString();
return s;
}

View File

@@ -36,77 +36,75 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! A list of strings
//! A list of strings
/*!
/*!
* This is a specialization of the List class with some members convention for
* string operations.
*/
class TAGLIB_EXPORT StringList : public List<String>
{
public:
/*!
class TAGLIB_EXPORT StringList : public List<String> {
public:
/*!
* Constructs an empty StringList.
*/
StringList();
StringList();
/*!
/*!
* 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(const StringList &l) = default;
StringList(const StringList &l) = default;
/*!
/*!
* Constructs a StringList with \a s as a member.
*/
StringList(const String &s);
StringList(const String &s);
/*!
/*!
* Makes a deep copy of the data in \a vl.
*
* \note This should only be used with the 8-bit codecs Latin1 and UTF8, when
* used with other codecs it will simply print a warning and exit.
*/
StringList(const ByteVectorList &vl, String::Type t = String::Latin1);
StringList(const ByteVectorList &vl, String::Type t = String::Latin1);
/*!
/*!
* Destroys this StringList instance.
*/
virtual ~StringList();
virtual ~StringList();
/*!
/*!
* Concatenate the list of strings into one string separated by \a separator.
*/
String toString(const String &separator = " ") const;
String toString(const String &separator = " ") const;
/*!
/*!
* Appends \a s to the end of the list and returns a reference to the
* list.
*/
StringList &append(const String &s);
StringList &append(const 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(const StringList &l);
StringList &append(const StringList &l);
/*!
/*!
* 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);
static StringList split(const String &s, const String &pattern);
private:
class StringListPrivate;
StringListPrivate *d;
};
private:
class StringListPrivate;
StringListPrivate *d;
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \related Strawberry_TagLib::TagLib::StringList

View File

@@ -30,215 +30,196 @@
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
#if defined(HAVE_MSC_BYTESWAP)
# include <stdlib.h>
#elif defined(HAVE_GLIBC_BYTESWAP)
# include <byteswap.h>
#elif defined(HAVE_MAC_BYTESWAP)
# include <libkern/OSByteOrder.h>
#elif defined(HAVE_OPENBSD_BYTESWAP)
# include <sys/endian.h>
#endif
# if defined(HAVE_MSC_BYTESWAP)
# include <stdlib.h>
# elif defined(HAVE_GLIBC_BYTESWAP)
# include <byteswap.h>
# elif defined(HAVE_MAC_BYTESWAP)
# include <libkern/OSByteOrder.h>
# elif defined(HAVE_OPENBSD_BYTESWAP)
# include <sys/endian.h>
# endif
#include <tstring.h>
#include <cstdio>
#include <cstdarg>
#include <cstring>
# include <tstring.h>
# include <cstdio>
# include <cstdarg>
# include <cstring>
namespace Strawberry_TagLib {
namespace TagLib
{
namespace Utils
{
namespace
{
namespace TagLib {
namespace Utils {
namespace {
/*!
/*!
* Reverses the order of bytes in an 16-bit integer.
*/
inline unsigned short byteSwap(unsigned short x)
{
#if defined(HAVE_GCC_BYTESWAP)
inline unsigned short byteSwap(unsigned short x) {
# if defined(HAVE_GCC_BYTESWAP)
return __builtin_bswap16(x);
return __builtin_bswap16(x);
#elif defined(HAVE_MSC_BYTESWAP)
# elif defined(HAVE_MSC_BYTESWAP)
return _byteswap_ushort(x);
return _byteswap_ushort(x);
#elif defined(HAVE_GLIBC_BYTESWAP)
# elif defined(HAVE_GLIBC_BYTESWAP)
return __bswap_16(x);
return __bswap_16(x);
#elif defined(HAVE_MAC_BYTESWAP)
# elif defined(HAVE_MAC_BYTESWAP)
return OSSwapInt16(x);
return OSSwapInt16(x);
#elif defined(HAVE_OPENBSD_BYTESWAP)
# elif defined(HAVE_OPENBSD_BYTESWAP)
return swap16(x);
return swap16(x);
#else
# else
return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
#endif
}
# endif
}
/*!
/*!
* Reverses the order of bytes in an 32-bit integer.
*/
inline unsigned int byteSwap(unsigned int x)
{
#if defined(HAVE_GCC_BYTESWAP)
inline unsigned int byteSwap(unsigned int x) {
# if defined(HAVE_GCC_BYTESWAP)
return __builtin_bswap32(x);
return __builtin_bswap32(x);
#elif defined(HAVE_MSC_BYTESWAP)
# elif defined(HAVE_MSC_BYTESWAP)
return _byteswap_ulong(x);
return _byteswap_ulong(x);
#elif defined(HAVE_GLIBC_BYTESWAP)
# elif defined(HAVE_GLIBC_BYTESWAP)
return __bswap_32(x);
return __bswap_32(x);
#elif defined(HAVE_MAC_BYTESWAP)
# elif defined(HAVE_MAC_BYTESWAP)
return OSSwapInt32(x);
return OSSwapInt32(x);
#elif defined(HAVE_OPENBSD_BYTESWAP)
# elif defined(HAVE_OPENBSD_BYTESWAP)
return swap32(x);
return swap32(x);
#else
# else
return ((x & 0xff000000u) >> 24)
| ((x & 0x00ff0000u) >> 8)
| ((x & 0x0000ff00u) << 8)
| ((x & 0x000000ffu) << 24);
return ((x & 0xff000000u) >> 24) | ((x & 0x00ff0000u) >> 8) | ((x & 0x0000ff00u) << 8) | ((x & 0x000000ffu) << 24);
#endif
}
# endif
}
/*!
/*!
* Reverses the order of bytes in an 64-bit integer.
*/
inline unsigned long long byteSwap(unsigned long long x)
{
#if defined(HAVE_GCC_BYTESWAP)
inline unsigned long long byteSwap(unsigned long long x) {
# if defined(HAVE_GCC_BYTESWAP)
return __builtin_bswap64(x);
return __builtin_bswap64(x);
#elif defined(HAVE_MSC_BYTESWAP)
# elif defined(HAVE_MSC_BYTESWAP)
return _byteswap_uint64(x);
return _byteswap_uint64(x);
#elif defined(HAVE_GLIBC_BYTESWAP)
# elif defined(HAVE_GLIBC_BYTESWAP)
return __bswap_64(x);
return __bswap_64(x);
#elif defined(HAVE_MAC_BYTESWAP)
# elif defined(HAVE_MAC_BYTESWAP)
return OSSwapInt64(x);
return OSSwapInt64(x);
#elif defined(HAVE_OPENBSD_BYTESWAP)
# elif defined(HAVE_OPENBSD_BYTESWAP)
return swap64(x);
return swap64(x);
#else
# else
return ((x & 0xff00000000000000ull) >> 56)
| ((x & 0x00ff000000000000ull) >> 40)
| ((x & 0x0000ff0000000000ull) >> 24)
| ((x & 0x000000ff00000000ull) >> 8)
| ((x & 0x00000000ff000000ull) << 8)
| ((x & 0x0000000000ff0000ull) << 24)
| ((x & 0x000000000000ff00ull) << 40)
| ((x & 0x00000000000000ffull) << 56);
return ((x & 0xff00000000000000ull) >> 56) | ((x & 0x00ff000000000000ull) >> 40) | ((x & 0x0000ff0000000000ull) >> 24) | ((x & 0x000000ff00000000ull) >> 8) | ((x & 0x00000000ff000000ull) << 8) | ((x & 0x0000000000ff0000ull) << 24) | ((x & 0x000000000000ff00ull) << 40) | ((x & 0x00000000000000ffull) << 56);
#endif
}
# endif
}
/*!
/*!
* Returns a formatted string just like standard sprintf(), but makes use of
* safer functions such as snprintf() if available.
*/
inline String formatString(const char *format, ...)
{
// Sufficient buffer size for the current internal uses.
// Consider changing this value when you use this function.
inline String formatString(const char *format, ...) {
// Sufficient buffer size for the current internal uses.
// Consider changing this value when you use this function.
static const size_t BufferSize = 128;
static const size_t BufferSize = 128;
va_list args;
va_start(args, format);
va_list args;
va_start(args, format);
char buf[BufferSize];
int length;
char buf[BufferSize];
int length;
#if defined(HAVE_VSNPRINTF)
# if defined(HAVE_VSNPRINTF)
length = vsnprintf(buf, BufferSize, format, args);
length = vsnprintf(buf, BufferSize, format, args);
#elif defined(HAVE_VSPRINTF_S)
# elif defined(HAVE_VSPRINTF_S)
length = vsprintf_s(buf, format, args);
length = vsprintf_s(buf, format, args);
#else
# else
// The last resort. May cause a buffer overflow.
// The last resort. May cause a buffer overflow.
length = vsprintf(buf, format, args);
if(length >= (int)BufferSize) {
debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
length = -1;
}
length = vsprintf(buf, format, args);
if (length >= (int)BufferSize) {
debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
length = -1;
}
#endif
# endif
va_end(args);
va_end(args);
if(length > 0)
return String(buf);
else
return String();
}
if (length > 0)
return String(buf);
else
return String();
}
/*!
/*!
* The types of byte order of the running system.
*/
enum ByteOrder
{
//! Little endian systems.
LittleEndian,
//! Big endian systems.
BigEndian
};
enum ByteOrder {
//! Little endian systems.
LittleEndian,
//! Big endian systems.
BigEndian
};
/*!
/*!
* Returns the byte order of the system.
*/
inline ByteOrder systemByteOrder()
{
union {
int i;
char c;
} u;
inline ByteOrder systemByteOrder() {
union {
int i;
char c;
} u;
u.i = 1;
if(u.c == 1)
return LittleEndian;
else
return BigEndian;
}
}
}
}
u.i = 1;
if (u.c == 1)
return LittleEndian;
else
return BigEndian;
}
} // namespace
} // namespace Utils
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -24,21 +24,20 @@
***************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
# include <config.h>
#endif
#ifdef HAVE_ZLIB
# include <zlib.h>
# include <tstring.h>
# include <tdebug.h>
# include <zlib.h>
# include <tstring.h>
# include <tdebug.h>
#endif
#include "tzlib.h"
using namespace Strawberry_TagLib::TagLib;
bool zlib::isAvailable()
{
bool zlib::isAvailable() {
#ifdef HAVE_ZLIB
return true;
@@ -50,13 +49,12 @@ bool zlib::isAvailable()
#endif
}
ByteVector zlib::decompress(const ByteVector &data)
{
ByteVector zlib::decompress(const ByteVector &data) {
#ifdef HAVE_ZLIB
z_stream stream = {};
if(inflateInit(&stream) != Z_OK) {
if (inflateInit(&stream) != Z_OK) {
debug("zlib::decompress() - Failed to initizlize zlib.");
return ByteVector();
}
@@ -64,7 +62,7 @@ ByteVector zlib::decompress(const ByteVector &data)
ByteVector inData = data;
stream.avail_in = static_cast<uInt>(inData.size());
stream.next_in = reinterpret_cast<Bytef *>(inData.data());
stream.next_in = reinterpret_cast<Bytef *>(inData.data());
const unsigned int chunkSize = 1024;
@@ -75,16 +73,15 @@ ByteVector zlib::decompress(const ByteVector &data)
outData.resize(outData.size() + chunkSize);
stream.avail_out = static_cast<uInt>(chunkSize);
stream.next_out = reinterpret_cast<Bytef *>(outData.data() + offset);
stream.next_out = reinterpret_cast<Bytef *>(outData.data() + offset);
const int result = inflate(&stream, Z_NO_FLUSH);
if(result == Z_STREAM_ERROR ||
result == Z_NEED_DICT ||
result == Z_DATA_ERROR ||
result == Z_MEM_ERROR)
{
if(result != Z_STREAM_ERROR)
if (result == Z_STREAM_ERROR ||
result == Z_NEED_DICT ||
result == Z_DATA_ERROR ||
result == Z_MEM_ERROR) {
if (result != Z_STREAM_ERROR)
inflateEnd(&stream);
debug("zlib::decompress() - Error reading compressed stream.");
@@ -92,7 +89,7 @@ ByteVector zlib::decompress(const ByteVector &data)
}
outData.resize(outData.size() - stream.avail_out);
} while(stream.avail_out == 0);
} while (stream.avail_out == 0);
inflateEnd(&stream);

View File

@@ -35,21 +35,21 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace zlib {
namespace zlib {
/*!
/*!
* Returns whether or not zlib is installed and ready to use.
*/
bool isAvailable();
bool isAvailable();
/*!
/*!
* Decompress \a data by zlib.
*/
ByteVector decompress(const ByteVector &data);
ByteVector decompress(const ByteVector &data);
}
}
}
} // namespace zlib
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif