Adapt most changes from taglib2

This commit is contained in:
Jonas Kvinge
2020-06-26 23:30:30 +02:00
parent 08882639e0
commit 5f71a558b9
374 changed files with 13708 additions and 4418 deletions

49
3rdparty/taglib/toolkit/taglib.cpp vendored Normal file
View File

@@ -0,0 +1,49 @@
/***************************************************************************
copyright : (C) 2016 by Michael Helmling
email : helmling@mathematik.uni-kl.de
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "taglib.h"
#include "tstring.h"
using namespace Strawberry_TagLib::TagLib;
String Strawberry_TagLib::TagLib::Version::string() {
return String::number(TAGLIB_MAJOR_VERSION) + "." + String::number(TAGLIB_MINOR_VERSION) + "." + String::number(TAGLIB_PATCH_VERSION);
}
unsigned int Strawberry_TagLib::TagLib::Version::combined() {
return (TAGLIB_MAJOR_VERSION << 16) | (TAGLIB_MINOR_VERSION << 8) | (TAGLIB_PATCH_VERSION << 4);
}
unsigned int(Strawberry_TagLib::TagLib::Version::major)() {
return TAGLIB_MAJOR_VERSION;
}
unsigned int(Strawberry_TagLib::TagLib::Version::minor)() {
return TAGLIB_MINOR_VERSION;
}
unsigned int Strawberry_TagLib::TagLib::Version::patch() {
return TAGLIB_PATCH_VERSION;
}

View File

@@ -30,30 +30,12 @@
#define TAGLIB_MINOR_VERSION 11
#define TAGLIB_PATCH_VERSION 1
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__)
# define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
#else
# define TAGLIB_IGNORE_MISSING_DESTRUCTOR
#endif
#if (defined(_MSC_VER) && _MSC_VER >= 1600)
# define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long long>(x)
#else
# define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long>(x)
#endif
#if __cplusplus >= 201402
# define TAGLIB_DEPRECATED [[deprecated]]
#elif defined(__GNUC__) || defined(__clang__)
# define TAGLIB_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
# define TAGLIB_DEPRECATED __declspec(deprecated)
#else
# define TAGLIB_DEPRECATED
#endif
#include <string>
//! A namespace for all TagLib related classes and functions
/*!
@@ -67,22 +49,43 @@
namespace Strawberry_TagLib {
namespace TagLib {
enum ByteOrder {
LittleEndian,
BigEndian
};
class String;
// These integer types are deprecated. Do not use them.
typedef wchar_t wchar; // Assumed to be sufficient to store a UTF-16 char.
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ulonglong;
namespace Version {
/*!
* Returns the version as a string in the form
* (Major Version).(Minor Version).(Patch Version), e.g. "4.2.0".
*/
String string();
/*!
* Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3)
* so I'm providing something here that should be constant.
*/
typedef std::basic_string<wchar_t> wstring;
* Returns the version as an unsigned integer in the form
* (Major Version << 16) | (Minor Version << 8) | (Patch Version), e.g. 0x040200
* Use this for simple and consistent version comparison, e.g.
* if (TagLib::GetVersion() <= ((1 << 16) | (11 << 8))) return false;
*/
unsigned int combined();
/*!
* Returns the major version, e.g. 4
*/
unsigned int(major)();
/*!
* Returns the minor version, e.g. 2
*/
unsigned int(minor)();
/*!
* Returns the patch version, e.g. 0
*/
unsigned int patch();
} // namespace Version
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -23,6 +23,7 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <memory>
#include <algorithm>
#include <iostream>
#include <limits>
@@ -30,10 +31,9 @@
#include <cstdio>
#include <cstring>
#include <tstring.h>
#include <tdebug.h>
#include <trefcounter.h>
#include <tutils.h>
#include "tstring.h"
#include "tdebug.h"
#include "tutils.h"
#include "tbytevector.h"
@@ -47,33 +47,33 @@ namespace Strawberry_TagLib {
namespace TagLib {
template<class TIterator>
int findChar(const TIterator dataBegin, const TIterator dataEnd, char c, unsigned int offset, int byteAlign) {
size_t findChar(const TIterator dataBegin, const TIterator dataEnd, char c, size_t offset, size_t byteAlign) {
const size_t dataSize = dataEnd - dataBegin;
if (offset + 1 > dataSize)
return -1;
return ByteVector::npos();
// n % 0 is invalid
if (byteAlign == 0)
return -1;
return ByteVector::npos();
for (TIterator it = dataBegin + offset; it < dataEnd; it += byteAlign) {
if (*it == c)
return static_cast<int>(it - dataBegin);
return (it - dataBegin);
}
return -1;
return ByteVector::npos();
}
template<class TIterator>
int findVector(const TIterator dataBegin, const TIterator dataEnd, const TIterator patternBegin, const TIterator patternEnd, unsigned int offset, int byteAlign) {
size_t findVector(const TIterator dataBegin, const TIterator dataEnd, const TIterator patternBegin, const TIterator patternEnd, size_t offset, size_t byteAlign) {
const size_t dataSize = dataEnd - dataBegin;
const size_t patternSize = patternEnd - patternBegin;
if (patternSize == 0 || offset + patternSize > dataSize)
return -1;
return ByteVector::npos();
// Special case that pattern contains just single char.
@@ -83,7 +83,7 @@ int findVector(const TIterator dataBegin, const TIterator dataEnd, const TIterat
// n % 0 is invalid
if (byteAlign == 0)
return -1;
return ByteVector::npos();
// We don't use sophisticated algorithms like Knuth-Morris-Pratt here.
@@ -100,68 +100,53 @@ int findVector(const TIterator dataBegin, const TIterator dataEnd, const TIterat
++itPattern;
if (itPattern == patternEnd)
return static_cast<int>(it - dataBegin);
return (it - dataBegin);
}
}
return -1;
return ByteVector::npos();
}
template<class T>
T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignificantByteFirst) {
template<typename T, size_t LENGTH, ByteOrder ENDIAN>
inline T toNumber(const ByteVector &v, size_t offset) {
if (LENGTH == sizeof(T) && offset + LENGTH <= v.size()) {
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
T tmp;
::memcpy(&tmp, v.data() + offset, sizeof(T));
if (offset >= v.size()) {
debug("toNumber<T>() -- No data to convert. Returning 0.");
if (ENDIAN != Utils::systemByteOrder())
return Utils::byteSwap(tmp);
else
return tmp;
}
else if (offset < v.size()) {
const size_t length = std::min(LENGTH, v.size() - offset);
T sum = 0;
for (size_t i = 0; i < length; ++i) {
const size_t shift = (ENDIAN == BigEndian ? length - 1 - i : i) * 8;
sum |= static_cast<T>(static_cast<unsigned char>(v[offset + i])) << shift;
}
return sum;
}
else {
debug("toNumber<T>() - offset is out of range. Returning 0.");
return 0;
}
length = std::min(length, v.size() - offset);
T sum = 0;
for (size_t i = 0; i < length; i++) {
const size_t shift = (mostSignificantByteFirst ? length - 1 - i : i) * 8;
sum |= static_cast<T>(static_cast<unsigned char>(v[static_cast<int>(offset + i)])) << shift;
}
return sum;
}
template<class T>
T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst) {
template<typename T, ByteOrder ENDIAN>
inline ByteVector fromNumber(T value) {
const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian);
const bool swap = (mostSignificantByteFirst != isBigEndian);
if (offset + sizeof(T) > v.size())
return toNumber<T>(v, offset, v.size() - offset, mostSignificantByteFirst);
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
T tmp;
::memcpy(&tmp, v.data() + offset, sizeof(T));
if (swap)
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);
if (swap)
if (ENDIAN != Utils::systemByteOrder())
value = Utils::byteSwap(value);
return ByteVector(reinterpret_cast<const char *>(&value), sizeof(T));
}
template<typename TFloat, typename TInt, Utils::ByteOrder ENDIAN>
template<typename TFloat, typename TInt, ByteOrder ENDIAN>
TFloat toFloat(const ByteVector &v, size_t offset) {
if (offset > v.size() - sizeof(TInt)) {
@@ -182,7 +167,7 @@ TFloat toFloat(const ByteVector &v, size_t offset) {
}
template<typename TFloat, typename TInt, Utils::ByteOrder ENDIAN>
template<typename TFloat, typename TInt, ByteOrder ENDIAN>
ByteVector fromFloat(TFloat value) {
union {
@@ -198,7 +183,7 @@ ByteVector fromFloat(TFloat value) {
}
template<Utils::ByteOrder ENDIAN>
template<ByteOrder ENDIAN>
long double toFloat80(const ByteVector &v, size_t offset) {
using std::swap;
@@ -211,7 +196,7 @@ long double toFloat80(const ByteVector &v, size_t offset) {
unsigned char bytes[10];
::memcpy(bytes, v.data() + offset, 10);
if (ENDIAN == Utils::LittleEndian) {
if (ENDIAN == LittleEndian) {
swap(bytes[0], bytes[9]);
swap(bytes[1], bytes[8]);
swap(bytes[2], bytes[7]);
@@ -249,105 +234,105 @@ long double toFloat80(const ByteVector &v, size_t offset) {
class ByteVector::ByteVectorPrivate {
public:
ByteVectorPrivate(unsigned int l, char c) : counter(new RefCounter()),
data(new std::vector<char>(l, c)),
offset(0),
length(l) {}
ByteVectorPrivate() : data(new std::vector<char>()),
offset(0),
length(0) {}
ByteVectorPrivate(const char *s, unsigned int l) : counter(new RefCounter()),
data(new std::vector<char>(s, s + l)),
offset(0),
length(l) {}
ByteVectorPrivate(ByteVectorPrivate *d, size_t o, size_t l) : data(d->data),
offset(d->offset + o),
length(l) {}
ByteVectorPrivate(const ByteVectorPrivate &d, unsigned int o, unsigned int l) : counter(d.counter),
data(d.data),
offset(d.offset + o),
length(l) {
counter->ref();
}
ByteVectorPrivate(size_t l, char c) : data(new std::vector<char>(l, c)),
offset(0),
length(l) {}
~ByteVectorPrivate() {
if (counter->deref()) {
delete counter;
delete data;
}
}
ByteVectorPrivate(const char *s, size_t l) : data(new std::vector<char>(s, s + l)),
offset(0),
length(l) {}
RefCounter *counter;
std::vector<char> *data;
unsigned int offset;
unsigned int length;
std::shared_ptr<std::vector<char>> data;
size_t offset;
size_t length;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
ByteVector ByteVector::fromCString(const char *s, unsigned int length) {
if (length == 0xffffffff)
return ByteVector(s, static_cast<unsigned int>(::strlen(s)));
size_t ByteVector::npos() {
return static_cast<size_t>(-1);
}
ByteVector ByteVector::fromCString(const char *s, size_t length) {
if (length == npos())
return ByteVector(s);
else
return ByteVector(s, length);
}
ByteVector ByteVector::fromUInt(unsigned int value, bool mostSignificantByteFirst) {
return fromNumber<unsigned int>(value, mostSignificantByteFirst);
ByteVector ByteVector::fromUInt16LE(size_t value) {
return fromNumber<unsigned short, LittleEndian>(static_cast<unsigned short>(value));
}
ByteVector ByteVector::fromShort(short value, bool mostSignificantByteFirst) {
return fromNumber<unsigned short>(value, mostSignificantByteFirst);
ByteVector ByteVector::fromUInt16BE(size_t value) {
return fromNumber<unsigned short, BigEndian>(static_cast<unsigned short>(value));
}
ByteVector ByteVector::fromLongLong(long long value, bool mostSignificantByteFirst) {
return fromNumber<unsigned long long>(value, mostSignificantByteFirst);
ByteVector ByteVector::fromUInt32LE(size_t value) {
return fromNumber<unsigned int, LittleEndian>(static_cast<unsigned int>(value));
}
ByteVector ByteVector::fromUInt32BE(size_t value) {
return fromNumber<unsigned int, BigEndian>(static_cast<unsigned int>(value));
}
ByteVector ByteVector::fromUInt64LE(unsigned long long value) {
return fromNumber<unsigned long long, LittleEndian>(value);
}
ByteVector ByteVector::fromUInt64BE(unsigned long long value) {
return fromNumber<unsigned long long, BigEndian>(value);
}
ByteVector ByteVector::fromFloat32LE(float value) {
return fromFloat<float, unsigned int, Utils::LittleEndian>(value);
return fromFloat<float, unsigned int, LittleEndian>(value);
}
ByteVector ByteVector::fromFloat32BE(float value) {
return fromFloat<float, unsigned int, Utils::BigEndian>(value);
return fromFloat<float, unsigned int, BigEndian>(value);
}
ByteVector ByteVector::fromFloat64LE(double value) {
return fromFloat<double, unsigned long long, Utils::LittleEndian>(value);
return fromFloat<double, unsigned long long, LittleEndian>(value);
}
ByteVector ByteVector::fromFloat64BE(double value) {
return fromFloat<double, unsigned long long, Utils::BigEndian>(value);
return fromFloat<double, unsigned long long, BigEndian>(value);
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
ByteVector::ByteVector() : d(new ByteVectorPrivate(0, '\0')) {
}
ByteVector::ByteVector() : d(new ByteVectorPrivate()) {}
ByteVector::ByteVector(unsigned int size, char value) : d(new ByteVectorPrivate(size, value)) {
}
ByteVector::ByteVector(size_t size, char value) : d(new ByteVectorPrivate(size, value)) {}
ByteVector::ByteVector(const ByteVector &v) : d(new ByteVectorPrivate(*v.d, 0, v.d->length)) {
}
ByteVector::ByteVector(const ByteVector &v) : d(new ByteVectorPrivate(*v.d)) {}
ByteVector::ByteVector(const ByteVector &v, unsigned int offset, unsigned int length) : d(new ByteVectorPrivate(*v.d, offset, length)) {
}
ByteVector::ByteVector(const ByteVector &v, size_t offset, size_t length) : d(new ByteVectorPrivate(v.d, offset, length)) {}
ByteVector::ByteVector(char c) : d(new ByteVectorPrivate(1, c)) {
}
ByteVector::ByteVector(char c) : d(new ByteVectorPrivate(1, c)) {}
ByteVector::ByteVector(const char *data, unsigned int length) : d(new ByteVectorPrivate(data, length)) {
}
ByteVector::ByteVector(const char *data, size_t length) : d(new ByteVectorPrivate(data, length)) {}
ByteVector::ByteVector(const char *data) : d(new ByteVectorPrivate(data, static_cast<unsigned int>(::strlen(data)))) {
}
ByteVector::ByteVector(const char *data) : d(new ByteVectorPrivate(data, ::strlen(data))) {}
ByteVector::~ByteVector() {
delete d;
}
ByteVector &ByteVector::setData(const char *data, unsigned int length) {
ByteVector &ByteVector::setData(const char *data, size_t length) {
ByteVector(data, length).swap(*this);
return *this;
}
@@ -366,7 +351,7 @@ const char *ByteVector::data() const {
return (size() > 0) ? (&(*d->data)[d->offset]) : nullptr;
}
ByteVector ByteVector::mid(unsigned int index, unsigned int length) const {
ByteVector ByteVector::mid(size_t index, size_t length) const {
index = std::min(index, size());
length = std::min(length, size() - index);
@@ -375,44 +360,43 @@ ByteVector ByteVector::mid(unsigned int index, unsigned int length) const {
}
char ByteVector::at(unsigned int index) const {
char ByteVector::at(size_t index) const {
return (index < size()) ? (*d->data)[d->offset + index] : 0;
}
int ByteVector::find(const ByteVector &pattern, unsigned int offset, int byteAlign) const {
size_t ByteVector::find(const ByteVector &pattern, size_t offset, size_t byteAlign) const {
return findVector<ConstIterator>(
begin(), end(), pattern.begin(), pattern.end(), offset, byteAlign);
}
int ByteVector::find(char c, unsigned int offset, int byteAlign) const {
size_t ByteVector::find(char c, size_t offset, size_t byteAlign) const {
return findChar<ConstIterator>(begin(), end(), c, offset, byteAlign);
}
int ByteVector::rfind(const ByteVector &pattern, unsigned int offset, int byteAlign) const {
size_t ByteVector::rfind(const ByteVector &pattern, size_t offset, size_t byteAlign) const {
if (offset > 0) {
offset = size() - offset - pattern.size();
if (offset >= size())
offset = 0;
}
const int pos = findVector<ConstReverseIterator>(
const size_t pos = findVector<ConstReverseIterator>(
rbegin(), rend(), pattern.rbegin(), pattern.rend(), offset, byteAlign);
if (pos == -1)
return -1;
if (pos == npos())
return npos();
else
return size() - pos - pattern.size();
}
bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset, unsigned int patternLength) const {
bool ByteVector::containsAt(const ByteVector &pattern, size_t offset, size_t patternOffset, size_t patternLength) const {
if (pattern.size() < patternLength)
patternLength = pattern.size();
// do some sanity checking -- all of these things are needed for the search to be valid
const unsigned int compareLength = patternLength - patternOffset;
const size_t compareLength = patternLength - patternOffset;
if (offset + compareLength > size() || patternOffset >= pattern.size() || patternLength == 0)
return false;
@@ -448,8 +432,8 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
// Check if there is at least one occurrence of the pattern.
int offset = find(pattern, 0);
if (offset == -1)
size_t offset = find(pattern, 0);
if (offset == ByteVector::npos())
return *this;
if (pattern.size() == with.size()) {
@@ -460,27 +444,27 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
do {
::memcpy(data() + offset, with.data(), with.size());
offset = find(pattern, offset + pattern.size());
} while (offset != -1);
} while (offset != ByteVector::npos());
}
else {
// Loop once to calculate the result size.
unsigned int dstSize = size();
size_t dstSize = size();
do {
dstSize += with.size() - pattern.size();
offset = find(pattern, offset + pattern.size());
} while (offset != -1);
} while (offset != ByteVector::npos());
// Loop again to copy modified data to the new vector.
ByteVector dst(dstSize);
int dstOffset = 0;
size_t dstOffset = 0;
offset = 0;
while (true) {
const int next = find(pattern, offset);
if (next == -1) {
const size_t next = find(pattern, offset);
if (next == ByteVector::npos()) {
::memcpy(dst.data() + dstOffset, data() + offset, size() - offset);
break;
}
@@ -501,23 +485,22 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
}
int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const {
size_t ByteVector::endsWithPartialMatch(const ByteVector &pattern) const {
if (pattern.size() > size())
return -1;
return npos();
const int startIndex = size() - pattern.size();
const size_t startIndex = size() - pattern.size();
// try to match the last n-1 bytes from the vector (where n is the pattern
// size) -- continue trying to match n-2, n-3...1 bytes
for (unsigned int i = 1; i < pattern.size(); i++) {
for (size_t i = 1; i < pattern.size(); i++) {
if (containsAt(pattern, startIndex + i, 0, pattern.size() - i))
return startIndex + i;
}
return -1;
return npos();
}
ByteVector &ByteVector::append(const ByteVector &v) {
@@ -527,8 +510,8 @@ ByteVector &ByteVector::append(const ByteVector &v) {
detach();
const unsigned int originalSize = size();
const unsigned int appendSize = v.size();
const size_t originalSize = size();
const size_t appendSize = v.size();
resize(originalSize + appendSize);
::memcpy(data() + originalSize, v.data(), appendSize);
@@ -547,11 +530,11 @@ ByteVector &ByteVector::clear() {
return *this;
}
unsigned int ByteVector::size() const {
size_t ByteVector::size() const {
return d->length;
}
ByteVector &ByteVector::resize(unsigned int size, char padding) {
ByteVector &ByteVector::resize(size_t size, char padding) {
if (size != d->length) {
detach();
@@ -620,71 +603,75 @@ bool ByteVector::isEmpty() const {
return (d->length == 0);
}
unsigned int ByteVector::toUInt(bool mostSignificantByteFirst) const {
return toNumber<unsigned int>(*this, 0, mostSignificantByteFirst);
short ByteVector::toInt16LE(size_t offset) const {
return static_cast<short>(toNumber<unsigned short, 2, LittleEndian>(*this, offset));
}
unsigned int ByteVector::toUInt(unsigned int offset, bool mostSignificantByteFirst) const {
return toNumber<unsigned int>(*this, offset, mostSignificantByteFirst);
short ByteVector::toInt16BE(size_t offset) const {
return static_cast<short>(toNumber<unsigned short, 2, BigEndian>(*this, offset));
}
unsigned int ByteVector::toUInt(unsigned int offset, unsigned int length, bool mostSignificantByteFirst) const {
return toNumber<unsigned int>(*this, offset, length, mostSignificantByteFirst);
unsigned short ByteVector::toUInt16LE(size_t offset) const {
return toNumber<unsigned short, 2, LittleEndian>(*this, offset);
}
short ByteVector::toShort(bool mostSignificantByteFirst) const {
return toNumber<unsigned short>(*this, 0, mostSignificantByteFirst);
unsigned short ByteVector::toUInt16BE(size_t offset) const {
return toNumber<unsigned short, 2, BigEndian>(*this, offset);
}
short ByteVector::toShort(unsigned int offset, bool mostSignificantByteFirst) const {
return toNumber<unsigned short>(*this, offset, mostSignificantByteFirst);
unsigned int ByteVector::toUInt24LE(size_t offset) const {
return toNumber<unsigned int, 3, LittleEndian>(*this, offset);
}
unsigned short ByteVector::toUShort(bool mostSignificantByteFirst) const {
return toNumber<unsigned short>(*this, 0, mostSignificantByteFirst);
unsigned int ByteVector::toUInt24BE(size_t offset) const {
return toNumber<unsigned int, 3, BigEndian>(*this, offset);
}
unsigned short ByteVector::toUShort(unsigned int offset, bool mostSignificantByteFirst) const {
return toNumber<unsigned short>(*this, offset, mostSignificantByteFirst);
unsigned int ByteVector::toUInt32LE(size_t offset) const {
return toNumber<unsigned int, 4, LittleEndian>(*this, offset);
}
long long ByteVector::toLongLong(bool mostSignificantByteFirst) const {
return toNumber<unsigned long long>(*this, 0, mostSignificantByteFirst);
unsigned int ByteVector::toUInt32BE(size_t offset) const {
return toNumber<unsigned int, 4, BigEndian>(*this, offset);
}
long long ByteVector::toLongLong(unsigned int offset, bool mostSignificantByteFirst) const {
return toNumber<unsigned long long>(*this, offset, mostSignificantByteFirst);
long long ByteVector::toInt64LE(size_t offset) const {
return static_cast<long long>(toNumber<unsigned long long, 8, LittleEndian>(*this, offset));
}
long long ByteVector::toInt64BE(size_t offset) const {
return static_cast<long long>(toNumber<unsigned long long, 8, BigEndian>(*this, offset));
}
float ByteVector::toFloat32LE(size_t offset) const {
return toFloat<float, unsigned int, Utils::LittleEndian>(*this, offset);
return toFloat<float, unsigned int, LittleEndian>(*this, offset);
}
float ByteVector::toFloat32BE(size_t offset) const {
return toFloat<float, unsigned int, Utils::BigEndian>(*this, offset);
return toFloat<float, unsigned int, BigEndian>(*this, offset);
}
double ByteVector::toFloat64LE(size_t offset) const {
return toFloat<double, unsigned long long, Utils::LittleEndian>(*this, offset);
return toFloat<double, unsigned long long, LittleEndian>(*this, offset);
}
double ByteVector::toFloat64BE(size_t offset) const {
return toFloat<double, unsigned long long, Utils::BigEndian>(*this, offset);
return toFloat<double, unsigned long long, BigEndian>(*this, offset);
}
long double ByteVector::toFloat80LE(size_t offset) const {
return toFloat80<Utils::LittleEndian>(*this, offset);
return toFloat80<LittleEndian>(*this, offset);
}
long double ByteVector::toFloat80BE(size_t offset) const {
return toFloat80<Utils::BigEndian>(*this, offset);
return toFloat80<BigEndian>(*this, offset);
}
const char &ByteVector::operator[](int index) const {
const char &ByteVector::operator[](size_t index) const {
return (*d->data)[d->offset + index];
}
char &ByteVector::operator[](int index) {
char &ByteVector::operator[](size_t index) {
detach();
return (*d->data)[d->offset + index];
}
@@ -766,6 +753,7 @@ ByteVector ByteVector::toHex() const {
}
ByteVector ByteVector::fromBase64(const ByteVector &input) {
static const unsigned char base64[256] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
@@ -785,7 +773,7 @@ ByteVector ByteVector::fromBase64(const ByteVector &input) {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
};
unsigned int len = input.size();
size_t len = input.size();
ByteVector output(len);
@@ -840,7 +828,7 @@ ByteVector ByteVector::fromBase64(const ByteVector &input) {
// Only return output if we processed all bytes
if (len == 0) {
output.resize(static_cast<unsigned int>(dst - reinterpret_cast<unsigned char*>(output.data())));
output.resize(dst - reinterpret_cast<unsigned char*>(output.data()));
return output;
}
return ByteVector();
@@ -850,7 +838,7 @@ ByteVector ByteVector::toBase64() const {
static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (!isEmpty()) {
unsigned int len = size();
size_t len = size();
ByteVector output(4 * ((len - 1) / 3 + 1)); // note roundup
const char *src = data();
@@ -887,22 +875,24 @@ ByteVector ByteVector::toBase64() const {
////////////////////////////////////////////////////////////////////////////////
void ByteVector::detach() {
if (d->counter->count() > 1) {
if (!d->data.unique()) {
if (!isEmpty())
ByteVector(&d->data->front() + d->offset, d->length).swap(*this);
else
ByteVector().swap(*this);
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
////////////////////////////////////////////////////////////////////////////////
// related functions
////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::ByteVector &v) {
for (unsigned int i = 0; i < v.size(); i++)
std::ostream &operator<<(std::ostream &s, const ByteVector &v) {
for (size_t i = 0; i < v.size(); i++)
s << v[i];
return s;
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -59,7 +59,7 @@ class TAGLIB_EXPORT ByteVector {
/*!
* Construct a vector of size \a size with all values set to \a value by default.
*/
explicit ByteVector(unsigned int size, char value = 0);
explicit ByteVector(size_t size, char value = 0);
/*!
* Constructs a byte vector that is a copy of \a v.
@@ -69,7 +69,7 @@ class TAGLIB_EXPORT ByteVector {
/*!
* Constructs a byte vector that is a copy of \a v.
*/
explicit ByteVector(const ByteVector &v, unsigned int offset, unsigned int length);
explicit ByteVector(const ByteVector &v, size_t offset, size_t length);
/*!
* Constructs a byte vector that contains \a c.
@@ -79,7 +79,7 @@ class TAGLIB_EXPORT ByteVector {
/*!
* Constructs a byte vector that copies \a data for up to \a length bytes.
*/
explicit ByteVector(const char *data, unsigned int length);
explicit ByteVector(const char *data, size_t length);
/*!
* Constructs a byte vector that copies \a data up to the first null byte.
@@ -97,7 +97,7 @@ class TAGLIB_EXPORT ByteVector {
/*!
* Sets the data for the byte array using the first \a length bytes of \a data
*/
ByteVector &setData(const char *data, unsigned int length);
ByteVector &setData(const char *data, size_t length);
/*!
* Sets the data for the byte array copies \a data up to the first null byte.
@@ -122,13 +122,13 @@ class TAGLIB_EXPORT ByteVector {
* Returns a byte vector made up of the bytes starting at \a index and for \a length bytes.
* If \a length is not specified it will return the bytes from \a index to the end of the vector.
*/
ByteVector mid(unsigned int index, unsigned int length = 0xffffffff) const;
ByteVector mid(size_t index, size_t length = npos()) const;
/*!
* This essentially performs the same as operator[](), but instead of causing
* a runtime error if the index is out of bounds, it will return a null byte.
*/
char at(unsigned int index) const;
char at(size_t index) const;
/*!
* Searches the ByteVector for \a pattern starting at \a offset and returns
@@ -136,7 +136,7 @@ class TAGLIB_EXPORT ByteVector {
* 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;
size_t find(const ByteVector &pattern, size_t offset = 0, size_t byteAlign = 1) const;
/*!
* Searches the char for \a c starting at \a offset and returns the offset.
@@ -144,21 +144,21 @@ class TAGLIB_EXPORT ByteVector {
* 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;
size_t find(char c, size_t offset = 0, size_t byteAlign = 1) const;
/*!
* Searches the ByteVector for \a pattern starting from either the end of the vector or \a offset and returns the offset.
* Returns -1 if the pattern was not found.
* If \a byteAlign is specified the pattern will only be matched if it starts on a byte divisible by \a byteAlign (starting from \a offset).
*/
int rfind(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const;
size_t rfind(const ByteVector &pattern, size_t offset = 0, size_t byteAlign = 1) const;
/*!
* Checks to see if the vector contains the \a pattern starting at position \a offset.
* Optionally, if you only want to search for part of the pattern you can specify an offset within the pattern to start from.
* Also, you can specify to only check for the first \a patternLength bytes of \a pattern with the \a patternLength argument.
*/
bool containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset = 0, unsigned int patternLength = 0xffffffff) const;
bool containsAt(const ByteVector &pattern, size_t offset, size_t patternOffset = 0, size_t patternLength = npos()) const;
/*!
* Returns true if the vector starts with \a pattern.
@@ -188,7 +188,7 @@ class TAGLIB_EXPORT ByteVector {
*
* \note This will not match the complete pattern at the end of the string; use endsWith() for that.
*/
int endsWithPartialMatch(const ByteVector &pattern) const;
size_t endsWithPartialMatch(const ByteVector &pattern) const;
/*!
* Appends \a v to the end of the ByteVector.
@@ -208,14 +208,14 @@ class TAGLIB_EXPORT ByteVector {
/*!
* Returns the size of the array.
*/
unsigned int size() const;
size_t size() const;
/*!
* Resize the vector to \a size.
* If the vector is currently less than \a size, pad the remaining spaces with \a padding.
* Returns a reference to the resized vector.
*/
ByteVector &resize(unsigned int size, char padding = 0);
ByteVector &resize(size_t size, char padding = 0);
/*!
* Returns an Iterator that points to the front of the vector.
@@ -261,104 +261,74 @@ class TAGLIB_EXPORT ByteVector {
* Returns true if the ByteVector is empty.
*
* \see size()
* \see isNull()
*/
bool isEmpty() const;
/*!
* Converts the first 4 bytes of the vector to an unsigned integer.
* Converts the 2 bytes at \a offset of the vector to a short as a signed 16-bit little-endian 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()
* \see fromUInt16LE()
*/
unsigned int toUInt(bool mostSignificantByteFirst = true) const;
short toInt16LE(size_t offset) const;
/*!
* Converts the 4 bytes at \a offset of the vector to an unsigned integer.
* Converts the 2 bytes at \a offset of the vector to a short as a signed 16-bit big-endian 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()
* \see fromUInt16BE()
*/
unsigned int toUInt(unsigned int offset, bool mostSignificantByteFirst = true) const;
short toInt16BE(size_t offset) 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.
* Converts the 2 bytes at \a offset of the vector to a unsigned short as an unsigned 16-bit little-endian 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()
* \see fromUInt16LE()
*/
unsigned int toUInt(unsigned int offset, unsigned int length,
bool mostSignificantByteFirst = true) const;
unsigned short toUInt16LE(size_t offset) const;
/*!
* Converts the first 2 bytes of the vector to a (signed) short.
* Converts the 2 bytes at \a offset of the vector to a unsigned short as an unsigned 16-bit big-endian integer.
*
* 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()
* \see fromUInt16BE()
*/
short toShort(bool mostSignificantByteFirst = true) const;
unsigned short toUInt16BE(size_t offset) 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 3 bytes at \a offset of the vector to a unsigned int as an unsigned 24-bit little-endian integer.
*/
short toShort(unsigned int offset, bool mostSignificantByteFirst = true) const;
unsigned int toUInt24LE(size_t offset) 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 3 bytes at \a offset of the vector to a unsigned int as an unsigned 24-bit big-endian integer.
*/
unsigned short toUShort(bool mostSignificantByteFirst = true) const;
unsigned int toUInt24BE(size_t offset) const;
/*!
* Converts the 2 bytes at \a offset of the vector to a unsigned short.
* Converts the 4 bytes at \a offset of the vector to a unsigned int as an unsigned 32-bit little-endian integer.
*
* 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()
* \see fromUInt32LE()
*/
unsigned short toUShort(unsigned int offset, bool mostSignificantByteFirst = true) const;
unsigned int toUInt32LE(size_t offset) const;
/*!
* Converts the first 8 bytes of the vector to a (signed) long long.
* Converts the 4 bytes at \a offset of the vector to a unsigned int as an unsigned 32-bit big-endian 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 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt()
* \see fromUInt32BE()
*/
long long toLongLong(bool mostSignificantByteFirst = true) const;
unsigned int toUInt32BE(size_t offset) const;
/*!
* Converts the 8 bytes at \a offset of the vector to a (signed) long long.
* Converts the 8 bytes at \a offset of the vector to a long long as a signed 64-bit little-endian 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 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt()
* \see fromUInt64LE()
*/
long long toLongLong(unsigned int offset, bool mostSignificantByteFirst = true) const;
long long toInt64LE(size_t offset) const;
/*!
* Converts the 8 bytes at \a offset of the vector to a long long as a signed 64-bit big-endian integer.
*
* \see fromUInt64BE()
*/
long long toInt64BE(size_t offset) const;
/*
* Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 32-bit little-endian floating point number.
@@ -395,33 +365,50 @@ class TAGLIB_EXPORT ByteVector {
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.
* Creates a 2 byte ByteVector based on \a value as an unsigned 16-bit little-endian integer.
*
* \see toUInt()
* \note If \a value is larger than 16-bit, the lowest 16 bits are used.
* \see toUInt16LE()
*/
static ByteVector fromUInt(unsigned int value, bool mostSignificantByteFirst = true);
static ByteVector fromUInt16LE(size_t value);
/*!
* 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.
* Creates a 2 byte ByteVector based on \a value as an unsigned 16-bit big-endian integer.
*
* \see toShort()
* \note If \a value is larger than 16-bit, the lowest 16 bits are used.
* \see toUInt16BE()
*/
static ByteVector fromShort(short value, bool mostSignificantByteFirst = true);
static ByteVector fromUInt16BE(size_t value);
/*!
* 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.
* Creates a 4 byte ByteVector based on \a value as an unsigned 32-bit little-endian integer.
*
* \see toLongLong()
* \note If \a value is larger than 32-bit, the lowest 32 bits are used.
* \see toUInt32LE()
*/
static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true);
static ByteVector fromUInt32LE(size_t value);
/*!
* Creates a 4 byte ByteVector based on \a value as an unsigned 32-bit big-endian integer.
*
* \note If \a value is larger than 32-bit, the lowest 32 bits are used.
* \see toUInt32BE()
*/
static ByteVector fromUInt32BE(size_t value);
/*!
* Creates a 8 byte ByteVector based on \a value as an unsigned 64-bit little-endian integer.
*
* \see toUInt64LE()
*/
static ByteVector fromUInt64LE(unsigned long long value);
/*!
* Creates a 8 byte ByteVector based on \a value as an unsigned 64-bit big-endian integer.
*
* \see toUInt64BE()
*/
static ByteVector fromUInt64BE(unsigned long long value);
/*!
* Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit little-endian floating point number.
@@ -454,17 +441,17 @@ class TAGLIB_EXPORT ByteVector {
/*!
* Returns a ByteVector based on the CString \a s.
*/
static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff);
static ByteVector fromCString(const char *s, size_t length = npos());
/*!
* Returns a const reference to the byte at \a index.
*/
const char &operator[](int index) const;
const char &operator[](size_t index) const;
/*!
* Returns a reference to the byte at \a index.
*/
char &operator[](int index);
char &operator[](size_t index);
/*!
* Returns true if this ByteVector and \a v are equal.
@@ -525,6 +512,13 @@ class TAGLIB_EXPORT ByteVector {
*/
void swap(ByteVector &v);
/*!
* Returns a special value used for \a length or \a patternLength parameters
* of ByteVector's member functions, means "until the end of the data".
* As a return value, it is usually used to indicate no matches.
*/
static size_t npos();
/*!
* Returns a hex-encoded copy of the byte vector.
*/
@@ -551,8 +545,6 @@ class TAGLIB_EXPORT ByteVector {
class ByteVectorPrivate;
ByteVectorPrivate *d;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \relates Strawberry_TagLib::TagLib::ByteVector
@@ -560,4 +552,7 @@ class TAGLIB_EXPORT ByteVector {
*/
TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::ByteVector &v);
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -27,18 +27,16 @@
using namespace Strawberry_TagLib::TagLib;
class ByteVectorListPrivate {};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, int byteAlign, int max) {
ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, size_t byteAlign, size_t 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)) {
size_t previousOffset = 0;
for (size_t offset = v.find(pattern, 0, byteAlign); offset != ByteVector::npos() && (max == 0 || max > l.size() + 1); offset = v.find(pattern, offset + pattern.size(), byteAlign)) {
if (offset - previousOffset >= 1)
l.append(v.mid(previousOffset, offset - previousOffset));
else
@@ -58,9 +56,14 @@ ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &patt
// public members
////////////////////////////////////////////////////////////////////////////////
ByteVectorList::ByteVectorList() : d(nullptr) {}
ByteVectorList::ByteVectorList() {}
ByteVectorList::~ByteVectorList() {}
ByteVectorList::ByteVectorList(const ByteVectorList &l) : List<ByteVector>(l) {}
ByteVectorList &ByteVectorList::operator=(const ByteVectorList &l) {
List<ByteVector>::operator=(l);
return *this;
}
ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const {

View File

@@ -47,9 +47,16 @@ class TAGLIB_EXPORT ByteVectorList : public List<ByteVector> {
explicit ByteVectorList();
/*!
* Destroys this ByteVectorList instance.
* Make a shallow, implicitly shared, copy of \a l.
* Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage.
*/
virtual ~ByteVectorList();
ByteVectorList(const ByteVectorList &l);
/*!
* Make a shallow, implicitly shared, copy of \a l.
* Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage.
*/
ByteVectorList &operator=(const ByteVectorList &l);
/*!
* Convert the ByteVectorList to a ByteVector separated by \a separator. By default a space is used.
@@ -63,11 +70,8 @@ class TAGLIB_EXPORT ByteVectorList : public List<ByteVector> {
* 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);
static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, size_t byteAlign = 1, size_t max = 0);
private:
class ByteVectorListPrivate;
ByteVectorListPrivate *d;
};
} // namespace TagLib

View File

@@ -38,7 +38,7 @@ class ByteVectorStream::ByteVectorStreamPrivate {
explicit ByteVectorStreamPrivate(const ByteVector &data);
ByteVector data;
long position;
long long position;
};
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) : data(_data), position(0) {}
@@ -57,7 +57,7 @@ FileName ByteVectorStream::name() const {
return FileName(""); // XXX do we need a name?
}
ByteVector ByteVectorStream::readBlock(unsigned long length) {
ByteVector ByteVectorStream::readBlock(size_t length) {
if (length == 0)
return ByteVector();
@@ -70,39 +70,39 @@ ByteVector ByteVectorStream::readBlock(unsigned long length) {
void ByteVectorStream::writeBlock(const ByteVector &data) {
unsigned int size = data.size();
if (long(d->position + size) > length()) {
const size_t size = data.size();
if (static_cast<long long>(d->position + size) > length()) {
truncate(d->position + size);
}
memcpy(d->data.data() + d->position, data.data(), size);
::memcpy(d->data.data() + d->position, data.data(), size);
d->position += size;
}
void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) {
void ByteVectorStream::insert(const ByteVector &data, long long start, size_t replace) {
long sizeDiff = data.size() - replace;
if (sizeDiff < 0) {
removeBlock(start + data.size(), -sizeDiff);
if (data.size() < replace) {
removeBlock(start + data.size(), replace - data.size());
}
else if (sizeDiff > 0) {
else if (data.size() > replace) {
const size_t sizeDiff = data.size() - replace;
truncate(length() + sizeDiff);
unsigned long readPosition = start + replace;
unsigned long writePosition = start + data.size();
memmove(d->data.data() + writePosition, d->data.data() + readPosition, length() - sizeDiff - readPosition);
const size_t readPosition = static_cast<size_t>(start + replace);
const size_t writePosition = static_cast<size_t>(start + data.size());
::memmove(d->data.data() + writePosition, d->data.data() + readPosition, static_cast<size_t>(length() - sizeDiff - readPosition));
}
seek(start);
writeBlock(data);
}
void ByteVectorStream::removeBlock(unsigned long start, unsigned long length) {
void ByteVectorStream::removeBlock(long long start, size_t length) {
unsigned long readPosition = start + length;
unsigned long writePosition = start;
if (readPosition < static_cast<unsigned long>(ByteVectorStream::length())) {
unsigned long bytesToMove = ByteVectorStream::length() - readPosition;
memmove(d->data.data() + writePosition, d->data.data() + readPosition, bytesToMove);
const long long readPosition = start + length;
long long writePosition = start;
if (readPosition < ByteVectorStream::length()) {
size_t bytesToMove = static_cast<size_t>(ByteVectorStream::length() - readPosition);
::memmove(d->data.data() + static_cast<ptrdiff_t>(writePosition), d->data.data() + static_cast<ptrdiff_t>(readPosition), bytesToMove);
writePosition += bytesToMove;
}
d->position = writePosition;
@@ -118,7 +118,7 @@ bool ByteVectorStream::isOpen() const {
return true;
}
void ByteVectorStream::seek(long offset, Position p) {
void ByteVectorStream::seek(long long offset, Position p) {
switch (p) {
case Beginning:
@@ -136,15 +136,15 @@ void ByteVectorStream::seek(long offset, Position p) {
void ByteVectorStream::clear() {}
long ByteVectorStream::tell() const {
long long ByteVectorStream::tell() const {
return d->position;
}
long ByteVectorStream::length() {
long long ByteVectorStream::length() {
return d->data.size();
}
void ByteVectorStream::truncate(long length) {
void ByteVectorStream::truncate(long long length) {
d->data.resize(length);
}

View File

@@ -50,17 +50,17 @@ class TAGLIB_EXPORT ByteVectorStream : public IOStream {
/*!
* Destroys this ByteVectorStream instance.
*/
virtual ~ByteVectorStream();
~ByteVectorStream() override;
/*!
* Returns the file name in the local file system encoding.
*/
FileName name() const;
FileName name() const override;
/*!
* Reads a block of size \a length at the current get pointer.
*/
ByteVector readBlock(unsigned long length);
ByteVector readBlock(size_t length) override;
/*!
* Attempts to write the block \a data at the current get pointer.
@@ -69,31 +69,31 @@ class TAGLIB_EXPORT ByteVectorStream : public IOStream {
* \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);
void writeBlock(const ByteVector &data) override;
/*!
* Insert \a data at position \a start in the file overwriting \a replace bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file after the insertion point.
*/
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
void insert(const ByteVector &data, long long start = 0, size_t replace = 0) override;
/*!
* Removes a block of the file starting a \a start and continuing for \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file after the removed portion.
*/
void removeBlock(unsigned long start = 0, unsigned long length = 0);
void removeBlock(long long start = 0, size_t length = 0) override;
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
bool readOnly() const;
bool readOnly() const override;
/*!
* Since the file can currently only be opened as an argument to the constructor (sort-of by design), this returns if that open succeeded.
*/
bool isOpen() const;
bool isOpen() const override;
/*!
* Move the I/O pointer to \a offset in the file from position \a p.
@@ -101,27 +101,27 @@ class TAGLIB_EXPORT ByteVectorStream : public IOStream {
*
* \see Position
*/
void seek(long offset, Position p = Beginning);
void seek(long long offset, Position p = Beginning) override;
/*!
* Reset the end-of-file and error flags on the file.
*/
void clear();
void clear() override;
/*!
* Returns the current offset within the file.
*/
long tell() const;
long long tell() const override;
/*!
* Returns the length of the file.
*/
long length();
long long length() override;
/*!
* Truncates the file to a \a length.
*/
void truncate(long length);
void truncate(long long length) override;
ByteVector *data();

View File

@@ -23,9 +23,7 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "taglib-config.h"
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)

View File

@@ -40,7 +40,7 @@ class DefaultListener : public DebugListener {
void printMessage(const String &msg) override {
#ifdef _WIN32
const wstring wstr = msg.toWString();
const std::wstring wstr = msg.toWString();
const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if (len != 0) {
std::vector<char> buf(len);

View File

@@ -53,7 +53,7 @@ class TAGLIB_EXPORT DebugListener {
private:
// Noncopyable
explicit DebugListener(const DebugListener&);
DebugListener(const DebugListener&);
DebugListener &operator=(const DebugListener&);
};

View File

@@ -28,49 +28,13 @@
#include "tstring.h"
#include "tdebug.h"
#include "tpropertymap.h"
#ifdef _WIN32
# include <windows.h>
# include <io.h>
#else
# include <cstdio>
# include <unistd.h>
#endif
#ifndef R_OK
# define R_OK 4
#endif
#ifndef W_OK
# define W_OK 2
#endif
#include "asffile.h"
#include "mpegfile.h"
#include "vorbisfile.h"
#include "flacfile.h"
#include "oggflacfile.h"
#include "mpcfile.h"
#include "mp4file.h"
#include "wavpackfile.h"
#include "speexfile.h"
#include "opusfile.h"
#include "trueaudiofile.h"
#include "aifffile.h"
#include "wavfile.h"
#include "apefile.h"
#include "modfile.h"
#include "s3mfile.h"
#include "itfile.h"
#include "xmfile.h"
#include "mp4file.h"
#include "dsffile.h"
#include "dsdifffile.h"
#include "audioproperties.h"
using namespace Strawberry_TagLib::TagLib;
class File::FilePrivate {
public:
FilePrivate(IOStream *_stream, bool _owner) : stream(_stream), streamOwner(_owner), valid(true) {}
explicit FilePrivate(IOStream *_stream, bool _owner) : stream(_stream), streamOwner(_owner), valid(true) {}
~FilePrivate() {
if (streamOwner)
@@ -86,10 +50,6 @@ class File::FilePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
File::File(const FileName fileName) : d(new FilePrivate(new FileStream(fileName), true)) {}
File::File(IOStream *stream) : d(new FilePrivate(stream, false)) {}
File::~File() {
delete d;
}
@@ -99,161 +59,45 @@ 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();
if (dynamic_cast<const FLAC::File*>(this))
return dynamic_cast<const FLAC::File*>(this)->properties();
if (dynamic_cast<const IT::File*>(this))
return dynamic_cast<const IT::File*>(this)->properties();
if (dynamic_cast<const Mod::File*>(this))
return dynamic_cast<const Mod::File*>(this)->properties();
if (dynamic_cast<const MPC::File*>(this))
return dynamic_cast<const MPC::File*>(this)->properties();
if (dynamic_cast<const MPEG::File*>(this))
return dynamic_cast<const MPEG::File*>(this)->properties();
if (dynamic_cast<const Ogg::FLAC::File*>(this))
return dynamic_cast<const Ogg::FLAC::File*>(this)->properties();
if (dynamic_cast<const Ogg::Speex::File*>(this))
return dynamic_cast<const Ogg::Speex::File*>(this)->properties();
if (dynamic_cast<const Ogg::Opus::File*>(this))
return dynamic_cast<const Ogg::Opus::File*>(this)->properties();
if (dynamic_cast<const Ogg::Vorbis::File*>(this))
return dynamic_cast<const Ogg::Vorbis::File*>(this)->properties();
if (dynamic_cast<const RIFF::AIFF::File*>(this))
return dynamic_cast<const RIFF::AIFF::File*>(this)->properties();
if (dynamic_cast<const RIFF::WAV::File*>(this))
return dynamic_cast<const RIFF::WAV::File*>(this)->properties();
if (dynamic_cast<const S3M::File*>(this))
return dynamic_cast<const S3M::File*>(this)->properties();
if (dynamic_cast<const TrueAudio::File*>(this))
return dynamic_cast<const TrueAudio::File*>(this)->properties();
if (dynamic_cast<const WavPack::File*>(this))
return dynamic_cast<const WavPack::File*>(this)->properties();
if (dynamic_cast<const XM::File*>(this))
return dynamic_cast<const XM::File*>(this)->properties();
if (dynamic_cast<const MP4::File*>(this))
return dynamic_cast<const MP4::File*>(this)->properties();
if (dynamic_cast<const ASF::File*>(this))
return dynamic_cast<const ASF::File*>(this)->properties();
if (dynamic_cast<const DSF::File*>(this))
return dynamic_cast<const DSF::File*>(this)->properties();
if (dynamic_cast<const DSDIFF::File*>(this))
return dynamic_cast<const DSDIFF::File*>(this)->properties();
return tag()->properties();
}
void File::removeUnsupportedProperties(const StringList &properties) {
tag()->removeUnsupportedProperties(properties);
}
void File::removeUnsupportedProperties(const StringList& properties) {
// here we only consider those formats that could possibly contain unsupported properties
if (dynamic_cast<APE::File*>(this))
dynamic_cast<APE::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<FLAC::File*>(this))
dynamic_cast<FLAC::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<MPC::File*>(this))
dynamic_cast<MPC::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<MPEG::File*>(this))
dynamic_cast<MPEG::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<Ogg::Vorbis::File*>(this))
dynamic_cast<Ogg::Vorbis::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<RIFF::AIFF::File*>(this))
dynamic_cast<RIFF::AIFF::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<RIFF::WAV::File*>(this))
dynamic_cast<RIFF::WAV::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<TrueAudio::File*>(this))
dynamic_cast<TrueAudio::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<WavPack::File*>(this))
dynamic_cast<WavPack::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<MP4::File*>(this))
dynamic_cast<MP4::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<ASF::File*>(this))
dynamic_cast<ASF::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<DSF::File*>(this))
dynamic_cast<DSF::File*>(this)->removeUnsupportedProperties(properties);
else if (dynamic_cast<DSDIFF::File*>(this))
dynamic_cast<DSDIFF::File*>(this)->removeUnsupportedProperties(properties);
else
tag()->removeUnsupportedProperties(properties);
PropertyMap File::setProperties(const PropertyMap &properties) {
return tag()->setProperties(properties);
}
PropertyMap File::setProperties(const PropertyMap& properties) {
if (dynamic_cast<APE::File*>(this))
return dynamic_cast<APE::File*>(this)->setProperties(properties);
else if (dynamic_cast<FLAC::File*>(this))
return dynamic_cast<FLAC::File*>(this)->setProperties(properties);
else if (dynamic_cast<IT::File*>(this))
return dynamic_cast<IT::File*>(this)->setProperties(properties);
else if (dynamic_cast<Mod::File*>(this))
return dynamic_cast<Mod::File*>(this)->setProperties(properties);
else if (dynamic_cast<MPC::File*>(this))
return dynamic_cast<MPC::File*>(this)->setProperties(properties);
else if (dynamic_cast<MPEG::File*>(this))
return dynamic_cast<MPEG::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::FLAC::File*>(this))
return dynamic_cast<Ogg::FLAC::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::Speex::File*>(this))
return dynamic_cast<Ogg::Speex::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::Opus::File*>(this))
return dynamic_cast<Ogg::Opus::File*>(this)->setProperties(properties);
else if (dynamic_cast<Ogg::Vorbis::File*>(this))
return dynamic_cast<Ogg::Vorbis::File*>(this)->setProperties(properties);
else if (dynamic_cast<RIFF::AIFF::File*>(this))
return dynamic_cast<RIFF::AIFF::File*>(this)->setProperties(properties);
else if (dynamic_cast<RIFF::WAV::File*>(this))
return dynamic_cast<RIFF::WAV::File*>(this)->setProperties(properties);
else if (dynamic_cast<S3M::File*>(this))
return dynamic_cast<S3M::File*>(this)->setProperties(properties);
else if (dynamic_cast<TrueAudio::File*>(this))
return dynamic_cast<TrueAudio::File*>(this)->setProperties(properties);
else if (dynamic_cast<WavPack::File*>(this))
return dynamic_cast<WavPack::File*>(this)->setProperties(properties);
else if (dynamic_cast<XM::File*>(this))
return dynamic_cast<XM::File*>(this)->setProperties(properties);
else if (dynamic_cast<MP4::File*>(this))
return dynamic_cast<MP4::File*>(this)->setProperties(properties);
else if (dynamic_cast<ASF::File*>(this))
return dynamic_cast<ASF::File*>(this)->setProperties(properties);
else if (dynamic_cast<DSF::File*>(this))
return dynamic_cast<DSF::File*>(this)->setProperties(properties);
else if (dynamic_cast<DSDIFF::File*>(this))
return dynamic_cast<DSDIFF::File*>(this)->setProperties(properties);
else
return tag()->setProperties(properties);
}
ByteVector File::readBlock(unsigned long length) {
ByteVector File::readBlock(size_t length) {
return d->stream->readBlock(length);
}
void File::writeBlock(const ByteVector& data) {
void File::writeBlock(const ByteVector &data) {
d->stream->writeBlock(data);
}
long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before) {
long long File::find(const ByteVector &pattern, long long fromOffset, const ByteVector &before) {
if (!d->stream || pattern.size() > bufferSize())
return -1;
// The position in the file that the current buffer starts at.
long bufferOffset = fromOffset;
ByteVector buffer;
long long bufferOffset = fromOffset;
// These variables are used to keep track of a partial match that happens at
// the end of a buffer.
int previousPartialMatch = -1;
int beforePreviousPartialMatch = -1;
size_t previousPartialMatch = ByteVector::npos();
size_t beforePreviousPartialMatch = ByteVector::npos();
// Save the location of the current read pointer. We will restore the
// position using seek() before all returns.
long originalPosition = tell();
long long originalPosition = tell();
// Start the search at the offset.
@@ -277,20 +121,20 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
// then check for "before". The order is important because it gives priority
// to "real" matches.
for (buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
for (ByteVector buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) {
// (1) previous partial match
if (previousPartialMatch >= 0 && int(bufferSize()) > previousPartialMatch) {
const int patternOffset = (bufferSize() - previousPartialMatch);
if (previousPartialMatch != ByteVector::npos() && bufferSize() > previousPartialMatch) {
const size_t patternOffset = (bufferSize() - previousPartialMatch);
if (buffer.containsAt(pattern, 0, patternOffset)) {
seek(originalPosition);
return bufferOffset - bufferSize() + previousPartialMatch;
}
}
if (!before.isEmpty() && beforePreviousPartialMatch >= 0 && int(bufferSize()) > beforePreviousPartialMatch) {
const int beforeOffset = (bufferSize() - beforePreviousPartialMatch);
if (!before.isEmpty() && beforePreviousPartialMatch != ByteVector::npos() && bufferSize() > beforePreviousPartialMatch) {
const size_t beforeOffset = (bufferSize() - beforePreviousPartialMatch);
if (buffer.containsAt(before, 0, beforeOffset)) {
seek(originalPosition);
return -1;
@@ -299,13 +143,13 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
// (2) pattern contained in current buffer
long location = buffer.find(pattern);
if (location >= 0) {
size_t location = buffer.find(pattern);
if (location != ByteVector::npos()) {
seek(originalPosition);
return bufferOffset + location;
}
if (!before.isEmpty() && buffer.find(before) >= 0) {
if (!before.isEmpty() && buffer.find(before) != ByteVector::npos()) {
seek(originalPosition);
return -1;
}
@@ -331,35 +175,23 @@ long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &be
}
long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before) {
long long File::rfind(const ByteVector &pattern, long long fromOffset, const ByteVector &before) {
if (!d->stream || pattern.size() > bufferSize())
return -1;
// The position in the file that the current buffer starts at.
ByteVector buffer;
// These variables are used to keep track of a partial match that happens at
// the end of a buffer.
/*
int previousPartialMatch = -1;
int beforePreviousPartialMatch = -1;
*/
// Save the location of the current read pointer. We will restore the
// position using seek() before all returns.
long originalPosition = tell();
long long originalPosition = tell();
// Start the search at the offset.
if (fromOffset == 0)
fromOffset = length();
long bufferLength = bufferSize();
long bufferOffset = fromOffset + pattern.size();
long long bufferLength = bufferSize();
long long bufferOffset = fromOffset + pattern.size();
// See the notes in find() for an explanation of this algorithm.
@@ -374,7 +206,7 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
}
seek(bufferOffset);
buffer = readBlock(bufferLength);
const ByteVector buffer = readBlock(static_cast<size_t>(bufferLength));
if (buffer.isEmpty())
break;
@@ -382,13 +214,13 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
// (2) pattern contained in current buffer
const long location = buffer.rfind(pattern);
if (location >= 0) {
const size_t location = buffer.rfind(pattern);
if (location != ByteVector::npos()) {
seek(originalPosition);
return bufferOffset + location;
}
if (!before.isEmpty() && buffer.find(before) >= 0) {
if (!before.isEmpty() && buffer.find(before) != ByteVector::npos()) {
seek(originalPosition);
return -1;
}
@@ -406,11 +238,11 @@ long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &b
}
void File::insert(const ByteVector& data, unsigned long start, unsigned long replace) {
void File::insert(const ByteVector &data, long long start, size_t replace) {
d->stream->insert(data, start, replace);
}
void File::removeBlock(unsigned long start, unsigned long length) {
void File::removeBlock(long long start, size_t length) {
d->stream->removeBlock(start, length);
}
@@ -426,11 +258,11 @@ bool File::isValid() const {
return isOpen() && d->valid;
}
void File::seek(long offset, Position p) {
void File::seek(long long offset, Position p) {
d->stream->seek(offset, IOStream::Position(p));
}
void File::truncate(long length) {
void File::truncate(long long length) {
d->stream->truncate(length);
}
@@ -438,20 +270,40 @@ void File::clear() {
d->stream->clear();
}
long File::tell() const {
long long File::tell() const {
return d->stream->tell();
}
long File::length() {
long long File::length() {
return d->stream->length();
}
String File::toString() const {
StringList desc;
AudioProperties *properties = audioProperties();
if (properties) {
desc.append(properties->toString());
}
Tag *t = tag();
if (t) {
desc.append(t->toString());
}
return desc.toString("\n");
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
unsigned int File::bufferSize() {
return 1024;
File::File(const FileName &fileName) : d(new FilePrivate(new FileStream(fileName), true)) {}
File::File(IOStream *stream) : d(new FilePrivate(stream, false)) {}
size_t File::bufferSize() {
return FileStream::bufferSize();
}
void File::setValid(bool valid) {

View File

@@ -150,7 +150,7 @@ class TAGLIB_EXPORT File {
/*!
* Reads a block of size \a length at the current get pointer.
*/
ByteVector readBlock(unsigned long length);
ByteVector readBlock(size_t length);
/*!
* Attempts to write the block \a data at the current get pointer.
@@ -171,7 +171,7 @@ class TAGLIB_EXPORT 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());
long long find(const ByteVector &pattern, long 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.
@@ -184,21 +184,21 @@ class TAGLIB_EXPORT 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());
long long rfind(const ByteVector &pattern, long long fromOffset = 0, const ByteVector &before = ByteVector());
/*!
* Insert \a data at position \a start in the file overwriting \a replace bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file after the insertion point.
*/
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
void insert(const ByteVector &data, long long start = 0, size_t replace = 0);
/*!
* Removes a block of the file starting a \a start and continuing for \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file after the removed portion.
*/
void removeBlock(unsigned long start = 0, unsigned long length = 0);
void removeBlock(long long start = 0, size_t length = 0);
/*!
* Returns true if the file is read only (or if the file can not be opened).
@@ -222,7 +222,7 @@ class TAGLIB_EXPORT File {
*
* \see Position
*/
void seek(long offset, Position p = Beginning);
void seek(long long offset, Position p = Beginning);
/*!
* Reset the end-of-file and error flags on the file.
@@ -232,12 +232,17 @@ class TAGLIB_EXPORT File {
/*!
* Returns the current offset within the file.
*/
long tell() const;
long long tell() const;
/*!
* Returns the length of the file.
*/
long length();
long long length();
/*!
* Returns description of the audio file and its tags.
*/
virtual String toString() const;
protected:
/*!
@@ -246,7 +251,7 @@ class TAGLIB_EXPORT File {
*
* \note Constructor is protected since this class should only be instantiated through subclasses.
*/
explicit File(const FileName fileName);
explicit File(const FileName &fileName);
/*!
* Construct a File object and use the \a stream instance.
@@ -267,15 +272,15 @@ class TAGLIB_EXPORT File {
/*!
* Truncates the file to a \a length.
*/
void truncate(long length);
void truncate(long long length);
/*!
* Returns the buffer size that is used for internal buffering.
*/
static unsigned int bufferSize();
static size_t bufferSize();
private:
explicit File(const File&);
File(const File&);
File &operator=(const File&);
class FilePrivate;

View File

@@ -51,9 +51,9 @@ FileHandle openFile(const FileName &path, bool readOnly) {
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
# if defined(PLATFORM_WINRT)
return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
return CreateFile2(path.wstr(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
# else
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
return CreateFileW(path.wstr(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
# endif
}
@@ -149,7 +149,7 @@ FileStream::FileStream(FileName fileName, bool openReadOnly)
if (d->file == InvalidFileHandle)
#ifdef _WIN32
debug("Could not open file " + fileName.toString());
debug("Could not open file " + String(fileName.wstr()));
#else
debug("Could not open file " + String(static_cast<const char *>(d->name)));
#endif
@@ -186,7 +186,7 @@ FileName FileStream::name() const {
return d->name;
}
ByteVector FileStream::readBlock(unsigned long length) {
ByteVector FileStream::readBlock(size_t length) {
if (!isOpen()) {
debug("FileStream::readBlock() -- invalid file.");
@@ -196,14 +196,14 @@ ByteVector FileStream::readBlock(unsigned long length) {
if (length == 0)
return ByteVector();
const unsigned long streamLength = static_cast<unsigned long>(FileStream::length());
if (length > bufferSize() && length > streamLength)
const long long streamLength = FileStream::length();
if (length > bufferSize() && static_cast<long long>(length) > streamLength)
length = streamLength;
ByteVector buffer(static_cast<unsigned int>(length));
ByteVector buffer(length);
const size_t count = readFile(d->file, buffer);
buffer.resize(static_cast<unsigned int>(count));
buffer.resize(count);
return buffer;
@@ -225,7 +225,7 @@ void FileStream::writeBlock(const ByteVector &data) {
}
void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) {
void FileStream::insert(const ByteVector &data, long long start, size_t replace) {
if (!isOpen()) {
debug("FileStream::insert() -- invalid file.");
@@ -259,18 +259,18 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
// the *difference* in the tag sizes. We want to avoid overwriting parts
// that aren't yet in memory, so this is necessary.
unsigned long bufferLength = bufferSize();
size_t bufferLength = bufferSize();
while (data.size() - replace > bufferLength)
bufferLength += bufferSize();
// Set where to start the reading and writing.
long readPosition = start + replace;
long writePosition = start;
long long readPosition = start + replace;
long long writePosition = start;
ByteVector buffer = data;
ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
ByteVector aboutToOverwrite(bufferLength);
while (true) {
// Seek to the current read position and read the data that we're about
@@ -307,19 +307,19 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
}
void FileStream::removeBlock(unsigned long start, unsigned long length) {
void FileStream::removeBlock(long long start, size_t length) {
if (!isOpen()) {
debug("FileStream::removeBlock() -- invalid file.");
return;
}
unsigned long bufferLength = bufferSize();
size_t bufferLength = bufferSize();
long readPosition = start + length;
long writePosition = start;
long long readPosition = start + length;
long long writePosition = start;
ByteVector buffer(static_cast<unsigned int>(bufferLength));
ByteVector buffer(bufferLength, 0);
for (unsigned int bytesRead = -1; bytesRead != 0;) {
seek(readPosition);
@@ -352,7 +352,7 @@ bool FileStream::isOpen() const {
return (d->file != InvalidFileHandle);
}
void FileStream::seek(long offset, Position p) {
void FileStream::seek(long long offset, Position p) {
if (!isOpen()) {
debug("FileStream::seek() -- invalid file.");
@@ -391,7 +391,7 @@ void FileStream::seek(long offset, Position p) {
return;
}
fseek(d->file, offset, whence);
fseeko(d->file, offset, whence);
#endif
@@ -409,15 +409,14 @@ void FileStream::clear() {
#endif
}
long FileStream::tell() const {
long long FileStream::tell() const {
#ifdef _WIN32
const LARGE_INTEGER zero = {};
LARGE_INTEGER position;
if (SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
position.QuadPart <= LONG_MAX) {
return static_cast<long>(position.QuadPart);
if (SetFilePointerEx(d->file, zero, &position, FILE_CURRENT)) {
return position.QuadPart;
}
else {
debug("FileStream::tell() -- Failed to get the file pointer.");
@@ -426,12 +425,12 @@ long FileStream::tell() const {
#else
return ftell(d->file);
return ftello(d->file);
#endif
}
long FileStream::length() {
long long FileStream::length() {
if (!isOpen()) {
debug("FileStream::length() -- invalid file.");
@@ -442,8 +441,8 @@ long FileStream::length() {
LARGE_INTEGER fileSize;
if (GetFileSizeEx(d->file, &fileSize) && fileSize.QuadPart <= LONG_MAX) {
return static_cast<long>(fileSize.QuadPart);
if (GetFileSizeEx(d->file, &fileSize)) {
return fileSize.QuadPart;
}
else {
debug("FileStream::length() -- Failed to get the file size.");
@@ -452,10 +451,10 @@ long FileStream::length() {
#else
const long curpos = tell();
const long long curpos = tell();
seek(0, End);
const long endpos = tell();
const long long endpos = tell();
seek(curpos, Beginning);
@@ -464,14 +463,18 @@ long FileStream::length() {
#endif
}
size_t FileStream::bufferSize() {
return 1024;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
void FileStream::truncate(long length) {
void FileStream::truncate(long long length) {
#ifdef _WIN32
const long currentPos = tell();
const long long currentPos = tell();
seek(length);
@@ -491,6 +494,3 @@ void FileStream::truncate(long length) {
#endif
}
unsigned int FileStream::bufferSize() {
return 1024;
}

View File

@@ -61,17 +61,17 @@ class TAGLIB_EXPORT FileStream : public IOStream {
/*!
* Destroys this FileStream instance.
*/
virtual ~FileStream();
~FileStream() override;
/*!
* Returns the file name in the local file system encoding.
*/
FileName name() const;
FileName name() const override;
/*!
* Reads a block of size \a length at the current get pointer.
*/
ByteVector readBlock(unsigned long length);
ByteVector readBlock(size_t length) override;
/*!
* Attempts to write the block \a data at the current get pointer.
@@ -80,14 +80,14 @@ class TAGLIB_EXPORT FileStream : public IOStream {
* \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);
void writeBlock(const ByteVector &data) override;
/*!
* Insert \a data at position \a start in the file overwriting \a replace bytes of the original content.
*
* \note This method is slow since it requires rewriting all of the file after the insertion point.
*/
void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0);
void insert(const ByteVector &data, long long start = 0, size_t replace = 0) override;
/*!
* Removes a block of the file starting a \a start and continuing for \a length bytes.
@@ -95,17 +95,17 @@ class TAGLIB_EXPORT FileStream : public IOStream {
* \note This method is slow since it involves rewriting all of the file
* after the removed portion.
*/
void removeBlock(unsigned long start = 0, unsigned long length = 0);
void removeBlock(long long start = 0, size_t length = 0) override;
/*!
* Returns true if the file is read only (or if the file can not be opened).
*/
bool readOnly() const;
bool readOnly() const override;
/*!
* Since the file can currently only be opened as an argument to the constructor (sort-of by design), this returns if that open succeeded.
*/
bool isOpen() const;
bool isOpen() const override;
/*!
* Move the I/O pointer to \a offset in the file from position \a p.
@@ -113,33 +113,32 @@ class TAGLIB_EXPORT FileStream : public IOStream {
*
* \see Position
*/
void seek(long offset, Position p = Beginning);
void seek(long long offset, Position p = Beginning) override;
/*!
* Reset the end-of-file and error flags on the file.
*/
void clear();
void clear() override;
/*!
* Returns the current offset within the file.
*/
long tell() const;
long long tell() const override;
/*!
* Returns the length of the file.
*/
long length();
long long length() override;
/*!
* Truncates the file to a \a length.
*/
void truncate(long length);
void truncate(long long length) override;
protected:
/*!
* Returns the buffer size that is used for internal buffering.
*/
static unsigned int bufferSize();
static size_t bufferSize();
private:
class FileStreamPrivate;

View File

@@ -24,8 +24,9 @@
***************************************************************************/
#ifdef _WIN32
# include <memory>
# include <windows.h>
# include <tstring.h>
# include "tstring.h"
#endif
#include "tiostream.h"
@@ -49,32 +50,36 @@ std::wstring ansiToUnicode(const char *str) {
}
} // namespace
// m_name is no longer used, but kept for backward compatibility.
class FileName::FileNamePrivate {
public:
FileNamePrivate() : data(new std::wstring()) {}
FileName::FileName(const wchar_t *name) : m_name(), m_wname(name) {}
FileNamePrivate(const wchar_t *name) : data(new std::wstring(name)) {}
FileName::FileName(const char *name) : m_name(), m_wname(ansiToUnicode(name)) {}
FileNamePrivate(const char *name) : data(new std::wstring(ansiToUnicode(name))) {}
FileName::FileName(const FileName &name) : m_name(), m_wname(name.m_wname) {}
std::shared_ptr<std::wstring> data;
};
FileName::operator const wchar_t *() const {
return m_wname.c_str();
FileName::FileName(const wchar_t *name) : d(new FileNamePrivate(name)) {}
FileName::FileName(const char *name) : d(new FileNamePrivate(name)) {}
FileName::FileName(const FileName &name) : d(new FileNamePrivate()) {
*d = *name.d;
}
FileName::operator const char *() const {
return m_name.c_str();
FileName::~FileName() {
delete d;
}
const std::wstring &FileName::wstr() const {
return m_wname;
FileName &FileName::operator=(const FileName &name) {
*d = *name.d;
return *this;
}
const std::string &FileName::str() const {
return m_name;
}
String FileName::toString() const {
return String(m_wname.c_str());
const wchar_t *FileName::wstr() const {
return d->data->c_str();
}
#endif // _WIN32

View File

@@ -34,24 +34,24 @@ namespace Strawberry_TagLib {
namespace TagLib {
#ifdef _WIN32
class String;
class TAGLIB_EXPORT FileName {
public:
FileName(const wchar_t *name);
FileName(const char *name);
FileName(const FileName &name);
operator const wchar_t *() const;
operator const char *() const;
~FileName();
const std::wstring &wstr() const;
const std::string &str() const;
FileName &operator=(const FileName &name);
String toString() const;
const wchar_t *wstr() const;
private:
const std::string m_name;
const std::wstring m_wname;
class FileNamePrivate;
FileNamePrivate *d;
};
#else
typedef const char *FileName;
@@ -88,7 +88,7 @@ class TAGLIB_EXPORT IOStream {
/*!
* Reads a block of size \a length at the current get pointer.
*/
virtual ByteVector readBlock(unsigned long length) = 0;
virtual ByteVector readBlock(size_t length) = 0;
/*!
* Attempts to write the block \a data at the current get pointer.
@@ -105,14 +105,14 @@ class TAGLIB_EXPORT IOStream {
* \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;
long long start = 0, size_t replace = 0) = 0;
/*!
* Removes a block of the file starting a \a start and continuing for \a length bytes.
*
* \note This method is slow since it involves rewriting all of the file after the removed portion.
*/
virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0;
virtual void removeBlock(long long start = 0, size_t length = 0) = 0;
/*!
* Returns true if the file is read only (or if the file can not be opened).
@@ -130,7 +130,7 @@ class TAGLIB_EXPORT IOStream {
*
* \see Position
*/
virtual void seek(long offset, Position p = Beginning) = 0;
virtual void seek(long long offset, Position p = Beginning) = 0;
/*!
* Reset the end-of-stream and error flags on the stream.
@@ -140,20 +140,20 @@ class TAGLIB_EXPORT IOStream {
/*!
* Returns the current offset within the stream.
*/
virtual long tell() const = 0;
virtual long long tell() const = 0;
/*!
* Returns the length of the stream.
*/
virtual long length() = 0;
virtual long long length() = 0;
/*!
* Truncates the stream to a \a length.
*/
virtual void truncate(long length) = 0;
virtual void truncate(long long length) = 0;
private:
explicit IOStream(const IOStream&);
IOStream(const IOStream&);
IOStream &operator=(const IOStream&);
};

View File

@@ -28,6 +28,7 @@
#include "taglib.h"
#include <cstddef>
#include <list>
namespace Strawberry_TagLib {
@@ -141,7 +142,7 @@ template<class T> class List {
*
* \see isEmpty()
*/
unsigned int size() const;
size_t size() const;
/*!
* Returns whether or not the list is empty.
@@ -153,17 +154,20 @@ template<class T> class List {
/*!
* Find the first occurrence of \a value.
*/
Iterator find(const T &value);
template<class U>
Iterator find(const U &value);
/*!
* Find the first occurrence of \a value.
*/
ConstIterator find(const T &value) const;
template<class U>
ConstIterator find(const U &value) const;
/*!
* Returns true if the list contains \a value.
*/
bool contains(const T &value) const;
template<class U>
bool contains(const U &value) const;
/*!
* Erase the item at \a it from the list.
@@ -203,14 +207,14 @@ template<class T> class List {
*
* \warning This method is slow. Use iterators to loop through the list.
*/
T &operator[](unsigned int i);
T &operator[](size_t i);
/*!
* Returns a const reference to item \a i in the list.
*
* \warning This method is slow. Use iterators to loop through the list.
*/
const T &operator[](unsigned int i) const;
const T &operator[](size_t i) const;
/*!
* Make a shallow, implicitly shared, copy of \a l.

View File

@@ -36,50 +36,59 @@ namespace TagLib {
// 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.
// BIC change to RefCounter
class ListPrivateBase : public RefCounterOld {
public:
ListPrivateBase() : autoDelete(false) {}
bool autoDelete;
};
// A generic implementation
template <class T>
template <class TP> class List<T>::ListPrivate : public ListPrivateBase
template <class TP> class List<T>::ListPrivate : public RefCounter
{
public:
explicit ListPrivate() : ListPrivateBase() {}
explicit ListPrivate(const std::list<TP> &l) : ListPrivateBase(), list(l) {}
explicit ListPrivate() {}
explicit ListPrivate(const std::list<TP> &l) : list(l) {}
void clear() {
list.clear();
std::list<TP>().swap(list);
}
void setAutoDelete(bool) {}
std::list<TP> list;
};
// 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
template <class TP> class List<T>::ListPrivate<TP *> : public RefCounter
{
public:
explicit ListPrivate() : ListPrivateBase() {}
explicit ListPrivate(const std::list<TP *> &l) : ListPrivateBase(), list(l) {}
~ListPrivate() {
clear();
explicit ListPrivate() : autoDelete(false) {}
explicit ListPrivate(const std::list<TP *> &l) : list(l), autoDelete(false) {}
~ListPrivate() override {
deletePointers();
}
void clear() {
deletePointers();
std::list<TP *>().swap(list);
}
void setAutoDelete(bool del) {
autoDelete = del;
}
std::list<TP *> list;
private:
void deletePointers() {
if(autoDelete) {
typename std::list<TP *>::const_iterator it = list.begin();
for(; it != list.end(); ++it)
delete *it;
}
list.clear();
}
std::list<TP *> list;
bool autoDelete;
};
////////////////////////////////////////////////////////////////////////////////
@@ -124,60 +133,74 @@ typename List<T>::ConstIterator List<T>::end() const {
template <class T>
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) {
detach();
Iterator it = begin();
while(it != end() && *it < value)
while (it != end() && *it < value)
++it;
if(unique && it != end() && *it == value)
if (unique && it != end() && *it == value)
return *this;
insert(it, value);
return *this;
}
template <class T>
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) {
detach();
d->list.insert(d->list.end(), l.begin(), l.end());
return *this;
}
template <class T>
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) {
detach();
d->list.insert(d->list.begin(), l.begin(), l.end());
return *this;
}
template <class T>
List<T> &List<T>::clear() {
detach();
d->clear();
return *this;
}
template <class T>
unsigned int List<T>::size() const {
return static_cast<unsigned int>(d->list.size());
size_t List<T>::size() const {
return d->list.size();
}
template <class T>
@@ -186,18 +209,21 @@ bool List<T>::isEmpty() const {
}
template <class T>
typename List<T>::Iterator List<T>::find(const T &value) {
template <class U>
typename List<T>::Iterator List<T>::find(const U &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 {
template <class U>
typename List<T>::ConstIterator List<T>::find(const U &value) const {
return std::find(d->list.begin(), d->list.end(), value);
}
template <class T>
bool List<T>::contains(const T &value) const {
template <class U>
bool List<T>::contains(const U &value) const {
return std::find(d->list.begin(), d->list.end(), value) != d->list.end();
}
@@ -224,42 +250,51 @@ const T &List<T>::back() const {
template <class T>
void List<T>::setAutoDelete(bool autoDelete) {
d->autoDelete = autoDelete;
d->setAutoDelete(autoDelete);
}
template <class T>
T &List<T>::back() {
detach();
return d->list.back();
}
template <class T>
T &List<T>::operator[](unsigned int i) {
T &List<T>::operator[](size_t i) {
Iterator it = d->list.begin();
std::advance(it, i);
return *it;
}
template <class T>
const T &List<T>::operator[](unsigned int i) const {
const T &List<T>::operator[](size_t i) const {
ConstIterator it = d->list.begin();
std::advance(it, i);
return *it;
}
template <class T>
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) {
using std::swap;
using std::swap;
swap(d, l.d);
}
template <class T>
@@ -278,10 +313,12 @@ bool List<T>::operator!=(const List<T> &l) const {
template <class T>
void List<T>::detach() {
if(d->count() > 1) {
if (!d->unique()) {
d->deref();
d = new ListPrivate<T>(d->list);
}
}
}
} // namespace Strawberry_TagLib::TagLib

View File

@@ -26,6 +26,7 @@
#ifndef TAGLIB_MAP_H
#define TAGLIB_MAP_H
#include <cstddef>
#include <map>
#include "taglib.h"
@@ -41,7 +42,7 @@ namespace TagLib {
*/
template<class Key, class T> class Map {
public:
private:
#ifndef DO_NOT_DOCUMENT
# ifdef WANT_CLASS_INSTANTIATION_OF_MAP
// Some STL implementations get snippy over the use of the class keyword to distinguish different templates; Sun Studio
@@ -49,14 +50,18 @@ template<class Key, class T> class Map {
// 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;
typedef std::map<class Key, class T> MapType;
# else
typedef typename std::map<Key, T>::iterator Iterator;
typedef typename std::map<Key, T>::const_iterator ConstIterator;
typedef std::map<Key, T> MapType;
# endif
#endif
public:
#ifndef DO_NOT_DOCUMENT
typedef typename MapType::iterator Iterator;
typedef typename MapType::const_iterator ConstIterator;
#endif
/*!
* Constructs an empty Map.
*/
@@ -114,7 +119,7 @@ template<class Key, class T> class Map {
*
* \see isEmpty()
*/
unsigned int size() const;
size_t size() const;
/*!
* Returns true if the map is empty.

View File

@@ -32,19 +32,14 @@ namespace TagLib {
// public members
////////////////////////////////////////////////////////////////////////////////
// BIC change to RefCounter
template <class Key, class T>
template <class KeyP, class TP>
class Map<Key, T>::MapPrivate : public RefCounterOld {
public:
explicit MapPrivate() : RefCounterOld() {}
#ifdef WANT_CLASS_INSTANTIATION_OF_MAP
explicit MapPrivate(const std::map<class KeyP, class TP>& m) : RefCounterOld(), map(m) {}
std::map<class KeyP, class TP> map;
#else
explicit MapPrivate(const std::map<KeyP, TP>& m) : RefCounterOld(), map(m) {}
std::map<KeyP, TP> map;
#endif
class Map<Key, T>::MapPrivate : public RefCounter {
public:
explicit MapPrivate() : RefCounter() {}
explicit MapPrivate(const MapType &m) : RefCounter(), map(m) {}
MapType map;
};
template <class Key, class T>
@@ -133,8 +128,8 @@ Map<Key, T> &Map<Key,T>::erase(const Key &key) {
}
template <class Key, class T>
unsigned int Map<Key, T>::size() const {
return static_cast<unsigned int>(d->map.size());
size_t Map<Key, T>::size() const {
return d->map.size();
}
template <class Key, class T>
@@ -167,7 +162,7 @@ void Map<Key, T>::swap(Map<Key, T> &m) {
template <class Key, class T>
void Map<Key, T>::detach() {
if(d->count() > 1) {
if (!d->unique()) {
d->deref();
d = new MapPrivate<Key, T>(d->map);
}

179
3rdparty/taglib/toolkit/tpicture.cpp vendored Normal file
View File

@@ -0,0 +1,179 @@
/***************************************************************************
copyright : (C) 2015 by Maxime Leblanc
email : lblnc.maxime@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <memory>
#include <algorithm>
#include "tpicture.h"
using namespace Strawberry_TagLib::TagLib;
namespace {
struct PictureData {
explicit PictureData() : type(Picture::Other) {}
ByteVector data;
Picture::Type type;
String mime;
String description;
};
} // namespace
class Picture::PicturePrivate {
public:
explicit PicturePrivate() : data(new PictureData()) {}
std::shared_ptr<PictureData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Picture::Picture() : d(new PicturePrivate()) {}
Picture::Picture(const ByteVector &data, Type type, const String &mime, const String &description) : d(new PicturePrivate()) {
d->data->data = data;
d->data->type = type;
d->data->mime = mime;
d->data->description = description;
}
Picture::Picture(const Picture &p) : d(new PicturePrivate(*p.d)) {}
Picture::~Picture() {
delete d;
}
String Picture::description() const {
return d->data->description;
}
ByteVector Picture::data() const {
return d->data->data;
}
String Picture::mime() const {
return d->data->mime;
}
Picture::Type Picture::type() const {
return d->data->type;
}
void Picture::swap(Picture &other) {
using std::swap;
swap(d, other.d);
}
/* =========== OPERATORS =========== */
Picture &Picture::operator=(const Picture &p) {
Picture(p).swap(*this);
return *this;
}
std::ostream &operator<<(std::ostream &s, const Picture &p) {
String type;
switch (p.type()) {
case Picture::FileIcon:
type = "FileIcon";
break;
case Picture::OtherFileIcon:
type = "OtherFileIcon";
break;
case Picture::FrontCover:
type = "FrontCover";
break;
case Picture::BackCover:
type = "BackCover";
break;
case Picture::LeafletPage:
type = "LeafletPage";
break;
case Picture::Media:
type = "Media";
break;
case Picture::LeadArtist:
type = "LeadArtist";
break;
case Picture::Artist:
type = "Artist";
break;
case Picture::Conductor:
type = "Conductor";
break;
case Picture::Band:
type = "Band";
break;
case Picture::Composer:
type = "Composer";
break;
case Picture::Lyricist:
type = "Lyricist";
break;
case Picture::RecordingLocation:
type = "RecordingLocation";
break;
case Picture::DuringRecording:
type = "DuringRecording";
break;
case Picture::DuringPerformance:
type = "DuringPerformance";
break;
case Picture::MovieScreenCapture:
type = "MovieScreenCapture";
break;
case Picture::ColouredFish:
type = "ColouredFish";
break;
case Picture::Illustration:
type = "Illustration";
break;
case Picture::BandLogo:
type = "BandLogo";
break;
case Picture::PublisherLogo:
type = "PublisherLogo";
break;
default:
type = "Other";
break;
}
ByteVector displayableData = p.data().mid(0, 20).toHex();
s << "\nPicture:\n"
<< "\ttype: " << type.to8Bit() << std::endl
<< "\tdesc: " << p.description().to8Bit() << std::endl
<< "\tmime: " << p.mime().to8Bit() << std::endl
<< "\tdata: " << std::hex << displayableData << "..." << std::endl;
return s;
}

157
3rdparty/taglib/toolkit/tpicture.h vendored Normal file
View File

@@ -0,0 +1,157 @@
/***************************************************************************
copyright : (C) 2015 by Maxime Leblanc
email : lblnc.maxime@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_PICTURE_H
#define TAGLIB_PICTURE_H
#include "taglib_export.h"
#include "tbytevector.h"
#include "tmap.h"
#include "tstring.h"
namespace Strawberry_TagLib {
namespace TagLib {
class TAGLIB_EXPORT Picture {
class PicturePrivate;
public:
/*!
* The Type enum is based on types in id3v2 tags
*/
enum Type {
//! A type not enumerated below
Other = 0x00,
//! 32x32 PNG image that should be used as the file icon
FileIcon = 0x01,
//! File icon of a different size or format
OtherFileIcon = 0x02,
//! Front cover image of the album
FrontCover = 0x03,
//! Back cover image of the album
BackCover = 0x04,
//! Inside leaflet page of the album
LeafletPage = 0x05,
//! Image from the album itself
Media = 0x06,
//! Picture of the lead artist or soloist
LeadArtist = 0x07,
//! Picture of the artist or performer
Artist = 0x08,
//! Picture of the conductor
Conductor = 0x09,
//! Picture of the band or orchestra
Band = 0x0A,
//! Picture of the composer
Composer = 0x0B,
//! Picture of the lyricist or text writer
Lyricist = 0x0C,
//! Picture of the recording location or studio
RecordingLocation = 0x0D,
//! Picture of the artists during recording
DuringRecording = 0x0E,
//! Picture of the artists during performance
DuringPerformance = 0x0F,
//! Picture from a movie or video related to the track
MovieScreenCapture = 0x10,
//! Picture of a large, coloured fish
ColouredFish = 0x11,
//! Illustration related to the track
Illustration = 0x12,
//! Logo of the band or performer
BandLogo = 0x13,
//! Logo of the publisher (record company)
PublisherLogo = 0x14
};
/*!
* Constructs an empty Picture.
*/
explicit Picture();
/*!
* Constructs a Picture object base on an other Picture
*/
Picture(const Picture &p);
/*!
* Constructs a Picture object based on the \a ByteVector given.
*
* \note type, mime and description are optional
*/
explicit Picture(const ByteVector &data, Type type = Other, const String &mime = "image/", const String &description = String());
/*!
* Destroys this Picture instance.
*/
virtual ~Picture();
/*!
* Returns the mime of the picture
*/
String mime() const;
/*!
* Returns the description of the picture
*/
String description() const;
/*!
* Returns the type of the picture
*/
Type type() const;
/*!
* Returns data of the picture
*/
ByteVector data() const;
/*!
* Performs a shallow, implicitly shared, copy of \a p, overwriting the
* Picture's current data.
*/
Picture &operator=(const Picture &p);
/*!
* Exchanges the content of the Picture by the content of \a p.
*/
void swap(Picture &p);
private:
PicturePrivate *d;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \relates TagLib::Picture
*
* Send the picture to an output stream.
*/
TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::Picture &picture);
#endif // TAGLIB_PICTUREMAP_H

75
3rdparty/taglib/toolkit/tpicturemap.cpp vendored Normal file
View File

@@ -0,0 +1,75 @@
/***************************************************************************
copyright : (C) 2015 by Maxime Leblanc
email : lblnc.maxime@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "tpicturemap.h"
using namespace Strawberry_TagLib::TagLib;
PictureMap::PictureMap() : Map<Picture::Type, PictureList>() {}
PictureMap::PictureMap(const PictureList &l) : Map<Picture::Type, PictureList>() {
insert(l);
}
PictureMap::PictureMap(const Picture &p) : Map<Picture::Type, PictureList>() {
insert(p);
}
void PictureMap::insert(const Picture &p) {
PictureList list;
if (contains(p.type())) {
list = Map<Picture::Type, PictureList>::find(p.type())->second;
list.append(p);
Map<Picture::Type, PictureList>::insert(p.type(), list);
}
else {
list.append(p);
Map<Picture::Type, PictureList>::insert(p.type(), list);
}
}
void PictureMap::insert(const PictureList &l) {
for (PictureList::ConstIterator it = l.begin(); it != l.end(); ++it) {
Picture picture = (*it);
insert(picture);
}
}
PictureMap::~PictureMap() {}
std::ostream &operator<<(std::ostream &s, const PictureMap &map) {
for (PictureMap::ConstIterator it = map.begin(); it != map.end(); ++it) {
PictureList list = it->second;
for (PictureList::ConstIterator it2 = list.begin(); it2 != list.end(); ++it2)
s << *it2;
}
return s;
}

89
3rdparty/taglib/toolkit/tpicturemap.h vendored Normal file
View File

@@ -0,0 +1,89 @@
/***************************************************************************
copyright : (C) 2015 by Maxime Leblanc
email : lblnc.maxime@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_PICTUREMAP_H
#define TAGLIB_PICTUREMAP_H
#include "tlist.h"
#include "tmap.h"
#include "taglib_export.h"
#include "tpicture.h"
namespace Strawberry_TagLib {
namespace TagLib {
//! A list of pictures
typedef List<Picture> PictureList;
/// TODO: review this interface before the release of TagLib v2.x in light of
/// https://github.com/taglib/taglib/issues/734#issuecomment-214001325
/*!
* This is a spcialization of the List class with some members.
*/
class TAGLIB_EXPORT PictureMap : public Map<Picture::Type, PictureList> {
public:
/*!
* Constructs an empty PictureList.
*/
explicit PictureMap();
/*!
* Constructs a PictureMap with \a Picture.
*/
explicit PictureMap(const Picture &p);
/*!
* Constructs a PictureMap with \a PictureList as a member.
*/
explicit PictureMap(const PictureList &l);
/*!
* Destroys this PictureList instance.
*/
~PictureMap() override;
/*!
* Inserts a PictureList into the picture map
*/
void insert(const PictureList &l);
/*!
* Inserts a Picture into the picture map
*/
void insert(const Picture &p);
};
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \relates TagLib::PictureMap
*
* Send the PictureMap to on output stream
*/
TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::PictureMap &map);
#endif // TAGLIB_PICTUREMAP_H

View File

@@ -116,7 +116,7 @@ class TAGLIB_EXPORT PropertyMap : public SimplePropertyMap {
*/
PropertyMap(const SimplePropertyMap &m);
virtual ~PropertyMap();
~PropertyMap() override;
/*!
* Inserts \a values under \a key in the map.

View File

@@ -23,9 +23,7 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "taglib-config.h"
#include "trefcounter.h"
@@ -36,26 +34,26 @@
# define ATOMIC_DEC(x) (--(x))
#elif defined(HAVE_GCC_ATOMIC)
# define ATOMIC_INT int
# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
# define ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1)
# define ATOMIC_INC(x) ::__sync_add_and_fetch(&x, 1)
# define ATOMIC_DEC(x) ::__sync_sub_and_fetch(&x, 1)
#elif defined(HAVE_WIN_ATOMIC)
# if !defined(NOMINMAX)
# define NOMINMAX
# endif
# include <windows.h>
# define ATOMIC_INT long
# define ATOMIC_INC(x) InterlockedIncrement(&x)
# define ATOMIC_DEC(x) InterlockedDecrement(&x)
# define ATOMIC_INT volatile LONG
# define ATOMIC_INC(x) ::InterlockedIncrement(&x)
# define ATOMIC_DEC(x) ::InterlockedDecrement(&x)
#elif defined(HAVE_MAC_ATOMIC)
# include <libkern/OSAtomic.h>
# define ATOMIC_INT int32_t
# define ATOMIC_INC(x) OSAtomicIncrement32Barrier(&x)
# define ATOMIC_DEC(x) OSAtomicDecrement32Barrier(&x)
# define ATOMIC_INC(x) ::OSAtomicIncrement32Barrier(&x)
# define ATOMIC_DEC(x) ::OSAtomicDecrement32Barrier(&x)
#elif defined(HAVE_IA64_ATOMIC)
# include <ia64intrin.h>
# define ATOMIC_INT int
# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
# define ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1)
# define ATOMIC_INC(x) ::__sync_add_and_fetch(&x, 1)
# define ATOMIC_DEC(x) ::__sync_sub_and_fetch(&x, 1)
#else
# define ATOMIC_INT int
# define ATOMIC_INC(x) (++(x))
@@ -69,7 +67,7 @@ class RefCounter::RefCounterPrivate {
public:
RefCounterPrivate() : refCount(1) {}
volatile ATOMIC_INT refCount;
ATOMIC_INT refCount;
};
RefCounter::RefCounter() : d(new RefCounterPrivate()) {}
@@ -89,5 +87,9 @@ bool RefCounter::deref() {
int RefCounter::count() const {
return static_cast<int>(d->refCount);
}
bool RefCounter::unique() const {
return (d->refCount == 1);
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -29,23 +29,6 @@
#include "taglib_export.h"
#include "taglib.h"
#ifdef __APPLE__
# define OSATOMIC_DEPRECATED 0
# include <libkern/OSAtomic.h>
# define TAGLIB_ATOMIC_MAC
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
# define TAGLIB_ATOMIC_WIN
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) && (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64) || defined(__ia64)) && !defined(__INTEL_COMPILER)
# define TAGLIB_ATOMIC_GCC
#elif defined(__ia64) && defined(__INTEL_COMPILER)
# include <ia64intrin.h>
# define TAGLIB_ATOMIC_GCC
#endif
#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
/*!
* \internal
@@ -64,56 +47,16 @@ class TAGLIB_EXPORT RefCounter {
void ref();
bool deref();
int count() const;
bool unique() const;
private:
RefCounter(const RefCounter&);
RefCounter &operator=(const RefCounter&);
class RefCounterPrivate;
RefCounterPrivate *d;
};
// BIC this old class is needed by tlist.tcc and tmap.tcc
class RefCounterOld {
public:
explicit RefCounterOld() : refCount(1) {}
# ifdef TAGLIB_ATOMIC_MAC
void ref() {
OSAtomicIncrement32Barrier(const_cast<int32_t *>(&refCount));
}
bool deref() { return !OSAtomicDecrement32Barrier(const_cast<int32_t *>(&refCount)); }
int32_t count() { return refCount; }
private:
volatile int32_t refCount;
# elif defined(TAGLIB_ATOMIC_WIN)
void ref() {
InterlockedIncrement(&refCount);
}
bool deref() { return !InterlockedDecrement(&refCount); }
long count() { return refCount; }
private:
volatile long refCount;
# elif defined(TAGLIB_ATOMIC_GCC)
void ref() {
__sync_add_and_fetch(&refCount, 1);
}
bool deref() { return !__sync_sub_and_fetch(&refCount, 1); }
int count() { return refCount; }
private:
volatile int refCount;
# else
void ref() {
refCount++;
}
bool deref() { return !--refCount; }
int count() { return refCount; }
private:
unsigned int refCount;
# endif
};
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -23,15 +23,15 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <memory>
#include <cerrno>
#include <climits>
#include <utf8-cpp/checked.h>
#include <tdebug.h>
#include <tstringlist.h>
#include <trefcounter.h>
#include <tutils.h>
#include "tdebug.h"
#include "tstringlist.h"
#include "tutils.h"
#include "tstring.h"
@@ -41,7 +41,7 @@ using namespace Strawberry_TagLib::TagLib;
// Returns the native format of std::wstring.
String::Type wcharByteOrder() {
if (Utils::systemByteOrder() == Utils::LittleEndian)
if (Utils::systemByteOrder() == LittleEndian)
return String::UTF16LE;
else
return String::UTF16BE;
@@ -143,21 +143,29 @@ void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t
namespace Strawberry_TagLib {
namespace TagLib {
class String::StringPrivate : public RefCounter {
class String::StringPrivate {
public:
StringPrivate() {}
StringPrivate() : data(new std::wstring()) {}
/*!
* Stores string in UTF-16. The byte order depends on the CPU endian.
*/
Strawberry_TagLib::TagLib::wstring data;
std::shared_ptr<std::wstring> data;
/*!
* This is only used to hold the the most recent value of toCString().
*/
std::string cstring;
std::shared_ptr<std::string> cstring;
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
size_t String::npos() {
return std::wstring::npos;
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
@@ -165,52 +173,40 @@ class String::StringPrivate : public RefCounter {
String::String() : d(new StringPrivate()) {
}
String::String(const String &s) : d(s.d) {
d->ref();
}
String::String(const String &s) : d(new StringPrivate(*s.d)) {}
String::String(const std::string &s, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, s.c_str(), s.length());
copyFromLatin1(*d->data, s.c_str(), s.length());
else if (t == String::UTF8)
copyFromUTF8(d->data, s.c_str(), s.length());
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()) {
String::String(const std::wstring &s, Type t) : d(new StringPrivate()) {
if (t == UTF16 || t == UTF16BE || t == UTF16LE) {
// This looks ugly but needed for the compatibility with TagLib1.8.
// Should be removed in TabLib2.0.
if (t == UTF16BE)
t = wcharByteOrder();
else if (t == UTF16LE)
t = (wcharByteOrder() == UTF16LE ? UTF16BE : UTF16LE);
if (t == UTF16Native)
t = wcharByteOrder();
copyFromUTF16(d->data, s.c_str(), s.length(), t);
}
if (t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(*d->data, s.c_str(), s.length(), t);
else {
debug("String::String() -- TagLib::wstring should not contain Latin1 or UTF-8.");
debug("String::String() -- std::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.
if (t == UTF16BE)
t = wcharByteOrder();
else if (t == UTF16LE)
t = (wcharByteOrder() == UTF16LE ? UTF16BE : UTF16LE);
if (t == UTF16Native)
t = wcharByteOrder();
copyFromUTF16(d->data, s, ::wcslen(s), t);
}
if (t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(*d->data, s, ::wcslen(s), t);
else {
debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8.");
}
@@ -220,9 +216,9 @@ String::String(const wchar_t *s, Type t) : d(new StringPrivate()) {
String::String(const char *s, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, s, ::strlen(s));
copyFromLatin1(*d->data, s, ::strlen(s));
else if (t == String::UTF8)
copyFromUTF8(d->data, s, ::strlen(s));
copyFromUTF8(*d->data, s, ::strlen(s));
else {
debug("String::String() -- const char * should not contain UTF16.");
}
@@ -231,8 +227,11 @@ String::String(const char *s, Type t) : d(new StringPrivate()) {
String::String(wchar_t c, Type t) : d(new StringPrivate()) {
if (t == UTF16Native)
t = wcharByteOrder();
if (t == UTF16 || t == UTF16BE || t == UTF16LE)
copyFromUTF16(d->data, &c, 1, t);
copyFromUTF16(*d->data, &c, 1, t);
else {
debug("String::String() -- wchar_t should not contain Latin1 or UTF-8.");
}
@@ -242,9 +241,9 @@ String::String(wchar_t c, Type t) : d(new StringPrivate()) {
String::String(char c, Type t) : d(new StringPrivate()) {
if (t == Latin1)
copyFromLatin1(d->data, &c, 1);
copyFromLatin1(*d->data, &c, 1);
else if (t == String::UTF8)
copyFromUTF8(d->data, &c, 1);
copyFromUTF8(*d->data, &c, 1);
else {
debug("String::String() -- char should not contain UTF16.");
}
@@ -256,23 +255,25 @@ String::String(const ByteVector &v, Type t) : d(new StringPrivate()) {
if (v.isEmpty())
return;
if (t == UTF16Native)
t = wcharByteOrder();
if (t == Latin1)
copyFromLatin1(d->data, v.data(), v.size());
copyFromLatin1(*d->data, v.data(), v.size());
else if (t == UTF8)
copyFromUTF8(d->data, v.data(), v.size());
copyFromUTF8(*d->data, v.data(), v.size());
else
copyFromUTF16(d->data, v.data(), v.size() / 2, t);
copyFromUTF16(*d->data, v.data(), v.size() / 2, t);
// If we hit a null in the ByteVector, shrink the string again.
d->data.resize(::wcslen(d->data.c_str()));
d->data->resize(::wcslen(d->data->c_str()));
}
////////////////////////////////////////////////////////////////////////////////
String::~String() {
if (d->deref())
delete d;
delete d;
}
std::string String::to8Bit(bool unicode) const {
@@ -282,51 +283,51 @@ std::string String::to8Bit(bool unicode) const {
}
Strawberry_TagLib::TagLib::wstring String::toWString() const {
return d->data;
const std::wstring &String::toWString() const {
return *d->data;
}
const char *String::toCString(bool unicode) const {
d->cstring = to8Bit(unicode);
return d->cstring.c_str();
d->cstring.reset(new std::string(to8Bit(unicode)));
return d->cstring->c_str();
}
const wchar_t *String::toCWString() const {
return d->data.c_str();
return d->data->c_str();
}
String::Iterator String::begin() {
detach();
return d->data.begin();
return d->data->begin();
}
String::ConstIterator String::begin() const {
return d->data.begin();
return d->data->begin();
}
String::Iterator String::end() {
detach();
return d->data.end();
return d->data->end();
}
String::ConstIterator String::end() const {
return d->data.end();
return d->data->end();
}
int String::find(const String &s, int offset) const {
return static_cast<int>(d->data.find(s.d->data, offset));
size_t String::find(const String &s, size_t offset) const {
return d->data->find(*s.d->data, offset);
}
int String::rfind(const String &s, int offset) const {
return static_cast<int>(d->data.rfind(s.d->data, offset));
size_t String::rfind(const String &s, size_t offset) const {
return d->data->rfind(*s.d->data, offset);
}
StringList String::split(const String &separator) const {
StringList list;
for (int index = 0;;) {
int sep = find(separator, index);
if (sep < 0) {
for (size_t index = 0;;) {
const size_t sep = find(separator, index);
if (sep == npos()) {
list.append(substr(index, size() - index));
break;
}
@@ -346,19 +347,18 @@ bool String::startsWith(const String &s) const {
return substr(0, s.length()) == s;
}
String String::substr(unsigned int position, unsigned int n) const {
String String::substr(size_t position, size_t length) const {
if (position == 0 && n >= size())
if (position == 0 && length >= size())
return *this;
else
return String(d->data.substr(position, n));
return String(d->data->substr(position, length));
}
String &String::append(const String &s) {
detach();
d->data += s.d->data;
*d->data += *s.d->data;
return *this;
}
@@ -373,29 +373,29 @@ String &String::clear() {
String String::upper() const {
String s;
s.d->data.reserve(size());
s.d->data->reserve(size());
for (ConstIterator it = begin(); it != end(); ++it) {
if (*it >= 'a' && *it <= 'z')
s.d->data.push_back(*it + 'A' - 'a');
s.d->data->push_back(*it + 'A' - 'a');
else
s.d->data.push_back(*it);
s.d->data->push_back(*it);
}
return s;
}
unsigned int String::size() const {
return static_cast<unsigned int>(d->data.size());
size_t String::size() const {
return d->data->size();
}
unsigned int String::length() const {
size_t String::length() const {
return size();
}
bool String::isEmpty() const {
return d->data.empty();
return d->data->empty();
}
ByteVector String::data(Type t) const {
@@ -472,7 +472,7 @@ ByteVector String::data(Type t) const {
int String::toInt(bool *ok) const {
const wchar_t *begin = d->data.c_str();
const wchar_t *begin = d->data->c_str();
wchar_t *end;
errno = 0;
const long value = ::wcstol(begin, &end, 10);
@@ -491,12 +491,12 @@ 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);
const size_t pos1 = d->data->find_first_not_of(WhiteSpaceChars);
if (pos1 == std::wstring::npos)
return String();
const size_t pos2 = d->data.find_last_not_of(WhiteSpaceChars);
return substr(static_cast<unsigned int>(pos1), static_cast<unsigned int>(pos2 - pos1 + 1));
const size_t pos2 = d->data->find_last_not_of(WhiteSpaceChars);
return substr(pos1, pos2 - pos1 + 1);
}
@@ -524,17 +524,17 @@ String String::number(int n) { // static
return Utils::formatString("%d", n);
}
wchar_t &String::operator[](int i) {
wchar_t &String::operator[](size_t i) {
detach();
return d->data[i];
return (*d->data)[i];
}
const wchar_t &String::operator[](int i) const {
return d->data[i];
const wchar_t &String::operator[](size_t i) const {
return (*d->data)[i];
}
bool String::operator==(const String &s) const {
return (d == s.d || d->data == s.d->data);
return (d->data == s.d->data || *d->data == *s.d->data);
}
bool String::operator!=(const String &s) const {
@@ -558,7 +558,7 @@ bool String::operator!=(const char *s) const {
}
bool String::operator==(const wchar_t *s) const {
return (d->data == s);
return (*d->data == s);
}
bool String::operator!=(const wchar_t *s) const {
@@ -568,14 +568,14 @@ bool String::operator!=(const wchar_t *s) const {
String &String::operator+=(const String &s) {
detach();
d->data += s.d->data;
*d->data += *s.d->data;
return *this;
}
String &String::operator+=(const wchar_t *s) {
detach();
d->data += s;
*d->data += s;
return *this;
}
@@ -583,21 +583,22 @@ String &String::operator+=(const char *s) {
detach();
for (int i = 0; s[i] != 0; i++)
d->data += static_cast<unsigned char>(s[i]);
*d->data += static_cast<unsigned char>(s[i]);
return *this;
}
String &String::operator+=(wchar_t c) {
detach();
d->data += c;
*d->data += c;
return *this;
}
String &String::operator+=(char c) {
detach();
d->data += static_cast<unsigned char>(c);
*d->data += static_cast<unsigned char>(c);
return *this;
}
@@ -611,7 +612,7 @@ String &String::operator=(const std::string &s) {
return *this;
}
String &String::operator=(const wstring &s) {
String &String::operator=(const std::wstring &s) {
String(s).swap(*this);
return *this;
}
@@ -627,7 +628,7 @@ String &String::operator=(char c) {
}
String &String::operator=(wchar_t c) {
String(c, wcharByteOrder()).swap(*this);
String(c).swap(*this);
return *this;
}
@@ -648,7 +649,7 @@ void String::swap(String &s) {
}
bool String::operator<(const String &s) const {
return (d->data < s.d->data);
return (*d->data < *s.d->data);
}
////////////////////////////////////////////////////////////////////////////////
@@ -656,30 +657,27 @@ bool String::operator<(const String &s) const {
////////////////////////////////////////////////////////////////////////////////
void String::detach() {
if (d->count() > 1)
String(d->data.c_str()).swap(*this);
if (!d->data.unique())
String(d->data->c_str()).swap(*this);
}
} // namespace TagLib
} // namespace Strawberry_TagLib
////////////////////////////////////////////////////////////////////////////////
// related non-member functions
////////////////////////////////////////////////////////////////////////////////
const Strawberry_TagLib::TagLib::String operator+(const Strawberry_TagLib::TagLib::String &s1, const Strawberry_TagLib::TagLib::String &s2) {
const String operator+(const String &s1, const String &s2) {
Strawberry_TagLib::TagLib::String s(s1);
s.append(s2);
return s;
}
const Strawberry_TagLib::TagLib::String operator+(const char *s1, const Strawberry_TagLib::TagLib::String &s2) {
const String operator+(const char *s1, const String &s2) {
Strawberry_TagLib::TagLib::String s(s1);
s.append(s2);
return s;
}
const Strawberry_TagLib::TagLib::String operator+(const Strawberry_TagLib::TagLib::String &s1, const char *s2) {
const String operator+(const String &s1, const char *s2) {
Strawberry_TagLib::TagLib::String s(s1);
s.append(s2);
return s;
@@ -689,3 +687,7 @@ std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::Strin
s << str.to8Bit();
return s;
}
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -69,7 +69,7 @@ class StringList;
/*!
* 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.
* For storage it uses std::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.
@@ -83,8 +83,8 @@ class StringList;
class TAGLIB_EXPORT String {
public:
#ifndef DO_NOT_DOCUMENT
typedef Strawberry_TagLib::TagLib::wstring::iterator Iterator;
typedef Strawberry_TagLib::TagLib::wstring::const_iterator ConstIterator;
typedef std::wstring::iterator Iterator;
typedef std::wstring::const_iterator ConstIterator;
#endif
/**
@@ -101,7 +101,7 @@ class TAGLIB_EXPORT String {
*/
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.
*/
UTF16BE = 2,
/*!
@@ -111,7 +111,11 @@ class TAGLIB_EXPORT String {
/*!
* UTF16 <i>little endian</i>. 16 bit characters.
*/
UTF16LE = 4
UTF16LE = 4,
/*!
* UTF16 in the <i>native byte order</i> of the system. 16 bit characters.
*/
UTF16Native = 5
};
/*!
@@ -135,19 +139,20 @@ class TAGLIB_EXPORT String {
/*!
* 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.
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or UTF16LE,
* when used with other codecs it will simply print a warning and exit.
* UTF16BE or UTF16LE is automatically chosen as default according to the CPU byte order
*/
String(const wstring &s, Type t = UTF16BE);
String(const std::wstring &s, Type t = UTF16Native);
/*!
* 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.
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or UTF16LE,
* when used with other codecs it will simply print a warning and exit.
* UTF16BE or UTF16LE is automatically chosen as default according to the CPU byte order
*/
String(const wchar_t *s, Type t = UTF16BE);
String(const wchar_t *s, Type t = UTF16Native);
/*!
* Makes a deep copy of the data in \a c.
@@ -158,8 +163,12 @@ class TAGLIB_EXPORT String {
/*!
* Makes a deep copy of the data in \a c.
*
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or UTF16LE,
* when used with other codecs it will simply print a warning and exit.
* UTF16BE or UTF16LE is automatically chosen as default according to the CPU byte order
*/
String(wchar_t c, Type t = Latin1);
String(wchar_t c, Type t = UTF16Native);
/*!
* Makes a deep copy of the data in \a s.
@@ -192,7 +201,7 @@ class TAGLIB_EXPORT String {
*
* \see toCWString()
*/
wstring toWString() const;
const std::wstring &toWString() const;
/*!
* Creates and returns a standard C-style (null-terminated) version of this String.
@@ -246,16 +255,16 @@ class TAGLIB_EXPORT String {
/*!
* Finds the first occurrence of pattern \a s in this string starting from \a offset.
* If the pattern is not found, -1 is returned.
* If the pattern is not found, \a npos is returned.
*/
int find(const String &s, int offset = 0) const;
size_t find(const String &s, size_t 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.
* If the pattern is not found, \a npos is returned.
*/
int rfind(const String &s, int offset = -1) const;
size_t rfind(const String &s, size_t offset = npos()) const;
/*!
* Splits the string on each occurrence of \a separator.
@@ -270,7 +279,7 @@ class TAGLIB_EXPORT String {
/*!
* Extract a substring from this string starting at \a position and continuing for \a n characters.
*/
String substr(unsigned int position, unsigned int n = 0xffffffff) const;
String substr(size_t position, size_t n = npos()) const;
/*!
* Append \a s to the current string and return a reference to the current string.
@@ -292,17 +301,15 @@ class TAGLIB_EXPORT String {
/*!
* Returns the size of the string.
*/
unsigned int size() const;
size_t size() const;
/*!
* Returns the length of the string. Equivalent to size().
*/
unsigned int length() const;
size_t length() const;
/*!
* Returns true if the string is empty.
*
* \see isNull()
*/
bool isEmpty() const;
@@ -347,12 +354,12 @@ class TAGLIB_EXPORT String {
/*!
* Returns a reference to the character at position \a i.
*/
wchar_t &operator[](int i);
wchar_t &operator[](size_t i);
/*!
* Returns a const reference to the character at position \a i.
*/
const wchar_t &operator[](int i) const;
const wchar_t &operator[](size_t i) const;
/*!
* Compares each character of the String with each character of \a s and returns true if the strings match.
@@ -422,7 +429,7 @@ class TAGLIB_EXPORT String {
/*!
* Performs a deep copy of the data in \a s.
*/
String &operator=(const wstring &s);
String &operator=(const std::wstring &s);
/*!
* Performs a deep copy of the data in \a s.
@@ -460,6 +467,13 @@ class TAGLIB_EXPORT String {
*/
bool operator<(const String &s) const;
/*!
* Returns a special value used for \a length parameter in String's member
* functions, means "until the end of the string".
* As a return value, it is usually used to indicate no matches.
*/
static size_t npos();
protected:
/*!
* If this String is being shared via implicit sharing, do a deep copy of the data and separate from the shared members.
@@ -472,9 +486,6 @@ class TAGLIB_EXPORT String {
StringPrivate *d;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \relates TagLib::String
*
@@ -504,4 +515,7 @@ TAGLIB_EXPORT const Strawberry_TagLib::TagLib::String operator+(const Strawberry
*/
TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::String &str);
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -0,0 +1,30 @@
/***************************************************************************
copyright : (C) 2012 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "tstringhandler.h"
Strawberry_TagLib::TagLib::StringHandler::StringHandler() {}
Strawberry_TagLib::TagLib::StringHandler::~StringHandler() {}

View File

@@ -0,0 +1,72 @@
/***************************************************************************
copyright : (C) 2012 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_STRINGHANDLER_H
#define TAGLIB_STRINGHANDLER_H
#include "tstring.h"
#include "tbytevector.h"
#include "taglib_export.h"
namespace Strawberry_TagLib {
namespace TagLib {
//! A abstraction for the string to data encoding.
/*!
* ID3v1, ID3v2 and RIFF Info tag sometimes store strings in local encodings
* encodings instead of ISO-8859-1 (Latin1), such as Windows-1252 for western
* languages, Shift_JIS for Japanese and so on. However, TagLib only supports
* genuine ISO-8859-1 by default.
*
* Here is an option to read and write tags in your preferrd encoding
* by subclassing this class, reimplementing parse() and render() and setting
* your reimplementation as the default with ID3v1::Tag::setStringHandler(),
* ID3v2::Tag::setStringHandler() or Info::Tag::setStringHandler().
*
* \see ID3v1::Tag::setStringHandler()
* \see ID3v2::Tag::setStringHandler()
* \see Info::Tag::setStringHandler()
*/
class TAGLIB_EXPORT StringHandler {
public:
explicit StringHandler();
virtual ~StringHandler();
/*!
* Decode a string from \a data.
*/
virtual String parse(const ByteVector &data) const = 0;
/*!
* Encode a ByteVector with the data from \a s.
*/
virtual ByteVector render(const String &s) const = 0;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -27,9 +27,6 @@
using namespace Strawberry_TagLib::TagLib;
class StringListPrivate {
};
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
@@ -38,8 +35,8 @@ StringList StringList::split(const String &s, const String &pattern) {
StringList l;
int previousOffset = 0;
for (int offset = s.find(pattern); offset != -1; offset = s.find(pattern, offset + 1)) {
size_t previousOffset = 0;
for (size_t offset = s.find(pattern); offset != String::npos(); offset = s.find(pattern, offset + 1)) {
l.append(s.substr(previousOffset, offset - previousOffset));
previousOffset = offset + 1;
}
@@ -54,9 +51,11 @@ StringList StringList::split(const String &s, const String &pattern) {
// public members
////////////////////////////////////////////////////////////////////////////////
StringList::StringList() : d(nullptr) {}
StringList::StringList() {}
StringList::StringList(const String &s) : d(nullptr) {
StringList::StringList(const StringList &l) : List<String>(l) {}
StringList::StringList(const String &s) {
append(s);
}
@@ -69,8 +68,6 @@ StringList::StringList(const ByteVectorList &bl, String::Type t) {
}
StringList::~StringList() {}
String StringList::toString(const String &separator) const {
String s;
@@ -103,11 +100,16 @@ StringList &StringList::append(const StringList &l) {
}
StringList &StringList::operator=(const StringList &l) {
List<String>::operator=(l);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
// related functions
////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &s, const StringList &l) {
std::ostream &Strawberry_TagLib::TagLib::operator<<(std::ostream &s, const StringList &l) {
s << l.toString();
return s;
}

View File

@@ -53,7 +53,7 @@ class TAGLIB_EXPORT StringList : public List<String> {
* Make a shallow, implicitly shared, copy of \a l.
* Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage.
*/
StringList(const StringList &l) = default;
StringList(const StringList &l);
/*!
* Constructs a StringList with \a s as a member.
@@ -68,11 +68,6 @@ class TAGLIB_EXPORT StringList : public List<String> {
*/
StringList(const ByteVectorList &bl, String::Type t = String::Latin1);
/*!
* Destroys this StringList instance.
*/
virtual ~StringList();
/*!
* Concatenate the list of strings into one string separated by \a separator.
*/
@@ -88,24 +83,26 @@ class TAGLIB_EXPORT StringList : public List<String> {
*/
StringList &append(const StringList &l);
/*!
* Make a shallow, implicitly shared, copy of \a l.
* Because this is implicitly shared, this method is lightweight and suitable for pass-by-value usage.
*/
StringList &operator=(const StringList &l);
/*!
* Splits the String \a s into several strings at \a pattern.
* This will not include the pattern in the returned strings.
*/
static StringList split(const String &s, const String &pattern);
private:
class StringListPrivate;
StringListPrivate *d;
};
} // namespace TagLib
} // namespace Strawberry_TagLib
/*!
* \related Strawberry_TagLib::TagLib::StringList
* Send the StringList to an output stream.
*/
std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::StringList &l);
TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const Strawberry_TagLib::TagLib::StringList &l);
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -30,9 +30,7 @@
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
#include "taglib-config.h"
# if defined(HAVE_MSC_BYTESWAP)
# include <cstdlib>
@@ -175,7 +173,7 @@ inline String formatString(const char *format, ...) {
// The last resort. May cause a buffer overflow.
length = vsprintf(buf, format, args);
if (length >= (int)BufferSize) {
if (length >= BufferSize) {
debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
length = -1;
}
@@ -190,16 +188,6 @@ inline String formatString(const char *format, ...) {
return String();
}
/*!
* The types of byte order of the running system.
*/
enum ByteOrder {
//! Little endian systems.
LittleEndian,
//! Big endian systems.
BigEndian
};
/*!
* Returns the byte order of the system.
*/

View File

@@ -23,14 +23,12 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "taglib-config.h"
#ifdef HAVE_ZLIB
# include <zlib.h>
# include <tstring.h>
# include <tdebug.h>
# include "tstring.h"
# include "tdebug.h"
#endif
#include "tzlib.h"