strawberry-audio-player-win.../3rdparty/taglib/ape/apeitem.cpp

278 lines
6.4 KiB
C++
Raw Normal View History

2018-05-10 15:29:28 +02:00
/***************************************************************************
copyright : (C) 2004 by Allan Sandfeld Jensen
email : kde@carewolf.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 <tbytevectorlist.h>
#include <tdebug.h>
#include "apeitem.h"
using namespace Strawberry_TagLib::TagLib;
2018-05-10 15:29:28 +02:00
using namespace APE;
2020-06-13 19:02:42 +02:00
class APE::Item::ItemPrivate {
public:
ItemPrivate() : type(Text), readOnly(false) {}
2018-05-10 15:29:28 +02:00
Item::ItemTypes type;
String key;
ByteVector value;
StringList text;
bool readOnly;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Item::Item() : d(new ItemPrivate()) {}
2018-05-10 15:29:28 +02:00
2020-06-13 19:02:42 +02:00
APE::Item::Item(const String &key, const StringList &values) : d(new ItemPrivate()) {
2018-05-10 15:29:28 +02:00
d->key = key;
d->text = values;
}
2020-06-13 19:02:42 +02:00
APE::Item::Item(const String &key, const ByteVector &value, bool binary) : d(new ItemPrivate()) {
2018-05-10 15:29:28 +02:00
d->key = key;
2020-06-13 19:02:42 +02:00
if (binary) {
2018-05-10 15:29:28 +02:00
d->type = Binary;
d->value = value;
}
else {
d->text.append(value);
}
}
APE::Item::Item(const Item &item) : d(new ItemPrivate(*item.d)) {}
2020-06-13 19:02:42 +02:00
APE::Item::~Item() {
2018-05-10 15:29:28 +02:00
delete d;
}
2020-06-13 19:02:42 +02:00
Item &APE::Item::operator=(const Item &item) {
2018-05-10 15:29:28 +02:00
Item(item).swap(*this);
return *this;
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::swap(Item &item) {
2018-05-10 15:29:28 +02:00
using std::swap;
swap(d, item.d);
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::setReadOnly(bool readOnly) {
2018-05-10 15:29:28 +02:00
d->readOnly = readOnly;
}
2020-06-13 19:02:42 +02:00
bool APE::Item::isReadOnly() const {
2018-05-10 15:29:28 +02:00
return d->readOnly;
}
2020-06-14 18:58:24 +02:00
void APE::Item::setType(APE::Item::ItemTypes type) {
d->type = type;
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
APE::Item::ItemTypes APE::Item::type() const {
2018-05-10 15:29:28 +02:00
return d->type;
}
2020-06-13 19:02:42 +02:00
String APE::Item::key() const {
2018-05-10 15:29:28 +02:00
return d->key;
}
2020-06-13 19:02:42 +02:00
ByteVector APE::Item::binaryData() const {
2018-05-10 15:29:28 +02:00
return d->value;
}
2020-06-13 19:02:42 +02:00
void APE::Item::setBinaryData(const ByteVector &value) {
2018-05-10 15:29:28 +02:00
d->type = Binary;
d->value = value;
d->text.clear();
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::setKey(const String &key) {
2018-05-10 15:29:28 +02:00
d->key = key;
}
2020-06-13 19:02:42 +02:00
void APE::Item::setValue(const String &value) {
2018-05-10 15:29:28 +02:00
d->type = Text;
d->text = value;
d->value.clear();
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::setValues(const StringList &value) {
2018-05-10 15:29:28 +02:00
d->type = Text;
d->text = value;
d->value.clear();
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::appendValue(const String &value) {
2018-05-10 15:29:28 +02:00
d->type = Text;
d->text.append(value);
d->value.clear();
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::appendValues(const StringList &values) {
2018-05-10 15:29:28 +02:00
d->type = Text;
d->text.append(values);
d->value.clear();
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
int APE::Item::size() const {
2018-05-10 15:29:28 +02:00
int result = 8 + d->key.size() + 1;
2020-06-13 19:02:42 +02:00
switch (d->type) {
2018-05-10 15:29:28 +02:00
case Text:
2020-06-13 19:02:42 +02:00
if (!d->text.isEmpty()) {
2018-05-10 15:29:28 +02:00
StringList::ConstIterator it = d->text.begin();
result += it->data(String::UTF8).size();
it++;
2020-06-13 19:02:42 +02:00
for (; it != d->text.end(); ++it)
2018-05-10 15:29:28 +02:00
result += 1 + it->data(String::UTF8).size();
}
break;
case Binary:
case Locator:
result += d->value.size();
break;
}
return result;
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
StringList APE::Item::toStringList() const {
2018-05-10 15:29:28 +02:00
return d->text;
}
2020-06-13 19:02:42 +02:00
StringList APE::Item::values() const {
2018-05-10 15:29:28 +02:00
return d->text;
}
2020-06-13 19:02:42 +02:00
String APE::Item::toString() const {
2020-06-13 19:02:42 +02:00
if (d->type == Text && !isEmpty())
2018-05-10 15:29:28 +02:00
return d->text.front();
else
return String();
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
bool APE::Item::isEmpty() const {
2020-06-13 19:02:42 +02:00
switch (d->type) {
2018-05-10 15:29:28 +02:00
case Text:
2020-06-13 19:02:42 +02:00
if (d->text.isEmpty())
2018-05-10 15:29:28 +02:00
return true;
2020-06-13 19:02:42 +02:00
if (d->text.size() == 1 && d->text.front().isEmpty())
2018-05-10 15:29:28 +02:00
return true;
return false;
case Binary:
case Locator:
return d->value.isEmpty();
default:
return false;
}
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
void APE::Item::parse(const ByteVector &data) {
2018-05-10 15:29:28 +02:00
// 11 bytes is the minimum size for an APE item
2020-06-13 19:02:42 +02:00
if (data.size() < 11) {
2018-05-10 15:29:28 +02:00
debug("APE::Item::parse() -- no data in item");
return;
}
2020-06-13 19:02:42 +02:00
const unsigned int valueLength = data.toUInt(0, false);
const unsigned int flags = data.toUInt(4, false);
2018-05-10 15:29:28 +02:00
// An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8.
// We assume that the validity of the given key has been checked.
d->key = String(&data[8], String::Latin1);
const ByteVector value = data.mid(8 + d->key.size() + 1, valueLength);
setReadOnly(flags & 1);
setType(ItemTypes((flags >> 1) & 3));
2020-06-13 19:02:42 +02:00
if (Text == d->type)
2018-05-10 15:29:28 +02:00
d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
else
d->value = value;
2018-05-10 15:29:28 +02:00
}
2020-06-13 19:02:42 +02:00
ByteVector APE::Item::render() const {
2018-05-10 15:29:28 +02:00
ByteVector data;
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
ByteVector value;
2020-06-13 19:02:42 +02:00
if (isEmpty())
2018-05-10 15:29:28 +02:00
return data;
2020-06-13 19:02:42 +02:00
if (d->type == Text) {
2018-05-10 15:29:28 +02:00
StringList::ConstIterator it = d->text.begin();
value.append(it->data(String::UTF8));
it++;
2020-06-13 19:02:42 +02:00
for (; it != d->text.end(); ++it) {
2018-05-10 15:29:28 +02:00
value.append('\0');
value.append(it->data(String::UTF8));
}
d->value = value;
}
else
value.append(d->value);
data.append(ByteVector::fromUInt(value.size(), false));
data.append(ByteVector::fromUInt(flags, false));
data.append(d->key.data(String::Latin1));
data.append(ByteVector('\0'));
data.append(value);
return data;
2018-05-10 15:29:28 +02:00
}