Additional manual formatting to taglib sources

This commit is contained in:
Jonas Kvinge
2020-06-14 17:01:05 +02:00
parent 577b7d8ec8
commit ef34dce4dc
217 changed files with 7367 additions and 8204 deletions

View File

@@ -39,18 +39,16 @@
// This is a bit ugly to keep writing over and over again.
// A rather obscure feature of the C++ spec that I hadn't thought of that makes
// working with C libs much more efficient. There's more here:
//
// A rather obscure feature of the C++ spec that I hadn't thought of that makes working with C libs much more efficient.
// There's more here:
// http://www.informit.com/isapi/product_id~{9C84DAB4-FE6E-49C5-BB0A-FB50331233EA}/content/index.asp
namespace Strawberry_TagLib {
namespace TagLib {
template<class TIterator>
int findChar(
const TIterator dataBegin, const TIterator dataEnd,
char c, unsigned int offset, int byteAlign) {
int findChar(const TIterator dataBegin, const TIterator dataEnd, char c, unsigned int offset, int byteAlign) {
const size_t dataSize = dataEnd - dataBegin;
if (offset + 1 > dataSize)
return -1;
@@ -66,13 +64,12 @@ int findChar(
}
return -1;
}
template<class TIterator>
int findVector(
const TIterator dataBegin, const TIterator dataEnd,
const TIterator patternBegin, const TIterator patternEnd,
unsigned int offset, int byteAlign) {
int findVector(const TIterator dataBegin, const TIterator dataEnd, const TIterator patternBegin, const TIterator patternEnd, unsigned int offset, int byteAlign) {
const size_t dataSize = dataEnd - dataBegin;
const size_t patternSize = patternEnd - patternBegin;
if (patternSize == 0 || offset + patternSize > dataSize)
@@ -108,10 +105,12 @@ int findVector(
}
return -1;
}
template<class T>
T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignificantByteFirst) {
if (offset >= v.size()) {
debug("toNumber<T>() -- No data to convert. Returning 0.");
return 0;
@@ -126,10 +125,12 @@ T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignifica
}
return sum;
}
template<class T>
T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst) {
const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian);
const bool swap = (mostSignificantByteFirst != isBigEndian);
@@ -144,10 +145,12 @@ T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst) {
return Utils::byteSwap(tmp);
else
return tmp;
}
template<class T>
ByteVector fromNumber(T value, bool mostSignificantByteFirst) {
const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian);
const bool swap = (mostSignificantByteFirst != isBigEndian);
@@ -155,10 +158,12 @@ ByteVector fromNumber(T value, bool mostSignificantByteFirst) {
value = Utils::byteSwap(value);
return ByteVector(reinterpret_cast<const char *>(&value), sizeof(T));
}
template<typename TFloat, typename TInt, Utils::ByteOrder ENDIAN>
TFloat toFloat(const ByteVector &v, size_t offset) {
if (offset > v.size() - sizeof(TInt)) {
debug("toFloat() - offset is out of range. Returning 0.");
return 0.0;
@@ -174,10 +179,12 @@ TFloat toFloat(const ByteVector &v, size_t offset) {
tmp.i = Utils::byteSwap(tmp.i);
return tmp.f;
}
template<typename TFloat, typename TInt, Utils::ByteOrder ENDIAN>
ByteVector fromFloat(TFloat value) {
union {
TInt i;
TFloat f;
@@ -188,10 +195,12 @@ ByteVector fromFloat(TFloat value) {
tmp.i = Utils::byteSwap(tmp.i);
return ByteVector(reinterpret_cast<char *>(&tmp), sizeof(TInt));
}
template<Utils::ByteOrder ENDIAN>
long double toFloat80(const ByteVector &v, size_t offset) {
using std::swap;
if (offset > v.size() - 10) {
@@ -235,6 +244,7 @@ long double toFloat80(const ByteVector &v, size_t offset) {
return -val;
else
return val;
}
class ByteVector::ByteVectorPrivate {
@@ -351,18 +361,20 @@ ByteVector &ByteVector::setData(const char *data) {
char *ByteVector::data() {
detach();
return (size() > 0) ? (&(*d->data)[d->offset]) : 0;
return (size() > 0) ? (&(*d->data)[d->offset]) : nullptr;
}
const char *ByteVector::data() const {
return (size() > 0) ? (&(*d->data)[d->offset]) : 0;
return (size() > 0) ? (&(*d->data)[d->offset]) : nullptr;
}
ByteVector ByteVector::mid(unsigned int index, unsigned int length) const {
index = std::min(index, size());
length = std::min(length, size() - index);
return ByteVector(*this, index, length);
}
char ByteVector::at(unsigned int index) const {
@@ -370,8 +382,10 @@ char ByteVector::at(unsigned int index) const {
}
int ByteVector::find(const ByteVector &pattern, unsigned int offset, int byteAlign) const {
return findVector<ConstIterator>(
begin(), end(), pattern.begin(), pattern.end(), offset, byteAlign);
}
int ByteVector::find(char c, unsigned int offset, int byteAlign) const {
@@ -395,6 +409,7 @@ int ByteVector::rfind(const ByteVector &pattern, unsigned int offset, int byteAl
}
bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset, unsigned int patternLength) const {
if (pattern.size() < patternLength)
patternLength = pattern.size();
@@ -404,6 +419,7 @@ bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsi
return false;
return (::memcmp(data() + offset, pattern.data() + patternOffset, compareLength) == 0);
}
bool ByteVector::startsWith(const ByteVector &pattern) const {
@@ -415,6 +431,7 @@ bool ByteVector::endsWith(const ByteVector &pattern) const {
}
ByteVector &ByteVector::replace(char oldByte, char newByte) {
detach();
for (ByteVector::Iterator it = begin(); it != end(); ++it) {
@@ -423,9 +440,11 @@ ByteVector &ByteVector::replace(char oldByte, char newByte) {
}
return *this;
}
ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &with) {
if (pattern.size() == 1 && with.size() == 1)
return replace(pattern[0], with[0]);
@@ -481,9 +500,11 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
}
return *this;
}
int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const {
if (pattern.size() > size())
return -1;
@@ -498,9 +519,11 @@ int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const {
}
return -1;
}
ByteVector &ByteVector::append(const ByteVector &v) {
if (v.isEmpty())
return *this;
@@ -513,6 +536,7 @@ ByteVector &ByteVector::append(const ByteVector &v) {
::memcpy(data() + originalSize, v.data(), appendSize);
return *this;
}
ByteVector &ByteVector::append(char c) {
@@ -530,6 +554,7 @@ unsigned int ByteVector::size() const {
}
ByteVector &ByteVector::resize(unsigned int size, char padding) {
if (size != d->length) {
detach();
@@ -544,6 +569,7 @@ ByteVector &ByteVector::resize(unsigned int size, char padding) {
}
return *this;
}
ByteVector::Iterator ByteVector::begin() {
@@ -570,10 +596,12 @@ ByteVector::ReverseIterator ByteVector::rbegin() {
}
ByteVector::ConstReverseIterator ByteVector::rbegin() const {
// Workaround for the Solaris Studio 12.4 compiler.
// We need a const reference to the data vector so we can ensure the const version of rbegin() is called.
const std::vector<char> &v = *d->data;
return v.rbegin() + (v.size() - (d->offset + d->length));
}
ByteVector::ReverseIterator ByteVector::rend() {
@@ -582,10 +610,12 @@ ByteVector::ReverseIterator ByteVector::rend() {
}
ByteVector::ConstReverseIterator ByteVector::rend() const {
// Workaround for the Solaris Studio 12.4 compiler.
// We need a const reference to the data vector so we can ensure the const version of rbegin() is called.
const std::vector<char> &v = *d->data;
return v.rbegin() + (v.size() - d->offset);
}
bool ByteVector::isNull() const {
@@ -876,6 +906,7 @@ ByteVector ByteVector::fromBase64(const ByteVector &input) {
}
ByteVector ByteVector::toBase64() const {
static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (!isEmpty()) {
unsigned int len = size();
@@ -906,6 +937,7 @@ ByteVector ByteVector::toBase64() const {
return output;
}
return ByteVector();
}

View File

@@ -38,10 +38,9 @@ namespace TagLib {
//! 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.
*/
* 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:
@@ -53,571 +52,531 @@ class TAGLIB_EXPORT ByteVector {
#endif
/*!
* Constructs an empty byte vector.
*/
* Constructs an empty byte vector.
*/
ByteVector();
/*!
* Construct a vector of size \a size with all values set to \a value by
* default.
*/
* Construct a vector of size \a size with all values set to \a value by default.
*/
ByteVector(unsigned int size, char value = 0);
/*!
* Constructs a byte vector that is a copy of \a v.
*/
* Constructs a byte vector that is a copy of \a v.
*/
ByteVector(const ByteVector &v);
/*!
* Constructs a byte vector that is a copy of \a v.
*/
* Constructs a byte vector that is a copy of \a v.
*/
ByteVector(const ByteVector &v, unsigned int offset, unsigned int length);
/*!
* Constructs a byte vector that contains \a c.
*/
* Constructs a byte vector that contains \a c.
*/
ByteVector(char c);
/*!
* Constructs a byte vector that copies \a data for up to \a length bytes.
*/
* Constructs a byte vector that copies \a data for up to \a length bytes.
*/
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.
*/
* 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);
/*!
* Destroys this ByteVector instance.
*/
* Destroys this ByteVector instance.
*/
virtual ~ByteVector();
/*!
* Sets the data for the byte array using the first \a length bytes of \a data
*/
* Sets the data for the byte array using the first \a length bytes of \a data
*/
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.
*/
* 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);
/*!
* 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.
*/
* 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();
/*!
* Returns a pointer to the internal data structure which may not be modified.
*/
* Returns a pointer to the internal data structure which may not be modified.
*/
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.
*/
* 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;
/*!
* 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.
*/
* 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;
/*!
* 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).
*/
* 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;
/*!
* 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).
*/
* 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;
/*!
* 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).
*/
* 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;
/*!
* 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.
*/
* 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;
/*!
* Returns true if the vector starts with \a pattern.
*/
* Returns true if the vector starts with \a pattern.
*/
bool startsWith(const ByteVector &pattern) const;
/*!
* Returns true if the vector ends with \a pattern.
*/
* Returns true if the vector ends with \a pattern.
*/
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.
*/
* 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);
/*!
* Replaces \a pattern with \a with and returns a reference to the ByteVector
* after the operation. This \e does modify the vector.
*/
* 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);
/*!
* 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
* patterns that start in one vector and end in another. When combined with
* startsWith() it can be used to find a pattern that overlaps two buffers.
*
* \note This will not match the complete pattern at the end of the string; use
* endsWith() for that.
*/
* 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 patterns that start in one vector and end in another.
* When combined with startsWith() it can be used to find a pattern that overlaps two buffers.
*
* \note This will not match the complete pattern at the end of the string; use endsWith() for that.
*/
int endsWithPartialMatch(const ByteVector &pattern) const;
/*!
* Appends \a v to the end of the ByteVector.
*/
* Appends \a v to the end of the ByteVector.
*/
ByteVector &append(const ByteVector &v);
/*!
* Appends \a c to the end of the ByteVector.
*/
* Appends \a c to the end of the ByteVector.
*/
ByteVector &append(char c);
/*!
* Clears the data.
*/
* Clears the data.
*/
ByteVector &clear();
/*!
* Returns the size of the array.
*/
* Returns the size of the array.
*/
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.
*/
* 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);
/*!
* Returns an Iterator that points to the front of the vector.
*/
* Returns an Iterator that points to the front of the vector.
*/
Iterator begin();
/*!
* Returns a ConstIterator that points to the front of the vector.
*/
* Returns a ConstIterator that points to the front of the vector.
*/
ConstIterator begin() const;
/*!
* Returns an Iterator that points to the back of the vector.
*/
* Returns an Iterator that points to the back of the vector.
*/
Iterator end();
/*!
* Returns a ConstIterator that points to the back of the vector.
*/
* Returns a ConstIterator that points to the back of the vector.
*/
ConstIterator end() const;
/*!
* Returns a ReverseIterator that points to the front of the vector.
*/
* Returns a ReverseIterator that points to the front of the vector.
*/
ReverseIterator rbegin();
/*!
* Returns a ConstReverseIterator that points to the front of the vector.
*/
* Returns a ConstReverseIterator that points to the front of the vector.
*/
ConstReverseIterator rbegin() const;
/*!
* Returns a ReverseIterator that points to the back of the vector.
*/
* Returns a ReverseIterator that points to the back of the vector.
*/
ReverseIterator rend();
/*!
* Returns a ConstReverseIterator that points to the back of the vector.
*/
* Returns a ConstReverseIterator that points to the back of the vector.
*/
ConstReverseIterator rend() const;
/*!
* Returns true if the vector is null.
*
* \note A vector may be empty without being null. So do not use this
* method to check if the vector is empty.
*
* \see isEmpty()
*
* \deprecated
*/
* Returns true if the vector is null.
*
* \note A vector may be empty without being null. So do not use this method to check if the vector is empty.
*
* \see isEmpty()
*
* \deprecated
*/
// BIC: remove
bool isNull() const;
/*!
* Returns true if the ByteVector is empty.
*
* \see size()
* \see isNull()
*/
* Returns true if the ByteVector is empty.
*
* \see size()
* \see isNull()
*/
bool isEmpty() const;
/*!
* Returns a CRC checksum of the byte vector's data.
*
* \note This uses an uncommon variant of CRC32 specializes in Ogg.
*/
* 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;
/*!
* Converts the first 4 bytes of the vector to an unsigned integer.
*
* If \a mostSignificantByteFirst is true this will operate left to right
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 ==
* 0x01000000 == 1.
*
* \see fromUInt()
*/
* Converts the first 4 bytes of the vector to an unsigned integer.
*
* If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer.
* For example if \a mostSignificantByteFirst is
* true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1.
*
* \see fromUInt()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 ==
* 0x01000000 == 1.
*
* \see fromUInt()
*/
* 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 evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1.
*
* \see fromUInt()
*/
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.
*
* If \a mostSignificantByteFirst is true this will operate left to right
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 ==
* 0x01000000 == 1.
*
* \see fromUInt()
*/
* 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.
*
* If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1.
*
* \see fromUInt()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
* Converts the first 2 bytes of the vector to a (signed) short.
*
* If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
* 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 evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
* Converts the first 2 bytes of the vector to a unsigned short.
*
* If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
* 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 evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromShort()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt()
*/
* Converts the first 8 bytes of the vector to a (signed) long long.
*
* If \a mostSignificantByteFirst is true this will operate left to right evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt()
*/
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
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt()
*/
* 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 evaluating the integer.
* For example if \a mostSignificantByteFirst is true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt()
*/
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.
*/
* 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;
/*
* Converts the 4 bytes at \a offset of the vector to a float as an IEEE754
* 32-bit big-endian floating point number.
*/
* 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;
/*
* Converts the 8 bytes at \a offset of the vector to a double as an IEEE754
* 64-bit little-endian floating point number.
*/
* 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;
/*
* Converts the 8 bytes at \a offset of the vector to a double as an IEEE754
* 64-bit big-endian floating point number.
*/
* 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;
/*
* 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.
*/
* 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;
/*
* 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.
*/
* 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;
/*!
* 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
* true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 ==
* 0x01000000 == 1.
*
* \see toUInt()
*/
* 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 true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 == 0x01000000 == 1.
*
* \see toUInt()
*/
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
* true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1.
*
* \see toShort()
*/
* 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 true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1.
*
* \see toShort()
*/
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
* true then $00 00 00 01 == 0x0000000000000001 == 1, if false,
* $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see toLongLong()
*/
* 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 true then $00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see toLongLong()
*/
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()
*/
* 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);
/*!
* Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit
* big-endian floating point number.
*
* \see fromFloat32LE()
*/
* 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);
/*!
* Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit
* little-endian floating point number.
*
* \see fromFloat64BE()
*/
* 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);
/*!
* Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit
* big-endian floating point number.
*
* \see fromFloat64LE()
*/
* 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);
/*!
* Returns a ByteVector based on the CString \a s.
*/
* Returns a ByteVector based on the CString \a s.
*/
static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff);
/*!
* Returns a const reference to the byte at \a index.
*/
* Returns a const reference to the byte at \a index.
*/
const char &operator[](int index) const;
/*!
* Returns a reference to the byte at \a index.
*/
* Returns a reference to the byte at \a index.
*/
char &operator[](int index);
/*!
* Returns true if this ByteVector and \a v are equal.
*/
* Returns true if this ByteVector and \a v are equal.
*/
bool operator==(const ByteVector &v) const;
/*!
* Returns true if this ByteVector and \a v are not equal.
*/
* Returns true if this ByteVector and \a v are not equal.
*/
bool operator!=(const ByteVector &v) const;
/*!
* Returns true if this ByteVector and the null terminated C string \a s
* contain the same data.
*/
* Returns true if this ByteVector and the null terminated C string \a s contain the same data.
*/
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.
*/
* 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;
/*!
* 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.
*/
* 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;
/*!
* Returns true if this ByteVector is greater than \a v.
*/
* Returns true if this ByteVector is greater than \a v.
*/
bool operator>(const ByteVector &v) const;
/*!
* Returns a vector that is \a v appended to this vector.
*/
* Returns a vector that is \a v appended to this vector.
*/
ByteVector operator+(const ByteVector &v) const;
/*!
* Copies ByteVector \a v.
*/
* Copies ByteVector \a v.
*/
ByteVector &operator=(const ByteVector &v);
/*!
* Copies a byte \a c.
*/
* Copies a byte \a 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.
*/
* 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);
/*!
* Exchanges the content of the ByteVector by the content of \a v.
*/
* Exchanges the content of the ByteVector by the content of \a 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).
*
* \warning Do not modify this variable. It will mess up the internal state
* of TagLib.
*
* \deprecated
*/
* A static, empty ByteVector which is convenient and fast (since returning an empty or "null" value does not require instantiating a new ByteVector).
*
* \warning Do not modify this variable. It will mess up the internal state
* of TagLib.
*
* \deprecated
*/
// BIC: remove
static ByteVector null;
/*!
* Returns a hex-encoded copy of the byte vector.
*/
* Returns a hex-encoded copy of the byte vector.
*/
ByteVector toHex() const;
/*!
* Returns a base64 encoded copy of the byte vector
*/
* Returns a base64 encoded copy of the byte vector
*/
ByteVector toBase64() const;
/*!
* Decodes the base64 encoded byte vector.
*/
* Decodes the base64 encoded byte vector.
*/
static ByteVector fromBase64(const ByteVector &);
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.
*/
* 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();
private:

View File

@@ -27,26 +27,18 @@
using namespace Strawberry_TagLib::TagLib;
class ByteVectorListPrivate {
};
class ByteVectorListPrivate {};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern,
int byteAlign) {
return split(v, pattern, byteAlign, 0);
}
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, int byteAlign, int max) {
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern,
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)) {
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
@@ -59,20 +51,19 @@ ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &patt
l.append(v.mid(previousOffset, v.size() - previousOffset));
return l;
}
////////////////////////////////////////////////////////////////////////////////
// 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 v;
ConstIterator it = begin();
@@ -80,9 +71,9 @@ ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const {
while (it != end()) {
v.append(*it);
it++;
if (it != end())
v.append(separator);
if (it != end()) v.append(separator);
}
return v;
}

View File

@@ -36,43 +36,34 @@ namespace TagLib {
//! A list of ByteVectors
/*!
* A List specialization with some handy features useful for ByteVectors.
*/
* A List specialization with some handy features useful for ByteVectors.
*/
class TAGLIB_EXPORT ByteVectorList : public List<ByteVector> {
public:
/*!
* Construct an empty ByteVectorList.
*/
* Construct an empty ByteVectorList.
*/
ByteVectorList();
/*!
* Destroys this ByteVectorList instance.
*/
* Destroys this ByteVectorList instance.
*/
virtual ~ByteVectorList();
/*!
* Convert the ByteVectorList to a ByteVector separated by \a separator. By
* default a space is used.
*/
* Convert the ByteVectorList to a ByteVector separated by \a separator. By default a space is used.
*/
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);
/*!
* 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);
* 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.
*/
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, int byteAlign = 1, int max = 0);
private:
class ByteVectorListPrivate;

View File

@@ -42,16 +42,13 @@ class ByteVectorStream::ByteVectorStreamPrivate {
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() {
delete d;
@@ -62,24 +59,29 @@ FileName ByteVectorStream::name() const {
}
ByteVector ByteVectorStream::readBlock(unsigned long length) {
if (length == 0)
return ByteVector();
ByteVector v = d->data.mid(d->position, length);
d->position += v.size();
return v;
}
void ByteVectorStream::writeBlock(const ByteVector &data) {
unsigned int size = data.size();
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) {
long sizeDiff = data.size() - replace;
if (sizeDiff < 0) {
removeBlock(start + data.size(), -sizeDiff);
@@ -92,9 +94,11 @@ void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsig
}
seek(start);
writeBlock(data);
}
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())) {
@@ -104,6 +108,7 @@ void ByteVectorStream::removeBlock(unsigned long start, unsigned long length) {
}
d->position = writePosition;
truncate(writePosition);
}
bool ByteVectorStream::readOnly() const {
@@ -115,6 +120,7 @@ bool ByteVectorStream::isOpen() const {
}
void ByteVectorStream::seek(long offset, Position p) {
switch (p) {
case Beginning:
d->position = offset;
@@ -126,10 +132,10 @@ void ByteVectorStream::seek(long offset, Position p) {
d->position = length() + offset; // offset is expected to be negative
break;
}
}
void ByteVectorStream::clear() {
}
void ByteVectorStream::clear() {}
long ByteVectorStream::tell() const {
return d->position;

View File

@@ -43,92 +43,84 @@ class AudioProperties;
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.
*/
* 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);
/*!
* Destroys this ByteVectorStream instance.
*/
* Destroys this ByteVectorStream instance.
*/
virtual ~ByteVectorStream();
/*!
* Returns the file name in the local file system encoding.
*/
* Returns the file name in the local file system encoding.
*/
FileName name() const;
/*!
* Reads a block of size \a length at the current get pointer.
*/
* Reads a block of size \a length at the current get pointer.
*/
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.
*
* \note This should be used instead of using the streaming output operator
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
* 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.
*
* \note This should be used instead of using the streaming output operator for a ByteVector.
* And even this function is significantly slower than doing output with a char[].
*/
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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
* Returns true if the file is read only (or if the file can not be opened).
*/
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.
*/
* 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;
/*!
* 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
*/
* 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);
/*!
* Reset the end-of-file and error flags on the file.
*/
* Reset the end-of-file and error flags on the file.
*/
void clear();
/*!
* Returns the current offset within the file.
*/
* Returns the current offset within the file.
*/
long tell() const;
/*!
* Returns the length of the file.
*/
* Returns the length of the file.
*/
long length();
/*!
* Truncates the file to a \a length.
*/
* Truncates the file to a \a length.
*/
void truncate(long length);
ByteVector *data();

View File

@@ -48,6 +48,7 @@ void debug(const String &s) {
}
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(
@@ -56,6 +57,7 @@ void debugData(const ByteVector &v) {
debugListener->printMessage(msg);
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -64,17 +64,17 @@ namespace Strawberry_TagLib {
namespace TagLib {
DebugListener *debugListener = &defaultListener;
DebugListener::DebugListener() {
}
DebugListener::DebugListener() {}
DebugListener::~DebugListener() {
}
DebugListener::~DebugListener() {}
void setDebugListener(DebugListener *listener) {
if (listener)
debugListener = listener;
else
debugListener = &defaultListener;
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -34,21 +34,21 @@ 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()
*/
* 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();
/*!
* When overridden in a derived class, redirects \a msg to your preferred
* channel such as stderr, Windows debugger or so forth.
*/
* 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;
private:
@@ -58,15 +58,13 @@ class TAGLIB_EXPORT 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.
*
* \note The caller is responsible for deleting the previous listener
* as needed after it is released.
*
* \see 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.
*
* \note The caller is responsible for deleting the previous listener as needed after it is released.
*
* \see DebugListener
*/
TAGLIB_EXPORT void setDebugListener(DebugListener *listener);
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -70,9 +70,7 @@ using namespace Strawberry_TagLib::TagLib;
class File::FilePrivate {
public:
FilePrivate(IOStream* _stream, bool _owner) : stream(_stream),
streamOwner(_owner),
valid(true) {}
FilePrivate(IOStream* _stream, bool _owner) : stream(_stream), streamOwner(_owner), valid(true) {}
~FilePrivate() {
if (streamOwner)
@@ -88,11 +86,9 @@ class File::FilePrivate {
// 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() {
delete d;
@@ -103,6 +99,7 @@ FileName File::name() 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();
@@ -145,11 +142,12 @@ PropertyMap File::properties() const {
if (dynamic_cast<const DSDIFF::File*>(this))
return dynamic_cast<const DSDIFF::File*>(this)->properties();
return tag()->properties();
}
void File::removeUnsupportedProperties(const StringList& properties) {
// here we only consider those formats that could possibly contain
// unsupported 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))
@@ -178,9 +176,11 @@ void File::removeUnsupportedProperties(const StringList& properties) {
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))
@@ -223,6 +223,7 @@ PropertyMap File::setProperties(const PropertyMap& properties) {
return dynamic_cast<DSDIFF::File*>(this)->setProperties(properties);
else
return tag()->setProperties(properties);
}
ByteVector File::readBlock(unsigned long length) {
@@ -234,6 +235,7 @@ void File::writeBlock(const ByteVector& data) {
}
long File::find(const ByteVector& pattern, long fromOffset, const ByteVector& before) {
if (!d->stream || pattern.size() > bufferSize())
return -1;
@@ -325,10 +327,12 @@ long File::find(const ByteVector& pattern, long fromOffset, const ByteVector& be
seek(originalPosition);
return -1;
}
long File::rfind(const ByteVector& pattern, long fromOffset, const ByteVector& before) {
if (!d->stream || pattern.size() > bufferSize())
return -1;
@@ -399,6 +403,7 @@ long File::rfind(const ByteVector& pattern, long fromOffset, const ByteVector& b
seek(originalPosition);
return -1;
}
void File::insert(const ByteVector& data, unsigned long start, unsigned long replace) {
@@ -441,32 +446,6 @@ long File::length() {
return d->stream->length();
}
bool File::isReadable(const char* file) {
#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later
return _access_s(file, R_OK) == 0;
#else
return access(file, R_OK) == 0;
#endif
}
bool File::isWritable(const char* file) {
#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later
return _access_s(file, W_OK) == 0;
#else
return access(file, W_OK) == 0;
#endif
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////

View File

@@ -43,16 +43,16 @@ class PropertyMap;
//! 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.
*/
* 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:
/*!
* Position in the file used for seeking.
*/
* Position in the file used for seeking.
*/
enum Position {
//! Seek from the beginning of the file.
Beginning,
@@ -63,251 +63,220 @@ class TAGLIB_EXPORT File {
};
/*!
* Specify which tags to strip either explicitly, or on save.
*/
* 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
};
/*!
* Used to specify if when saving files, if values between different tag
* types should be syncronized.
*/
* 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
};
/*!
* Destroys this File instance.
*/
* Destroys this File instance.
*/
virtual ~File();
/*!
* Returns the file name in the local file system encoding.
*/
* Returns the file name in the local file system encoding.
*/
FileName name() const;
/*!
* Returns a pointer to this file's tag. This should be reimplemented in
* the concrete subclasses.
*/
* Returns a pointer to this file's tag.
* This should be reimplemented in the concrete subclasses.
*/
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.
* For each metadata object of the file that could not be parsed into the PropertyMap
* format, the returned map's unsupportedData() list will contain one entry identifying
* that object (e.g. the frame type for ID3v2 tags). Use removeUnsupportedProperties()
* to remove (a subset of) them.
* For files that contain more than one tag (e.g. an MP3 with both an ID3v1 and an ID3v2
* tag) only the most "modern" one will be exported (ID3v2 in this case).
* BIC: Will be made virtual in future releases.
*/
* 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.
* For each metadata object of the file that could not be parsed into the PropertyMap
* format, the returned map's unsupportedData() list will contain one entry identifying
* that object (e.g. the frame type for ID3v2 tags). Use removeUnsupportedProperties()
* to remove (a subset of) them.
* For files that contain more than one tag (e.g. an MP3 with both an ID3v1 and an ID3v2
* tag) only the most "modern" one will be exported (ID3v2 in this case).
* BIC: Will be made virtual in future releases.
*/
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.
*/
* 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);
/*!
* 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.
* If some value(s) could not be written imported to the specific metadata format,
* the returned PropertyMap will contain those value(s). Otherwise it will be empty,
* indicating that no problems occurred.
* With file types that support several tag formats (for instance, MP3 files can have
* ID3v1, ID3v2, and APEv2 tags), this function will create the most appropriate one
* (ID3v2 for MP3 files). Older formats will be updated as well, if they exist, but won't
* be taken into account for the return value of this function.
* See the documentation of the subclass implementations for detailed descriptions.
* BIC: will become pure virtual in the future
*/
* 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.
* If some value(s) could not be written imported to the specific metadata format,
* the returned PropertyMap will contain those value(s). Otherwise it will be empty,
* indicating that no problems occurred.
* With file types that support several tag formats (for instance, MP3 files can have
* ID3v1, ID3v2, and APEv2 tags), this function will create the most appropriate one
* (ID3v2 for MP3 files). Older formats will be updated as well, if they exist, but won't
* be taken into account for the return value of this function.
* See the documentation of the subclass implementations for detailed descriptions.
* BIC: will become pure virtual in the future
*/
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.
*/
* 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;
/*!
* Save the file and its associated tags. This should be reimplemented in
* the concrete subclasses. Returns true if the save succeeds.
*
* \warning On UNIX multiple processes are able to write to the same file at
* the same time. This can result in serious file corruption. If you are
* developing a program that makes use of TagLib from multiple processes you
* must insure that you are only doing writes to a particular file from one
* of them.
*/
* Save the file and its associated tags.
* This should be reimplemented in the concrete subclasses.
* Returns true if the save succeeds.
*
* \warning On UNIX multiple processes are able to write to the same file at the same time.
* This can result in serious file corruption.
* If you are developing a program that makes use of TagLib from multiple processes you
* must insure that you are only doing writes to a particular file from one of them.
*/
virtual bool save() = 0;
/*!
* Reads a block of size \a length at the current get pointer.
*/
* Reads a block of size \a length at the current get pointer.
*/
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.
*
* \note This should be used instead of using the streaming output operator
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
* 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.
*
* \note This should be used instead of using the streaming output operator for a ByteVector.
* And even this function is significantly slower than doing output with a char[].
*/
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
* for a tag before the sync frame.
*
* Searching starts at \a fromOffset, which defaults to the beginning of the
* file.
*
* \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());
* 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 for a tag before the sync frame.
*
* Searching starts at \a fromOffset, which defaults to the beginning of the file.
*
* \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());
/*!
* 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
* for a tag before the sync frame.
*
* Searching starts at \a fromOffset and proceeds from the that point to the
* beginning of the file and defaults to the end of the file.
*
* \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.
*/
* 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 for a tag before the sync frame.
*
* Searching starts at \a fromOffset and proceeds from the that point to the
* beginning of the file and defaults to the end of the file.
*
* \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());
/*!
* 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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
* Returns true if the file is read only (or if the file can not be opened).
*/
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.
*/
* 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;
/*!
* Returns true if the file is open and readable.
*/
* Returns true if the file is open and readable.
*/
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
*/
* 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);
/*!
* Reset the end-of-file and error flags on the file.
*/
* Reset the end-of-file and error flags on the file.
*/
void clear();
/*!
* Returns the current offset within the file.
*/
* Returns the current offset within the file.
*/
long tell() const;
/*!
* Returns the length of the file.
*/
* Returns the length of the file.
*/
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);
/*!
* Returns true if \a file can be opened for writing.
*
* \deprecated
*/
TAGLIB_DEPRECATED static bool isWritable(const char *name);
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.
*/
* 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);
/*!
* Construct a File object and use the \a stream instance.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note Constructor is protected since this class should only be
* instantiated through subclasses.
*/
* Construct a File object and use the \a stream instance.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*
* \note Constructor is protected since this class should only be instantiated through subclasses.
*/
File(IOStream *stream);
/*!
* Marks the file as valid or invalid.
*
* \see isValid()
*/
* Marks the file as valid or invalid.
*
* \see isValid()
*/
void setValid(bool valid);
/*!
* Truncates the file to a \a length.
*/
* Truncates the file to a \a length.
*/
void truncate(long length);
/*!
* Returns the buffer size that is used for internal buffering.
*/
* Returns the buffer size that is used for internal buffering.
*/
static unsigned int bufferSize();
private:

View File

@@ -47,6 +47,7 @@ typedef HANDLE FileHandle;
const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE;
FileHandle openFile(const FileName &path, bool readOnly) {
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
# if defined(PLATFORM_WINRT)
@@ -65,19 +66,23 @@ void closeFile(FileHandle 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
@@ -89,7 +94,7 @@ struct FileNameHandle : public std::string {
typedef FILE *FileHandle;
const FileHandle InvalidFileHandle = 0;
const FileHandle InvalidFileHandle = nullptr;
FileHandle openFile(const FileName &path, bool readOnly) {
return fopen(path, readOnly ? "rb" : "rb+");
@@ -131,6 +136,7 @@ class FileStream::FileStreamPrivate {
FileStream::FileStream(FileName fileName, bool openReadOnly)
: d(new FileStreamPrivate(fileName)) {
// First try with read / write mode, if that fails, fall back to read only.
if (!openReadOnly)
@@ -147,10 +153,11 @@ FileStream::FileStream(FileName fileName, bool openReadOnly)
#else
debug("Could not open file " + String(static_cast<const char *>(d->name)));
#endif
}
FileStream::FileStream(int fileDescriptor, bool openReadOnly)
: d(new FileStreamPrivate("")) {
FileStream::FileStream(int fileDescriptor, bool openReadOnly) : d(new FileStreamPrivate("")) {
// First try with read / write mode, if that fails, fall back to read only.
if (!openReadOnly)
@@ -163,13 +170,16 @@ FileStream::FileStream(int fileDescriptor, bool openReadOnly)
if (d->file == InvalidFileHandle)
debug("Could not open file using file descriptor");
}
FileStream::~FileStream() {
if (isOpen())
closeFile(d->file);
delete d;
}
FileName FileStream::name() const {
@@ -177,6 +187,7 @@ FileName FileStream::name() const {
}
ByteVector FileStream::readBlock(unsigned long length) {
if (!isOpen()) {
debug("FileStream::readBlock() -- invalid file.");
return ByteVector();
@@ -195,9 +206,11 @@ ByteVector FileStream::readBlock(unsigned long length) {
buffer.resize(static_cast<unsigned int>(count));
return buffer;
}
void FileStream::writeBlock(const ByteVector &data) {
if (!isOpen()) {
debug("FileStream::writeBlock() -- invalid file.");
return;
@@ -209,9 +222,11 @@ void FileStream::writeBlock(const ByteVector &data) {
}
writeFile(d->file, data);
}
void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) {
if (!isOpen()) {
debug("FileStream::insert() -- invalid file.");
return;
@@ -289,9 +304,11 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
buffer = aboutToOverwrite;
}
}
void FileStream::removeBlock(unsigned long start, unsigned long length) {
if (!isOpen()) {
debug("FileStream::removeBlock() -- invalid file.");
return;
@@ -324,6 +341,7 @@ void FileStream::removeBlock(unsigned long start, unsigned long length) {
}
truncate(writePosition);
}
bool FileStream::readOnly() const {
@@ -335,6 +353,7 @@ bool FileStream::isOpen() const {
}
void FileStream::seek(long offset, Position p) {
if (!isOpen()) {
debug("FileStream::seek() -- invalid file.");
return;
@@ -375,6 +394,7 @@ void FileStream::seek(long offset, Position p) {
fseek(d->file, offset, whence);
#endif
}
void FileStream::clear() {
@@ -412,6 +432,7 @@ long FileStream::tell() const {
}
long FileStream::length() {
if (!isOpen()) {
debug("FileStream::length() -- invalid file.");
return 0;

View File

@@ -41,111 +41,104 @@ class AudioProperties;
//! 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.
*/
* 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:
/*!
* Construct a File object and opens the \a file. \a file should be a
* be a C-string in the local file system encoding.
*/
* 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);
/*!
* Construct a File object and opens the \a file using file descriptor.
*/
* Construct a File object and opens the \a file using file descriptor.
*/
FileStream(int fileDescriptor, bool openReadOnly = false);
/*!
* Destroys this FileStream instance.
*/
* Destroys this FileStream instance.
*/
virtual ~FileStream();
/*!
* Returns the file name in the local file system encoding.
*/
* Returns the file name in the local file system encoding.
*/
FileName name() const;
/*!
* Reads a block of size \a length at the current get pointer.
*/
* Reads a block of size \a length at the current get pointer.
*/
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.
*
* \note This should be used instead of using the streaming output operator
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
* 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.
*
* \note This should be used instead of using the streaming output operator for a ByteVector.
* And even this function is significantly slower than doing output with a char[].
*/
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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
* Returns true if the file is read only (or if the file can not be opened).
*/
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.
*/
* 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;
/*!
* 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
*/
* 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);
/*!
* Reset the end-of-file and error flags on the file.
*/
* Reset the end-of-file and error flags on the file.
*/
void clear();
/*!
* Returns the current offset within the file.
*/
* Returns the current offset within the file.
*/
long tell() const;
/*!
* Returns the length of the file.
*/
* Returns the length of the file.
*/
long length();
/*!
* Truncates the file to a \a length.
*/
* Truncates the file to a \a length.
*/
void truncate(long length);
protected:
/*!
* Returns the buffer size that is used for internal buffering.
*/
* Returns the buffer size that is used for internal buffering.
*/
static unsigned int bufferSize();
private:

View File

@@ -36,6 +36,7 @@ using namespace Strawberry_TagLib::TagLib;
namespace {
std::wstring ansiToUnicode(const char *str) {
const int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
if (len == 0)
return std::wstring();
@@ -44,22 +45,17 @@ std::wstring ansiToUnicode(const char *str) {
MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], len);
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 {
return m_wname.c_str();
@@ -87,11 +83,8 @@ String FileName::toString() const {
// public members
////////////////////////////////////////////////////////////////////////////////
IOStream::IOStream() {
}
IOStream::IOStream() {}
IOStream::~IOStream() {
}
IOStream::~IOStream() {}
void IOStream::clear() {
}
void IOStream::clear() {}

View File

@@ -62,8 +62,8 @@ typedef const char *FileName;
class TAGLIB_EXPORT IOStream {
public:
/*!
* Position in the file used for seeking.
*/
* Position in the file used for seeking.
*/
enum Position {
//! Seek from the beginning of the file.
Beginning,
@@ -76,87 +76,80 @@ class TAGLIB_EXPORT IOStream {
IOStream();
/*!
* Destroys this IOStream instance.
*/
* Destroys this IOStream instance.
*/
virtual ~IOStream();
/*!
* Returns the stream name in the local file system encoding.
*/
* Returns the stream name in the local file system encoding.
*/
virtual FileName name() const = 0;
/*!
* Reads a block of size \a length at the current get pointer.
*/
* Reads a block of size \a length at the current get pointer.
*/
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.
*
* \note This should be used instead of using the streaming output operator
* for a ByteVector. And even this function is significantly slower than
* doing output with a char[].
*/
* 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.
*
* \note This should be used instead of using the streaming output operator for a ByteVector.
* And even this function is significantly slower than doing output with a char[].
*/
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.
*/
* 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;
/*!
* 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.
*/
* 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;
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
* Returns true if the file is read only (or if the file can not be opened).
*/
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.
*/
* 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;
/*!
* 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
*/
* 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;
/*!
* Reset the end-of-stream and error flags on the stream.
*/
* Reset the end-of-stream and error flags on the stream.
*/
virtual void clear();
/*!
* Returns the current offset within the stream.
*/
* Returns the current offset within the stream.
*/
virtual long tell() const = 0;
/*!
* Returns the length of the stream.
*/
* Returns the length of the stream.
*/
virtual long length() = 0;
/*!
* Truncates the stream to a \a length.
*/
* Truncates the stream to a \a length.
*/
virtual void truncate(long length) = 0;
private:

View File

@@ -36,8 +36,8 @@ namespace TagLib {
//! 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:
* This is basic generic list that's somewhere between a std::list and a QValueList.
* This class is implicitly shared. For example:
*
* \code
*
@@ -45,10 +45,10 @@ namespace TagLib {
*
* \endcode
*
* The above example is very cheap. This also makes lists suitable for the
* return types of functions. The above example will just copy a pointer rather
* than copying the data in the list. When your \e shared list's data changes,
* only \e then will the data be copied.
* The above example is very cheap.
* This also makes lists suitable for the return types of functions.
* The above example will just copy a pointer rather than copying the data in the list.
* When your \e shared list's data changes, only \e then will the data be copied.
*/
template<class T> class List {
@@ -59,198 +59,185 @@ template<class T> class List {
#endif
/*!
* Constructs an empty list.
*/
* Constructs an empty 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.
*/
* 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);
/*!
* Destroys this List instance. If auto deletion is enabled and this list
* contains a pointer type all of the members are also deleted.
*/
* 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();
/*!
* Returns an STL style iterator to the beginning of the list. See
* std::list::const_iterator for the semantics.
*/
* Returns an STL style iterator to the beginning of the list.
* See std::list::const_iterator for the semantics.
*/
Iterator begin();
/*!
* Returns an STL style constant iterator to the beginning of the list. See
* std::list::iterator for the semantics.
*/
* Returns an STL style constant iterator to the beginning of the list.
* See std::list::iterator for the semantics.
*/
ConstIterator begin() const;
/*!
* Returns an STL style iterator to the end of the list. See
* std::list::iterator for the semantics.
*/
* Returns an STL style iterator to the end of the list.
* See std::list::iterator for the semantics.
*/
Iterator end();
/*!
* Returns an STL style constant iterator to the end of the list. See
* std::list::const_iterator for the semantics.
*/
* Returns an STL style constant iterator to the end of the list.
* See std::list::const_iterator for the semantics.
*/
ConstIterator end() const;
/*!
* Inserts a copy of \a value before \a it.
*/
* Inserts a copy of \a value before \a it.
*/
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.
*/
* 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);
/*!
* Appends \a item to the end of the list and returns a reference to the
* list.
*/
* Appends \a item to the end of the list and returns a reference to the list.
*/
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.
*/
* 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);
/*!
* Prepends \a item to the beginning list and returns a reference to the
* list.
*/
* Prepends \a item to the beginning list and returns a reference to the list.
*/
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.
*/
* 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);
/*!
* Clears the list. If auto deletion is enabled and this list contains a
* pointer type the members are also deleted.
*
* \see setAutoDelete()
*/
* 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();
/*!
* Returns the number of elements in the list.
*
* \see isEmpty()
*/
* Returns the number of elements in the list.
*
* \see isEmpty()
*/
unsigned int size() const;
/*!
* Returns whether or not the list is empty.
*
* \see size()
*/
* Returns whether or not the list is empty.
*
* \see size()
*/
bool isEmpty() const;
/*!
* Find the first occurrence of \a value.
*/
* Find the first occurrence of \a value.
*/
Iterator find(const T &value);
/*!
* Find the first occurrence of \a value.
*/
* Find the first occurrence of \a value.
*/
ConstIterator find(const T &value) const;
/*!
* Returns true if the list contains \a value.
*/
* Returns true if the list contains \a value.
*/
bool contains(const T &value) const;
/*!
* Erase the item at \a it from the list.
*/
* Erase the item at \a it from the list.
*/
Iterator erase(Iterator it);
/*!
* Returns a reference to the first item in the list.
*/
* Returns a reference to the first item in the list.
*/
const T &front() const;
/*!
* Returns a reference to the first item in the list.
*/
* Returns a reference to the first item in the list.
*/
T &front();
/*!
* Returns a reference to the last item in the list.
*/
* Returns a reference to the last item in the list.
*/
const T &back() const;
/*!
* Returns a reference to the last item in the list.
*/
* Returns a reference to the last item in the list.
*/
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.
*
* \note This relies on partial template instantiation -- most modern C++
* compilers should now support this.
*/
* 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.
*
* \note This relies on partial template instantiation -- most modern C++ compilers should now support this.
*/
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.
*/
* 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);
/*!
* Returns a const reference to item \a i in the list.
*
* \warning This method is slow. Use iterators to loop through the list.
*/
* 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;
/*!
* 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.
*/
* 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);
/*!
* Exchanges the content of this list by the content of \a l.
*/
* Exchanges the content of this list by the content of \a l.
*/
void swap(List<T> &l);
/*!
* Compares this list with \a l and returns true if all of the elements are
* the same.
*/
* Compares this list with \a l and returns true if all of the elements are the same.
*/
bool operator==(const List<T> &l) const;
/*!
* Compares this list with \a l and returns true if the lists differ.
*/
* Compares this list with \a l and returns true if the lists differ.
*/
bool operator!=(const List<T> &l) const;
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.
*/
* 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();
private:
@@ -263,8 +250,7 @@ template<class T> class List {
} // namespace TagLib
} // namespace Strawberry_TagLib
// Since GCC doesn't support the "export" keyword, we have to include the
// implementation.
// Since GCC doesn't support the "export" keyword, we have to include the implementation.
#include "tlist.tcc"

View File

@@ -33,16 +33,14 @@ namespace TagLib {
// public members
////////////////////////////////////////////////////////////////////////////////
// The functionality of List<T>::setAutoDelete() is implemented here partial
// template specialization. This is implemented in such a way that calling
// setAutoDelete() on non-pointer types will simply have no effect.
// The functionality of List<T>::setAutoDelete() is implemented here partial template specialization.
// This is implemented in such a way that calling setAutoDelete() on non-pointer types will simply have no effect.
// A base for the generic and specialized private class types. New
// non-templatized members should be added here.
// A base for the generic and specialized private class types.
// New non-templatized members should be added here.
// BIC change to RefCounter
class ListPrivateBase : public RefCounterOld
{
class ListPrivateBase : public RefCounterOld {
public:
ListPrivateBase() : autoDelete(false) {}
bool autoDelete;
@@ -62,8 +60,7 @@ public:
std::list<TP> list;
};
// A partial specialization for all pointer types that implements the
// setAutoDelete() functionality.
// A partial specialization for all pointer types that implements the setAutoDelete() functionality.
template <class T>
template <class TP> class List<T>::ListPrivate<TP *> : public ListPrivateBase
@@ -90,60 +87,49 @@ public:
////////////////////////////////////////////////////////////////////////////////
template <class T>
List<T>::List() :
d(new ListPrivate<T>())
{
}
List<T>::List() : d(new ListPrivate<T>()){}
template <class T>
List<T>::List(const List<T> &l) : d(l.d)
{
List<T>::List(const List<T> &l) : d(l.d) {
d->ref();
}
template <class T>
List<T>::~List()
{
List<T>::~List() {
if(d->deref())
delete d;
}
template <class T>
typename List<T>::Iterator List<T>::begin()
{
typename List<T>::Iterator List<T>::begin() {
detach();
return d->list.begin();
}
template <class T>
typename List<T>::ConstIterator List<T>::begin() const
{
typename List<T>::ConstIterator List<T>::begin() const {
return d->list.begin();
}
template <class T>
typename List<T>::Iterator List<T>::end()
{
typename List<T>::Iterator List<T>::end() {
detach();
return d->list.end();
}
template <class T>
typename List<T>::ConstIterator List<T>::end() const
{
typename List<T>::ConstIterator List<T>::end() const {
return d->list.end();
}
template <class T>
typename List<T>::Iterator List<T>::insert(Iterator it, const T &item)
{
typename List<T>::Iterator List<T>::insert(Iterator it, const T &item) {
detach();
return d->list.insert(it, item);
}
template <class T>
List<T> &List<T>::sortedInsert(const T &value, bool unique)
{
List<T> &List<T>::sortedInsert(const T &value, bool unique) {
detach();
Iterator it = begin();
while(it != end() && *it < value)
@@ -155,117 +141,100 @@ List<T> &List<T>::sortedInsert(const T &value, bool unique)
}
template <class T>
List<T> &List<T>::append(const T &item)
{
List<T> &List<T>::append(const T &item) {
detach();
d->list.push_back(item);
return *this;
}
template <class T>
List<T> &List<T>::append(const List<T> &l)
{
List<T> &List<T>::append(const List<T> &l) {
detach();
d->list.insert(d->list.end(), l.begin(), l.end());
return *this;
}
template <class T>
List<T> &List<T>::prepend(const T &item)
{
List<T> &List<T>::prepend(const T &item) {
detach();
d->list.push_front(item);
return *this;
}
template <class T>
List<T> &List<T>::prepend(const List<T> &l)
{
List<T> &List<T>::prepend(const List<T> &l) {
detach();
d->list.insert(d->list.begin(), l.begin(), l.end());
return *this;
}
template <class T>
List<T> &List<T>::clear()
{
List<T> &List<T>::clear() {
detach();
d->clear();
return *this;
}
template <class T>
unsigned int List<T>::size() const
{
unsigned int List<T>::size() const {
return static_cast<unsigned int>(d->list.size());
}
template <class T>
bool List<T>::isEmpty() const
{
bool List<T>::isEmpty() const {
return d->list.empty();
}
template <class T>
typename List<T>::Iterator List<T>::find(const T &value)
{
typename List<T>::Iterator List<T>::find(const T &value) {
detach();
return std::find(d->list.begin(), d->list.end(), value);
}
template <class T>
typename List<T>::ConstIterator List<T>::find(const T &value) const
{
typename List<T>::ConstIterator List<T>::find(const T &value) const {
return std::find(d->list.begin(), d->list.end(), value);
}
template <class T>
bool List<T>::contains(const T &value) const
{
bool List<T>::contains(const T &value) const {
return std::find(d->list.begin(), d->list.end(), value) != d->list.end();
}
template <class T>
typename List<T>::Iterator List<T>::erase(Iterator it)
{
typename List<T>::Iterator List<T>::erase(Iterator it) {
return d->list.erase(it);
}
template <class T>
const T &List<T>::front() const
{
const T &List<T>::front() const {
return d->list.front();
}
template <class T>
T &List<T>::front()
{
T &List<T>::front() {
detach();
return d->list.front();
}
template <class T>
const T &List<T>::back() const
{
const T &List<T>::back() const {
return d->list.back();
}
template <class T>
void List<T>::setAutoDelete(bool autoDelete)
{
void List<T>::setAutoDelete(bool autoDelete) {
d->autoDelete = autoDelete;
}
template <class T>
T &List<T>::back()
{
T &List<T>::back() {
detach();
return d->list.back();
}
template <class T>
T &List<T>::operator[](unsigned int i)
{
T &List<T>::operator[](unsigned int i) {
Iterator it = d->list.begin();
std::advance(it, i);
@@ -273,8 +242,7 @@ T &List<T>::operator[](unsigned int i)
}
template <class T>
const T &List<T>::operator[](unsigned int i) const
{
const T &List<T>::operator[](unsigned int i) const {
ConstIterator it = d->list.begin();
std::advance(it, i);
@@ -282,29 +250,25 @@ const T &List<T>::operator[](unsigned int i) const
}
template <class T>
List<T> &List<T>::operator=(const List<T> &l)
{
List<T> &List<T>::operator=(const List<T> &l) {
List<T>(l).swap(*this);
return *this;
}
template <class T>
void List<T>::swap(List<T> &l)
{
void List<T>::swap(List<T> &l) {
using std::swap;
swap(d, l.d);
}
template <class T>
bool List<T>::operator==(const List<T> &l) const
{
bool List<T>::operator==(const List<T> &l) const {
return d->list == l.d->list;
}
template <class T>
bool List<T>::operator!=(const List<T> &l) const
{
bool List<T>::operator!=(const List<T> &l) const {
return d->list != l.d->list;
}
@@ -313,8 +277,7 @@ bool List<T>::operator!=(const List<T> &l) const
////////////////////////////////////////////////////////////////////////////////
template <class T>
void List<T>::detach()
{
void List<T>::detach() {
if(d->count() > 1) {
d->deref();
d = new ListPrivate<T>(d->list);

View File

@@ -36,23 +36,19 @@ namespace TagLib {
//! 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.
*/
* 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:
#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.
// 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
@@ -62,129 +58,126 @@ template<class Key, class T> class Map {
#endif
/*!
* Constructs an empty Map.
*/
* Constructs an empty 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.
*/
* 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);
/*!
* Destroys this instance of the Map.
*/
* Destroys this instance of the Map.
*/
virtual ~Map();
/*!
* Returns an STL style iterator to the beginning of the map. See
* std::map::iterator for the semantics.
*/
* Returns an STL style iterator to the beginning of the map.
* See std::map::iterator for the semantics.
*/
Iterator begin();
/*!
* Returns an STL style iterator to the beginning of the map. See
* std::map::const_iterator for the semantics.
*/
* Returns an STL style iterator to the beginning of the map.
* See std::map::const_iterator for the semantics.
*/
ConstIterator begin() const;
/*!
* Returns an STL style iterator to the end of the map. See
* std::map::iterator for the semantics.
*/
* Returns an STL style iterator to the end of the map.
* See std::map::iterator for the semantics.
*/
Iterator end();
/*!
* Returns an STL style iterator to the end of the map. See
* std::map::const_iterator for the semantics.
*/
* Returns an STL style iterator to the end of the map.
* See std::map::const_iterator for the semantics.
*/
ConstIterator end() const;
/*!
* Inserts \a value under \a key in the map. If a value for \a key already
* exists it will be overwritten.
*/
* 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);
/*!
* Removes all of the elements from elements from the map. This however
* will not delete pointers if the mapped type is a pointer type.
*/
* 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();
/*!
* The number of elements in the map.
*
* \see isEmpty()
*/
* The number of elements in the map.
*
* \see isEmpty()
*/
unsigned int size() const;
/*!
* Returns true if the map is empty.
*
* \see size()
*/
* Returns true if the map is empty.
*
* \see size()
*/
bool isEmpty() const;
/*!
* Find the first occurrence of \a key.
*/
* Find the first occurrence of \a key.
*/
Iterator find(const Key &key);
/*!
* Find the first occurrence of \a key.
*/
* Find the first occurrence of \a key.
*/
ConstIterator find(const Key &key) const;
/*!
* Returns true if the map contains an instance of \a key.
*/
* Returns true if the map contains an instance of \a key.
*/
bool contains(const Key &key) const;
/*!
* Erase the item at \a it from the list.
*/
* Erase the item at \a it from the list.
*/
Map<Key, T> &erase(Iterator it);
/*!
* Erase the item with \a key from the list.
*/
* Erase the item with \a key from the list.
*/
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.
*/
* 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;
/*!
* Returns a reference to the value associated with \a key.
*
* \note This has undefined behavior if the key is not present in the map.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* Exchanges the content of this map by the content of \a m.
*/
* Exchanges the content of this map by the content of \a m.
*/
void swap(Map<Key, T> &m);
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.
*/
* 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();
private:
@@ -197,8 +190,7 @@ template<class Key, class T> class Map {
} // namespace TagLib
} // namespace Strawberry_TagLib
// Since GCC doesn't support the "export" keyword, we have to include the
// implementation.
// Since GCC doesn't support the "export" keyword, we have to include the implementation.
#include "tmap.tcc"

View File

@@ -35,8 +35,7 @@ namespace TagLib {
// BIC change to RefCounter
template <class Key, class T>
template <class KeyP, class TP>
class Map<Key, T>::MapPrivate : public RefCounterOld
{
class Map<Key, T>::MapPrivate : public RefCounterOld {
public:
MapPrivate() : RefCounterOld() {}
#ifdef WANT_CLASS_INSTANTIATION_OF_MAP
@@ -49,136 +48,114 @@ public:
};
template <class Key, class T>
Map<Key, T>::Map() :
d(new MapPrivate<Key, T>())
{
}
Map<Key, T>::Map() : d(new MapPrivate<Key, T>()){}
template <class Key, class T>
Map<Key, T>::Map(const Map<Key, T> &m) : d(m.d)
{
Map<Key, T>::Map(const Map<Key, T> &m) : d(m.d) {
d->ref();
}
template <class Key, class T>
Map<Key, T>::~Map()
{
Map<Key, T>::~Map() {
if(d->deref())
delete(d);
}
template <class Key, class T>
typename Map<Key, T>::Iterator Map<Key, T>::begin()
{
typename Map<Key, T>::Iterator Map<Key, T>::begin() {
detach();
return d->map.begin();
}
template <class Key, class T>
typename Map<Key, T>::ConstIterator Map<Key, T>::begin() const
{
typename Map<Key, T>::ConstIterator Map<Key, T>::begin() const {
return d->map.begin();
}
template <class Key, class T>
typename Map<Key, T>::Iterator Map<Key, T>::end()
{
typename Map<Key, T>::Iterator Map<Key, T>::end() {
detach();
return d->map.end();
}
template <class Key, class T>
typename Map<Key, T>::ConstIterator Map<Key, T>::end() const
{
typename Map<Key, T>::ConstIterator Map<Key, T>::end() const {
return d->map.end();
}
template <class Key, class T>
Map<Key, T> &Map<Key, T>::insert(const Key &key, const T &value)
{
Map<Key, T> &Map<Key, T>::insert(const Key &key, const T &value) {
detach();
d->map[key] = value;
return *this;
}
template <class Key, class T>
Map<Key, T> &Map<Key, T>::clear()
{
Map<Key, T> &Map<Key, T>::clear() {
detach();
d->map.clear();
return *this;
}
template <class Key, class T>
bool Map<Key, T>::isEmpty() const
{
bool Map<Key, T>::isEmpty() const {
return d->map.empty();
}
template <class Key, class T>
typename Map<Key, T>::Iterator Map<Key, T>::find(const Key &key)
{
typename Map<Key, T>::Iterator Map<Key, T>::find(const Key &key) {
detach();
return d->map.find(key);
}
template <class Key, class T>
typename Map<Key,T>::ConstIterator Map<Key, T>::find(const Key &key) const
{
typename Map<Key,T>::ConstIterator Map<Key, T>::find(const Key &key) const {
return d->map.find(key);
}
template <class Key, class T>
bool Map<Key, T>::contains(const Key &key) const
{
bool Map<Key, T>::contains(const Key &key) const {
return d->map.find(key) != d->map.end();
}
template <class Key, class T>
Map<Key, T> &Map<Key,T>::erase(Iterator it)
{
Map<Key, T> &Map<Key,T>::erase(Iterator it) {
detach();
d->map.erase(it);
return *this;
}
template <class Key, class T>
Map<Key, T> &Map<Key,T>::erase(const Key &key)
{
Map<Key, T> &Map<Key,T>::erase(const Key &key) {
detach();
d->map.erase(key);
return *this;
}
template <class Key, class T>
unsigned int Map<Key, T>::size() const
{
unsigned int Map<Key, T>::size() const {
return static_cast<unsigned int>(d->map.size());
}
template <class Key, class T>
const T &Map<Key, T>::operator[](const Key &key) const
{
const T &Map<Key, T>::operator[](const Key &key) const {
return d->map[key];
}
template <class Key, class T>
T &Map<Key, T>::operator[](const Key &key)
{
T &Map<Key, T>::operator[](const Key &key) {
detach();
return d->map[key];
}
template <class Key, class T>
Map<Key, T> &Map<Key, T>::operator=(const Map<Key, T> &m)
{
Map<Key, T> &Map<Key, T>::operator=(const Map<Key, T> &m) {
Map<Key, T>(m).swap(*this);
return *this;
}
template <class Key, class T>
void Map<Key, T>::swap(Map<Key, T> &m)
{
void Map<Key, T>::swap(Map<Key, T> &m) {
using std::swap;
swap(d, m.d);
@@ -189,8 +166,7 @@ void Map<Key, T>::swap(Map<Key, T> &m)
////////////////////////////////////////////////////////////////////////////////
template <class Key, class T>
void Map<Key, T>::detach()
{
void Map<Key, T>::detach() {
if(d->count() > 1) {
d->deref();
d = new MapPrivate<Key, T>(d->map);

View File

@@ -52,13 +52,16 @@ bool PropertyMap::insert(const String &key, const StringList &values) {
else
SimplePropertyMap::operator[](realKey).append(values);
return true;
}
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) {
@@ -74,13 +77,16 @@ bool PropertyMap::contains(const String &key) const {
}
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;
}
return true;
}
PropertyMap &PropertyMap::erase(const String &key) {
@@ -95,10 +101,12 @@ PropertyMap &PropertyMap::erase(const PropertyMap &other) {
}
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 {
@@ -110,6 +118,7 @@ StringList &PropertyMap::operator[](const String &key) {
}
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))
@@ -121,6 +130,7 @@ bool PropertyMap::operator==(const PropertyMap &other) const {
return false;
}
return unsupported == other.unsupported;
}
bool PropertyMap::operator!=(const PropertyMap &other) const {
@@ -128,6 +138,7 @@ bool PropertyMap::operator!=(const PropertyMap &other) const {
}
String PropertyMap::toString() const {
String ret;
for (ConstIterator it = begin(); it != end(); ++it)
@@ -135,15 +146,18 @@ String PropertyMap::toString() const {
if (!unsupported.isEmpty())
ret += "Unsupported Data: " + unsupported.toString(", ") + "\n";
return ret;
}
void PropertyMap::removeEmpty() {
PropertyMap m;
for (ConstIterator it = begin(); it != end(); ++it) {
if (!it->second.isEmpty())
m.insert(it->first, it->second);
}
*this = m;
}
StringList &PropertyMap::unsupportedData() {

View File

@@ -37,74 +37,70 @@ typedef Map<String, StringList> SimplePropertyMap;
//! 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
* unicode String.
*
* Note that most metadata formats pose additional conditions on the tag keys. The
* most popular ones (Vorbis, APE, ID3v2) should support all ASCII only words of
* length between 2 and 16.
*
* This class can contain any tags, but here is a list of "well-known" tags that
* you might want to use:
*
* Basic tags:
*
* - TITLE
* - ALBUM
* - ARTIST
* - ALBUMARTIST
* - SUBTITLE
* - TRACKNUMBER
* - DISCNUMBER
* - DATE
* - ORIGINALDATE
* - GENRE
* - COMMENT
*
* Sort names:
*
* - TITLESORT
* - ALBUMSORT
* - ARTISTSORT
* - ALBUMARTISTSORT
*
* Credits:
*
* - COMPOSER
* - LYRICIST
* - CONDUCTOR
* - REMIXER
* - PERFORMER:<XXXX>
*
* Other tags:
*
* - ISRC
* - ASIN
* - BPM
* - COPYRIGHT
* - ENCODEDBY
* - MOOD
* - COMMENT
* - MEDIA
* - LABEL
* - CATALOGNUMBER
* - BARCODE
*
* MusicBrainz identifiers:
*
* - MUSICBRAINZ_TRACKID
* - MUSICBRAINZ_ALBUMID
* - MUSICBRAINZ_RELEASEGROUPID
* - MUSICBRAINZ_WORKID
* - MUSICBRAINZ_ARTISTID
* - MUSICBRAINZ_ALBUMARTISTID
* - ACOUSTID_ID
* - ACOUSTID_FINGERPRINT
* - MUSICIP_PUID
*
*/
* 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 unicode String.
*
* Note that most metadata formats pose additional conditions on the tag keys.
* The most popular ones (Vorbis, APE, ID3v2) should support all ASCII only words of length between 2 and 16.
*
* This class can contain any tags, but here is a list of "well-known" tags that you might want to use:
*
* Basic tags:
*
* - TITLE
* - ALBUM
* - ARTIST
* - ALBUMARTIST
* - SUBTITLE
* - TRACKNUMBER
* - DISCNUMBER
* - DATE
* - ORIGINALDATE
* - GENRE
* - COMMENT
*
* Sort names:
*
* - TITLESORT
* - ALBUMSORT
* - ARTISTSORT
* - ALBUMARTISTSORT
*
* Credits:
*
* - COMPOSER
* - LYRICIST
* - CONDUCTOR
* - REMIXER
* - PERFORMER:<XXXX>
*
* Other tags:
*
* - ISRC
* - ASIN
* - BPM
* - COPYRIGHT
* - ENCODEDBY
* - MOOD
* - COMMENT
* - MEDIA
* - LABEL
* - CATALOGNUMBER
* - BARCODE
*
* MusicBrainz identifiers:
*
* - MUSICBRAINZ_TRACKID
* - MUSICBRAINZ_ALBUMID
* - MUSICBRAINZ_RELEASEGROUPID
* - MUSICBRAINZ_WORKID
* - MUSICBRAINZ_ARTISTID
* - MUSICBRAINZ_ALBUMARTISTID
* - ACOUSTID_ID
* - ACOUSTID_FINGERPRINT
* - MUSICIP_PUID
*
*/
class TAGLIB_EXPORT PropertyMap : public SimplePropertyMap {
public:
@@ -114,112 +110,105 @@ class TAGLIB_EXPORT PropertyMap : public SimplePropertyMap {
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.
*/
* 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);
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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* Find the first occurrence of \a key.
*/
* Find the first occurrence of \a key.
*/
Iterator find(const String &key);
/*!
* Find the first occurrence of \a key.
*/
* Find the first occurrence of \a key.
*/
ConstIterator find(const String &key) const;
/*!
* Returns true if the map contains values for \a key.
*/
* Returns true if the map contains values for \a key.
*/
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.
*/
* 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;
/*!
* Erase the \a key and its values from the map.
*/
* Erase the \a key and its values from the map.
*/
PropertyMap &erase(const String &key);
/*!
* Erases from this map all keys that appear in \a other.
*/
* Erases from this map all keys that appear in \a 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.
*/
* 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);
/*!
* 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.
*/
* 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;
/*!
* 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.
*/
* 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);
/*!
* Returns true if and only if \other has the same contents as this map.
*/
* Returns true if and only if \other has the same contents as this map.
*/
bool operator==(const PropertyMap &other) const;
/*!
* Returns false if and only \other has the same contents as this map.
*/
* Returns false if and only \other has the same contents as this map.
*/
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
* be e.g. binary data, unknown ID3 frames, etc.
* You can remove items from the returned list, which tells TagLib to remove
* those unsupported elements if you call File::setProperties() with the
* same PropertyMap as argument.
*/
* 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 be e.g. binary data, unknown ID3 frames, etc.
* You can remove items from the returned list, which tells TagLib to remove
* those unsupported elements if you call File::setProperties() with the
* same PropertyMap as argument.
*/
StringList &unsupportedData();
const StringList &unsupportedData() const;
/*!
* Removes all entries which have an empty value list.
*/
* Removes all entries which have an empty value list.
*/
void removeEmpty();
String toString() const;

View File

@@ -72,8 +72,7 @@ class RefCounter::RefCounterPrivate {
volatile ATOMIC_INT refCount;
};
RefCounter::RefCounter() : d(new RefCounterPrivate()) {
}
RefCounter::RefCounter() : d(new RefCounterPrivate()) {}
RefCounter::~RefCounter() {
delete d;

View File

@@ -40,34 +40,41 @@ 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;
}
// 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]);
}
// 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) {
}
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.
@@ -81,6 +88,7 @@ unsigned short nextUTF16<wchar_t>(const wchar_t **p) {
template<>
unsigned short nextUTF16<char>(const char **p) {
union {
unsigned short w;
char c[2];
@@ -88,12 +96,14 @@ unsigned short nextUTF16<char>(const char **p) {
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) {
@@ -125,7 +135,9 @@ void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t
else
data[i] = c;
}
}
} // namespace
namespace Strawberry_TagLib {
@@ -160,16 +172,19 @@ String::String(const String &s) : d(s.d) {
}
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)
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) {
// This looks ugly but needed for the compatibility with TagLib1.8.
// Should be removed in TabLib2.0.
@@ -183,9 +198,11 @@ String::String(const wstring &s, Type t) : d(new StringPrivate()) {
else {
debug("String::String() -- TagLib::wstring should not contain Latin1 or UTF-8.");
}
}
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.
@@ -199,9 +216,11 @@ String::String(const wchar_t *s, Type t) : d(new StringPrivate()) {
else {
debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8.");
}
}
String::String(const char *s, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, s, ::strlen(s));
else if (t == String::UTF8)
@@ -209,17 +228,21 @@ String::String(const char *s, Type t) : d(new StringPrivate()) {
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)
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)
copyFromLatin1(d->data, &c, 1);
else if (t == String::UTF8)
@@ -227,9 +250,11 @@ String::String(char c, Type t) : d(new StringPrivate()) {
else {
debug("String::String() -- char should not contain UTF16.");
}
}
String::String(const ByteVector &v, Type t) : d(new StringPrivate()) {
if (v.isEmpty())
return;
@@ -242,6 +267,7 @@ String::String(const ByteVector &v, Type t) : d(new StringPrivate()) {
// If we hit a null in the ByteVector, shrink the string again.
d->data.resize(::wcslen(d->data.c_str()));
}
////////////////////////////////////////////////////////////////////////////////
@@ -252,8 +278,10 @@ String::~String() {
}
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 {
@@ -296,6 +324,7 @@ int String::rfind(const String &s, int offset) const {
}
StringList String::split(const String &separator) const {
StringList list;
for (int index = 0;;) {
int sep = find(separator, index);
@@ -309,6 +338,7 @@ StringList String::split(const String &separator) const {
}
}
return list;
}
bool String::startsWith(const String &s) const {
@@ -319,24 +349,31 @@ bool String::startsWith(const String &s) const {
}
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) {
detach();
d->data += s.d->data;
return *this;
}
String &String::clear() {
*this = String();
return *this;
}
String String::upper() const {
String s;
s.d->data.reserve(size());
@@ -348,6 +385,7 @@ String String::upper() const {
}
return s;
}
unsigned int String::size() const {
@@ -367,6 +405,7 @@ bool String::isNull() const {
}
ByteVector String::data(Type t) const {
switch (t) {
case Latin1: {
ByteVector v(size(), 0);
@@ -434,13 +473,15 @@ ByteVector String::data(Type t) const {
return ByteVector();
}
}
}
int String::toInt() const {
return toInt(0);
return toInt(nullptr);
}
int String::toInt(bool *ok) const {
const wchar_t *begin = d->data.c_str();
wchar_t *end;
errno = 0;
@@ -453,9 +494,11 @@ int String::toInt(bool *ok) const {
}
return static_cast<int>(value);
}
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);
@@ -464,26 +507,30 @@ String String::stripWhiteSpace() const {
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)
return false;
}
return true;
}
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);
}
@@ -505,6 +552,7 @@ bool String::operator!=(const String &s) const {
}
bool String::operator==(const char *s) const {
const wchar_t *p = toCWString();
while (*p != L'\0' || *s != '\0') {
@@ -512,6 +560,7 @@ bool String::operator==(const char *s) const {
return false;
}
return true;
}
bool String::operator!=(const char *s) const {
@@ -621,11 +670,6 @@ void String::detach() {
String(d->data.c_str()).swap(*this);
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
const String::Type String::WCharByteOrder = wcharByteOrder();
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -68,15 +68,13 @@ class StringList;
//! 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/
* CPU byte order)
* 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/ CPU byte order)
*
* The use of implicit sharing means that copying a string is cheap, the only
* \e cost comes into play when the copy is modified. Prior to that the string
* just has a pointer to the data of the \e parent String. This also makes
* this class suitable as a function return type.
* The use of implicit sharing means that copying a string is cheap, the only \e cost comes into play when the copy is modified.
* Prior to that the string just has a pointer to the data of the \e parent String.
* This also makes this class suitable as a function return type.
*
* In addition to adding implicit sharing, this class keeps track of four
* possible encodings, which are the four supported by the ID3v2 standard.
@@ -90,458 +88,416 @@ class TAGLIB_EXPORT String {
#endif
/**
* The four types of string encodings supported by the ID3v2 specification.
* ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8.
*/
* 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 {
/*!
* IS08859-1, or <i>Latin1</i> encoding. 8 bit characters.
*/
* IS08859-1, or <i>Latin1</i> encoding. 8 bit characters.
*/
Latin1 = 0,
/*!
* UTF16 with a <i>byte order mark</i>. 16 bit characters.
*/
* UTF16 with a <i>byte order mark</i>. 16 bit characters.
*/
UTF16 = 1,
/*!
* UTF16 <i>big endian</i>. 16 bit characters. This is the encoding used
* internally by TagLib.
*/
* UTF16 <i>big endian</i>. 16 bit characters. This is the encoding used internally by TagLib.
*/
UTF16BE = 2,
/*!
* UTF8 encoding. Characters are usually 8 bits but can be up to 32.
*/
* UTF8 encoding. Characters are usually 8 bits but can be up to 32.
*/
UTF8 = 3,
/*!
* UTF16 <i>little endian</i>. 16 bit characters.
*/
* UTF16 <i>little endian</i>. 16 bit characters.
*/
UTF16LE = 4
};
/*!
* Constructs an empty String.
*/
* Constructs an empty 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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* 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.
*/
* 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);
/*!
* Makes a deep copy of the data in \a c.
*/
* Makes a deep copy of the data in \a c.
*/
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.
*/
* 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);
/*!
* Makes a deep copy of the data in \a v.
*/
* Makes a deep copy of the data in \a v.
*/
String(const ByteVector &v, Type t = Latin1);
/*!
* Destroys this String instance.
*/
* Destroys this String instance.
*/
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()
*/
* 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;
/*!
* 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()
*/
* 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;
/*!
* 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.
*
* The returned string is still owned by this String and should not be deleted
* by the user.
*
* The returned pointer remains valid until this String instance is destroyed
* or toCString() is called again.
*
* \warning This however has the side effect that the returned string will remain
* in memory <b>in addition to</b> other memory that is consumed by this
* String instance. So, this method should not be used on large strings or
* where memory is critical. Consider using to8Bit() instead to avoid it.
*
* \see to8Bit()
*/
* 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.
*
* The returned string is still owned by this String and should not be deleted by the user.
*
* The returned pointer remains valid until this String instance is destroyed or toCString() is called again.
*
* \warning This however has the side effect that the returned string will remain
* in memory <b>in addition to</b> other memory that is consumed by this String instance.
* So, this method should not be used on large strings or where memory is critical. Consider using to8Bit() instead to avoid it.
*
* \see to8Bit()
*/
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.
*
* The returned string is still owned by this String and should not be deleted
* by the user.
*
* The returned pointer remains valid until this String instance is destroyed
* or any other method of this String is called.
*
* \note This returns a pointer to the String's internal data without any
* conversions.
*
* \see toWString()
*/
* 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.
*
* The returned string is still owned by this String and should not be deleted by the user.
*
* The returned pointer remains valid until this String instance is destroyed or any other method of this String is called.
*
* \note This returns a pointer to the String's internal data without any conversions.
*
* \see toWString()
*/
const wchar_t *toCWString() const;
/*!
* Returns an iterator pointing to the beginning of the string.
*/
* Returns an iterator pointing to the beginning of the string.
*/
Iterator begin();
/*!
* Returns a const iterator pointing to the beginning of the string.
*/
* Returns a const iterator pointing to the beginning of the string.
*/
ConstIterator begin() const;
/*!
* Returns an iterator pointing to the end of the string (the position
* after the last character).
*/
* Returns an iterator pointing to the end of the string (the position after the last character).
*/
Iterator end();
/*!
* Returns a const iterator pointing to the end of the string (the position
* after the last character).
*/
* Returns a const iterator pointing to the end of the string (the position after the last character).
*/
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.
*/
* 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;
/*!
* 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.
*/
* 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;
/*!
* Splits the string on each occurrence of \a separator.
*/
* Splits the string on each occurrence of \a separator.
*/
StringList split(const String &separator = " ") const;
/*!
* Returns true if the strings starts with the substring \a s.
*/
* Returns true if the strings starts with the substring \a s.
*/
bool startsWith(const String &s) const;
/*!
* Extract a substring from this string starting at \a position and
* continuing for \a n characters.
*/
* 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;
/*!
* Append \a s to the current string and return a reference to the current
* string.
*/
* Append \a s to the current string and return a reference to the current string.
*/
String &append(const String &s);
/*!
* Clears the string.
*/
* Clears the string.
*/
String &clear();
/*!
* Returns an upper case version of the string.
*
* \warning This only works for the characters in US-ASCII, i.e. A-Z.
*/
* 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;
/*!
* Returns the size of the string.
*/
* Returns the size of the string.
*/
unsigned int size() const;
/*!
* Returns the length of the string. Equivalent to size().
*/
* Returns the length of the string. Equivalent to size().
*/
unsigned int length() const;
/*!
* Returns true if the string is empty.
*
* \see isNull()
*/
* Returns true if the string is empty.
*
* \see isNull()
*/
bool isEmpty() const;
/*!
* Returns true if this string is null -- i.e. it is a copy of the
* String::null string.
*
* \note A string can be empty and not null. So do not use this method to
* check if the string is empty.
*
* \see isEmpty()
*
* \deprecated
*/
* Returns true if this string is null -- i.e. it is a copy of the String::null string.
*
* \note A string can be empty and not null. So do not use this method to check if the string is empty.
*
* \see isEmpty()
*
* \deprecated
*/
// 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.
*
* \note If \a t is UTF16, the returned data is encoded in little-endian
* format and has a BOM.
*
* \note The returned data is not null terminated.
*/
* 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.
*
* \note If \a t is UTF16, the returned data is encoded in little-endian format and has a BOM.
*
* \note The returned data is not null terminated.
*/
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.
*/
* 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;
/*!
* 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.
*/
* 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;
/*!
* Returns a string with the leading and trailing whitespace stripped.
*/
* Returns a string with the leading and trailing whitespace stripped.
*/
String stripWhiteSpace() const;
/*!
* Returns true if the file only uses characters required by Latin1.
*/
* Returns true if the file only uses characters required by Latin1.
*/
bool isLatin1() const;
/*!
* Returns true if the file only uses characters required by (7-bit) ASCII.
*/
* Returns true if the file only uses characters required by (7-bit) ASCII.
*/
bool isAscii() const;
/*!
* Converts the base-10 integer \a n to a string.
*/
* Converts the base-10 integer \a n to a string.
*/
static String number(int n);
/*!
* Returns a reference to the character at position \a i.
*/
* Returns a reference to the character at position \a i.
*/
wchar_t &operator[](int i);
/*!
* Returns a const reference to the character at position \a i.
*/
* Returns a const reference to the character at position \a i.
*/
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.
*/
* 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;
/*!
* Compares each character of the String with each character of \a s and
* returns false if the strings match.
*/
* 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;
/*!
* Compares each character of the String with each character of \a s and
* returns true if the strings match.
*/
* 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;
/*!
* Compares each character of the String with each character of \a s and
* returns false if the strings match.
*/
* 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;
/*!
* Compares each character of the String with each character of \a s and
* returns true if the strings match.
*/
* 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;
/*!
* Compares each character of the String with each character of \a s and
* returns false if the strings match.
*/
* 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;
/*!
* Appends \a s to the end of the String.
*/
* Appends \a s to the end of the String.
*/
String &operator+=(const String &s);
/*!
* Appends \a s to the end of the String.
*/
* Appends \a s to the end of the String.
*/
String &operator+=(const wchar_t *s);
/*!
* Appends \a s to the end of the String.
*/
* Appends \a s to the end of the String.
*/
String &operator+=(const char *s);
/*!
* Appends \a s to the end of the String.
*/
* Appends \a s to the end of the String.
*/
String &operator+=(wchar_t c);
/*!
* Appends \a c to the end of the String.
*/
* Appends \a c to the end of the String.
*/
String &operator+=(char c);
/*!
* Performs a shallow, implicitly shared, copy of \a s, overwriting the
* String's current data.
*/
* Performs a shallow, implicitly shared, copy of \a s, overwriting the String's current data.
*/
String &operator=(const String &s);
/*!
* Performs a deep copy of the data in \a s.
*/
* Performs a deep copy of the data in \a s.
*/
String &operator=(const std::string &s);
/*!
* Performs a deep copy of the data in \a s.
*/
* Performs a deep copy of the data in \a s.
*/
String &operator=(const wstring &s);
/*!
* Performs a deep copy of the data in \a s.
*/
* Performs a deep copy of the data in \a s.
*/
String &operator=(const wchar_t *s);
/*!
* Performs a deep copy of the data in \a s.
*/
* Performs a deep copy of the data in \a s.
*/
String &operator=(char c);
/*!
* Performs a deep copy of the data in \a s.
*/
* Performs a deep copy of the data in \a s.
*/
String &operator=(wchar_t c);
/*!
* Performs a deep copy of the data in \a s.
*/
* Performs a deep copy of the data in \a s.
*/
String &operator=(const char *s);
/*!
* Performs a deep copy of the data in \a v.
*/
* Performs a deep copy of the data in \a v.
*/
String &operator=(const ByteVector &v);
/*!
* Exchanges the content of the String by the content of \a s.
*/
* Exchanges the content of the String by the content of \a 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.
*/
* 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;
/*!
* A null string provided for convenience.
*
* \warning Do not modify this variable. It will mess up the internal state
* of TagLib.
*
* \deprecated
*/
* A null string provided for convenience.
*
* \warning Do not modify this variable. It will mess up the internal state of TagLib.
*
* \deprecated
*/
// BIC: remove
static String null;
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.
*/
* 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();
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;
class StringPrivate;
StringPrivate *d;
};

View File

@@ -35,6 +35,7 @@ class StringListPrivate {
////////////////////////////////////////////////////////////////////////////////
StringList StringList::split(const String &s, const String &pattern) {
StringList l;
int previousOffset = 0;
@@ -46,32 +47,32 @@ StringList StringList::split(const String &s, const String &pattern) {
l.append(s.substr(previousOffset, s.size() - previousOffset));
return l;
}
////////////////////////////////////////////////////////////////////////////////
// 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>() {
ByteVectorList::ConstIterator i = bl.begin();
for (; i != bl.end(); i++) {
append(String(*i, t));
}
}
StringList::~StringList() {
}
StringList::~StringList() {}
String StringList::toString(const String &separator) const {
String s;
ConstIterator it = begin();
@@ -85,16 +86,21 @@ String StringList::toString(const String &separator) const {
}
return s;
}
StringList &StringList::append(const String &s) {
List<String>::append(s);
return *this;
}
StringList &StringList::append(const StringList &l) {
List<String>::append(l);
return *this;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -39,63 +39,59 @@ namespace TagLib {
//! A list of strings
/*!
* This is a specialization of the List class with some members convention for
* string operations.
* This is a specialization of the List class with some members convention for string operations.
*/
class TAGLIB_EXPORT StringList : public List<String> {
public:
/*!
* Constructs an empty StringList.
*/
* Constructs an empty 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.
*/
* 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;
/*!
* Constructs a StringList with \a s as a member.
*/
* Constructs a StringList with \a s as a member.
*/
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.
*/
* 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);
/*!
* Destroys this StringList instance.
*/
* Destroys this StringList instance.
*/
virtual ~StringList();
/*!
* Concatenate the list of strings into one string separated by \a separator.
*/
* Concatenate the list of strings into one string separated by \a separator.
*/
String toString(const String &separator = " ") const;
/*!
* Appends \a s to the end of the list and returns a reference to the
* list.
*/
* Appends \a s to the end of the list and returns a reference to the list.
*/
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.
*/
* 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);
/*!
* Splits the String \a s into several strings at \a pattern. This will not include
* the pattern in the returned strings.
*/
* Splits the String \a s into several strings at \a pattern.
* This will not include the pattern in the returned strings.
*/
static StringList split(const String &s, const String &pattern);
private:

View File

@@ -55,8 +55,8 @@ namespace Utils {
namespace {
/*!
* Reverses the order of bytes in an 16-bit integer.
*/
* Reverses the order of bytes in an 16-bit integer.
*/
inline unsigned short byteSwap(unsigned short x) {
# if defined(HAVE_GCC_BYTESWAP)
@@ -86,8 +86,8 @@ inline unsigned short byteSwap(unsigned short x) {
}
/*!
* Reverses the order of bytes in an 32-bit integer.
*/
* Reverses the order of bytes in an 32-bit integer.
*/
inline unsigned int byteSwap(unsigned int x) {
# if defined(HAVE_GCC_BYTESWAP)
@@ -117,8 +117,8 @@ inline unsigned int byteSwap(unsigned int x) {
}
/*!
* Reverses the order of bytes in an 64-bit integer.
*/
* Reverses the order of bytes in an 64-bit integer.
*/
inline unsigned long long byteSwap(unsigned long long x) {
# if defined(HAVE_GCC_BYTESWAP)
@@ -148,9 +148,8 @@ inline unsigned long long byteSwap(unsigned long long x) {
}
/*!
* Returns a formatted string just like standard sprintf(), but makes use of
* safer functions such as snprintf() if available.
*/
* 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.
@@ -192,8 +191,8 @@ inline String formatString(const char *format, ...) {
}
/*!
* The types of byte order of the running system.
*/
* The types of byte order of the running system.
*/
enum ByteOrder {
//! Little endian systems.
LittleEndian,
@@ -202,8 +201,8 @@ enum ByteOrder {
};
/*!
* Returns the byte order of the system.
*/
* Returns the byte order of the system.
*/
inline ByteOrder systemByteOrder() {
union {
int i;

View File

@@ -38,8 +38,8 @@ namespace TagLib {
namespace zlib {
/*!
* Returns whether or not zlib is installed and ready to use.
*/
* Returns whether or not zlib is installed and ready to use.
*/
bool isAvailable();
/*!