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

View File

@@ -23,9 +23,10 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include <trefcounter.h>
#include <memory>
#include "taglib.h"
#include "tdebug.h"
#include "asfattribute.h"
#include "asffile.h"
@@ -33,10 +34,11 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::Attribute::AttributePrivate : public RefCounter {
public:
AttributePrivate() : pictureValue(ASF::Picture::fromInvalid()), numericValue(0), stream(0), language(0) {}
AttributeTypes type;
namespace {
struct AttributeData {
explicit AttributeData() : numericValue(0), stream(0), language(0) {}
ASF::Attribute::AttributeTypes type;
String stringValue;
ByteVector byteVectorValue;
ASF::Picture pictureValue;
@@ -44,52 +46,60 @@ class ASF::Attribute::AttributePrivate : public RefCounter {
int stream;
int language;
};
} // namespace
class ASF::Attribute::AttributePrivate {
public:
AttributePrivate() : data(new AttributeData()) {
data->pictureValue = ASF::Picture::fromInvalid();
}
std::shared_ptr<AttributeData> data;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Attribute::Attribute() : d(new AttributePrivate()) {
d->type = UnicodeType;
d->data->type = UnicodeType;
}
ASF::Attribute::Attribute(const ASF::Attribute &other) : d(other.d) {
d->ref();
}
ASF::Attribute::Attribute(const ASF::Attribute &other) : d(new AttributePrivate(*other.d)) {}
ASF::Attribute::Attribute(const String &value) : d(new AttributePrivate()) {
d->type = UnicodeType;
d->stringValue = value;
d->data->type = UnicodeType;
d->data->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value) : d(new AttributePrivate()) {
d->type = BytesType;
d->byteVectorValue = value;
d->data->type = BytesType;
d->data->byteVectorValue = value;
}
ASF::Attribute::Attribute(const ASF::Picture &value) : d(new AttributePrivate()) {
d->type = BytesType;
d->pictureValue = value;
d->data->type = BytesType;
d->data->pictureValue = value;
}
ASF::Attribute::Attribute(unsigned int value) : d(new AttributePrivate()) {
d->type = DWordType;
d->numericValue = value;
d->data->type = DWordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(unsigned long long value) : d(new AttributePrivate()) {
d->type = QWordType;
d->numericValue = value;
d->data->type = QWordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(unsigned short value) : d(new AttributePrivate()) {
d->type = WordType;
d->numericValue = value;
d->data->type = WordType;
d->data->numericValue = value;
}
ASF::Attribute::Attribute(bool value) : d(new AttributePrivate()) {
d->type = BoolType;
d->numericValue = value;
d->data->type = BoolType;
d->data->numericValue = value;
}
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other) {
@@ -104,54 +114,54 @@ void ASF::Attribute::swap(Attribute &other) {
}
ASF::Attribute::~Attribute() {
if (d->deref())
delete d;
delete d;
}
ASF::Attribute::AttributeTypes ASF::Attribute::type() const {
return d->type;
return d->data->type;
}
String ASF::Attribute::toString() const {
return d->stringValue;
return d->data->stringValue;
}
ByteVector ASF::Attribute::toByteVector() const {
if (d->pictureValue.isValid())
return d->pictureValue.render();
return d->byteVectorValue;
if (d->data->pictureValue.isValid())
return d->data->pictureValue.render();
return d->data->byteVectorValue;
}
unsigned short ASF::Attribute::toBool() const {
return d->numericValue ? 1 : 0;
return d->data->numericValue ? 1 : 0;
}
unsigned short ASF::Attribute::toUShort() const {
return static_cast<unsigned short>(d->numericValue);
return static_cast<unsigned short>(d->data->numericValue);
}
unsigned int ASF::Attribute::toUInt() const {
return static_cast<unsigned int>(d->numericValue);
return static_cast<unsigned int>(d->data->numericValue);
}
unsigned long long ASF::Attribute::toULongLong() const {
return static_cast<unsigned long long>(d->numericValue);
return static_cast<unsigned long long>(d->data->numericValue);
}
ASF::Picture ASF::Attribute::toPicture() const {
return d->pictureValue;
return d->data->pictureValue;
}
String ASF::Attribute::parse(ASF::File &f, int kind) {
unsigned int size, nameLength;
String name;
d->pictureValue = Picture::fromInvalid();
d->data->pictureValue = Picture::fromInvalid();
// extended content descriptor
if (kind == 0) {
nameLength = readWORD(&f);
name = readString(&f, nameLength);
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
d->data->type = ASF::Attribute::AttributeTypes(readWORD(&f));
size = readWORD(&f);
}
// metadata & metadata library
@@ -159,11 +169,11 @@ String ASF::Attribute::parse(ASF::File &f, int kind) {
int temp = readWORD(&f);
// metadata library
if (kind == 2) {
d->language = temp;
d->data->language = temp;
}
d->stream = readWORD(&f);
d->data->stream = readWORD(&f);
nameLength = readWORD(&f);
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
d->data->type = ASF::Attribute::AttributeTypes(readWORD(&f));
size = readDWORD(&f);
name = readString(&f, nameLength);
}
@@ -172,42 +182,42 @@ String ASF::Attribute::parse(ASF::File &f, int kind) {
debug("ASF::Attribute::parse() -- Value larger than 64kB");
}
switch (d->type) {
switch (d->data->type) {
case WordType:
d->numericValue = readWORD(&f);
d->data->numericValue = readWORD(&f);
break;
case BoolType:
if (kind == 0) {
d->numericValue = (readDWORD(&f) != 0);
d->data->numericValue = (readDWORD(&f) != 0);
}
else {
d->numericValue = (readWORD(&f) != 0);
d->data->numericValue = (readWORD(&f) != 0);
}
break;
case DWordType:
d->numericValue = readDWORD(&f);
d->data->numericValue = readDWORD(&f);
break;
case QWordType:
d->numericValue = readQWORD(&f);
d->data->numericValue = readQWORD(&f);
break;
case UnicodeType:
d->stringValue = readString(&f, size);
d->data->stringValue = readString(&f, size);
break;
case BytesType:
case GuidType:
d->byteVectorValue = f.readBlock(size);
d->data->byteVectorValue = f.readBlock(size);
break;
}
if (d->type == BytesType && name == "WM/Picture") {
d->pictureValue.parse(d->byteVectorValue);
if (d->pictureValue.isValid()) {
d->byteVectorValue.clear();
if (d->data->type == BytesType && name == "WM/Picture") {
d->data->pictureValue.parse(d->data->byteVectorValue);
if (d->data->pictureValue.isValid()) {
d->data->byteVectorValue.clear();
}
}
@@ -217,7 +227,7 @@ String ASF::Attribute::parse(ASF::File &f, int kind) {
int ASF::Attribute::dataSize() const {
switch (d->type) {
switch (d->data->type) {
case WordType:
return 2;
case BoolType:
@@ -227,13 +237,13 @@ int ASF::Attribute::dataSize() const {
case QWordType:
return 5;
case UnicodeType:
return d->stringValue.size() * 2 + 2;
return static_cast<int>(d->data->stringValue.size() * 2 + 2);
case BytesType:
if (d->pictureValue.isValid())
return d->pictureValue.dataSize();
if (d->data->pictureValue.isValid())
return d->data->pictureValue.dataSize();
break;
case GuidType:
return d->byteVectorValue.size();
return static_cast<int>(d->data->byteVectorValue.size());
}
return 0;
@@ -243,56 +253,56 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const {
ByteVector data;
switch (d->type) {
switch (d->data->type) {
case WordType:
data.append(ByteVector::fromShort(toUShort(), false));
data.append(ByteVector::fromUInt16LE(toUShort()));
break;
case BoolType:
if (kind == 0) {
data.append(ByteVector::fromUInt(toBool(), false));
data.append(ByteVector::fromUInt32LE(toBool()));
}
else {
data.append(ByteVector::fromShort(toBool(), false));
data.append(ByteVector::fromUInt16LE(toBool()));
}
break;
case DWordType:
data.append(ByteVector::fromUInt(toUInt(), false));
data.append(ByteVector::fromUInt32LE(toUInt()));
break;
case QWordType:
data.append(ByteVector::fromLongLong(toULongLong(), false));
data.append(ByteVector::fromUInt64LE(toULongLong()));
break;
case UnicodeType:
data.append(renderString(d->stringValue));
data.append(renderString(d->data->stringValue));
break;
case BytesType:
if (d->pictureValue.isValid()) {
data.append(d->pictureValue.render());
if (d->data->pictureValue.isValid()) {
data.append(d->data->pictureValue.render());
break;
}
break;
case GuidType:
data.append(d->byteVectorValue);
data.append(d->data->byteVectorValue);
break;
}
if (kind == 0) {
data = renderString(name, true) +
ByteVector::fromShort(static_cast<int>(d->type), false) +
ByteVector::fromShort(data.size(), false) +
ByteVector::fromUInt16LE((int)d->data->type) +
ByteVector::fromUInt16LE(data.size()) +
data;
}
else {
ByteVector nameData = renderString(name);
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
ByteVector::fromShort(d->stream, false) +
ByteVector::fromShort(nameData.size(), false) +
ByteVector::fromShort(static_cast<int>(d->type), false) +
ByteVector::fromUInt(data.size(), false) +
data = ByteVector::fromUInt16LE(kind == 2 ? d->data->language : 0) +
ByteVector::fromUInt16LE(d->data->stream) +
ByteVector::fromUInt16LE(nameData.size()) +
ByteVector::fromUInt16LE(static_cast<int>(d->data->type)) +
ByteVector::fromUInt32LE(data.size()) +
nameData +
data;
}
@@ -302,17 +312,17 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const {
}
int ASF::Attribute::language() const {
return d->language;
return d->data->language;
}
void ASF::Attribute::setLanguage(int value) {
d->language = value;
d->data->language = value;
}
int ASF::Attribute::stream() const {
return d->stream;
return d->data->stream;
}
void ASF::Attribute::setStream(int value) {
d->stream = value;
d->data->stream = value;
}

View File

@@ -56,7 +56,7 @@ class TAGLIB_EXPORT Attribute {
/*!
* Constructs an empty attribute.
*/
explicit Attribute();
Attribute();
/*!
* Constructs an attribute with \a key and a UnicodeType \a value.
@@ -66,7 +66,7 @@ class TAGLIB_EXPORT Attribute {
/*!
* Constructs an attribute with \a key and a BytesType \a value.
*/
explicit Attribute(const ByteVector &value);
Attribute(const ByteVector &value);
/*!
* Constructs an attribute with \a key and a Picture \a value.
@@ -79,27 +79,27 @@ class TAGLIB_EXPORT Attribute {
* WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications.
* You must add code in your application to perform validations if you want to maintain complete compatibility with ID3.
*/
explicit Attribute(const Picture &value);
Attribute(const Picture &value);
/*!
* Constructs an attribute with \a key and a DWordType \a value.
*/
explicit Attribute(unsigned int value);
Attribute(unsigned int value);
/*!
* Constructs an attribute with \a key and a QWordType \a value.
*/
explicit Attribute(unsigned long long value);
Attribute(unsigned long long value);
/*!
* Constructs an attribute with \a key and a WordType \a value.
*/
explicit Attribute(unsigned short value);
Attribute(unsigned short value);
/*!
* Constructs an attribute with \a key and a BoolType \a value.
*/
explicit Attribute(bool value);
Attribute(bool value);
/*!
* Construct an attribute as a copy of \a other.
@@ -181,17 +181,13 @@ class TAGLIB_EXPORT Attribute {
*/
void setStream(int value);
#ifndef DO_NOT_DOCUMENT
/* THIS IS PRIVATE, DON'T TOUCH IT! */
String parse(ASF::File &file, int kind = 0);
#endif
//! Returns the size of the stored data
int dataSize() const;
private:
friend class File;
String parse(ASF::File &file, int kind = 0);
ByteVector render(const String &name, int kind = 0) const;
class AttributePrivate;

View File

@@ -23,11 +23,13 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tdebug.h>
#include <tbytevectorlist.h>
#include <tpropertymap.h>
#include <tstring.h>
#include <tagutils.h>
#include <memory>
#include "tdebug.h"
#include "tbytevectorlist.h"
#include "tpropertymap.h"
#include "tstring.h"
#include "tagutils.h"
#include "asffile.h"
#include "asftag.h"
@@ -49,34 +51,23 @@ class ASF::File::FilePrivate {
class MetadataObject;
class MetadataLibraryObject;
FilePrivate() : headerSize(0),
tag(nullptr),
properties(nullptr),
contentDescriptionObject(nullptr),
extendedContentDescriptionObject(nullptr),
headerExtensionObject(nullptr),
metadataObject(nullptr),
metadataLibraryObject(nullptr) {
objects.setAutoDelete(true);
}
typedef List<std::shared_ptr<BaseObject>> ObjectList;
typedef ObjectList::ConstIterator ObjectConstIterator;
~FilePrivate() {
delete tag;
delete properties;
}
FilePrivate() : headerSize(0) {}
unsigned long long headerSize;
ASF::Tag *tag;
ASF::AudioProperties *properties;
std::unique_ptr<ASF::Tag> tag;
std::unique_ptr<ASF::AudioProperties> properties;
List<BaseObject *> objects;
ObjectList objects;
ContentDescriptionObject *contentDescriptionObject;
ExtendedContentDescriptionObject *extendedContentDescriptionObject;
HeaderExtensionObject *headerExtensionObject;
MetadataObject *metadataObject;
MetadataLibraryObject *metadataLibraryObject;
std::shared_ptr<ContentDescriptionObject> contentDescriptionObject;
std::shared_ptr<ExtendedContentDescriptionObject> extendedContentDescriptionObject;
std::shared_ptr<HeaderExtensionObject> headerExtensionObject;
std::shared_ptr<MetadataObject> metadataObject;
std::shared_ptr<MetadataLibraryObject> metadataLibraryObject;
};
namespace {
@@ -156,7 +147,7 @@ class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePriv
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject {
public:
List<ASF::File::FilePrivate::BaseObject *> objects;
ObjectList objects;
HeaderExtensionObject();
ByteVector guid() const override;
void parse(ASF::File *file, unsigned int size) override;
@@ -179,7 +170,7 @@ class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::B
void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size) {
data.clear();
if (size > 24 && size <= static_cast<unsigned int>(file->length()))
if (size > 24 && static_cast<long long>(size) <= file->length())
data = file->readBlock(size - 24);
else
data = ByteVector();
@@ -187,7 +178,7 @@ void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int siz
}
ByteVector ASF::File::FilePrivate::BaseObject::render(ASF::File * /*file*/) {
return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data;
return guid() + ByteVector::fromUInt64LE(data.size() + 24) + data;
}
ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) {}
@@ -208,8 +199,8 @@ void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsign
return;
}
const long long duration = data.toLongLong(40, false);
const long long preroll = data.toLongLong(56, false);
const long long duration = data.toInt64LE(40);
const long long preroll = data.toInt64LE(56);
file->d->properties->setLengthInMilliseconds(static_cast<int>(duration / 10000.0 - preroll + 0.5));
}
@@ -226,11 +217,11 @@ void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsi
return;
}
file->d->properties->setCodec(data.toUShort(54, false));
file->d->properties->setChannels(data.toUShort(56, false));
file->d->properties->setSampleRate(data.toUInt(58, false));
file->d->properties->setBitrate(static_cast<int>(data.toUInt(62, false) * 8.0 / 1000.0 + 0.5));
file->d->properties->setBitsPerSample(data.toUShort(68, false));
file->d->properties->setCodec(data.toUInt16LE(54));
file->d->properties->setChannels(data.toUInt16LE(56));
file->d->properties->setSampleRate(data.toUInt32LE(58));
file->d->properties->setBitrate(static_cast<int>(data.toUInt32LE(62) * 8.0 / 1000.0 + 0.5));
file->d->properties->setBitsPerSample(data.toUInt16LE(68));
}
@@ -261,11 +252,11 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *f
const ByteVector v4 = renderString(file->d->tag->comment());
const ByteVector v5 = renderString(file->d->tag->rating());
data.clear();
data.append(ByteVector::fromShort(v1.size(), false));
data.append(ByteVector::fromShort(v2.size(), false));
data.append(ByteVector::fromShort(v3.size(), false));
data.append(ByteVector::fromShort(v4.size(), false));
data.append(ByteVector::fromShort(v5.size(), false));
data.append(ByteVector::fromUInt16LE(v1.size()));
data.append(ByteVector::fromUInt16LE(v2.size()));
data.append(ByteVector::fromUInt16LE(v3.size()));
data.append(ByteVector::fromUInt16LE(v4.size()));
data.append(ByteVector::fromUInt16LE(v5.size()));
data.append(v1);
data.append(v2);
data.append(v3);
@@ -293,7 +284,7 @@ void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file) {
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
@@ -317,7 +308,7 @@ void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file) {
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
@@ -341,7 +332,7 @@ void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsig
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file) {
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
@@ -372,17 +363,17 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
file->setValid(false);
break;
}
BaseObject *obj;
std::shared_ptr<BaseObject> obj;
if (guid == metadataGuid) {
file->d->metadataObject = new MetadataObject();
file->d->metadataObject.reset(new MetadataObject());
obj = file->d->metadataObject;
}
else if (guid == metadataLibraryGuid) {
file->d->metadataLibraryObject = new MetadataLibraryObject();
file->d->metadataLibraryObject.reset(new MetadataLibraryObject());
obj = file->d->metadataLibraryObject;
}
else {
obj = new UnknownObject(guid);
obj.reset(new UnknownObject(guid));
}
obj->parse(file, static_cast<unsigned int>(size));
objects.append(obj);
@@ -394,10 +385,10 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file) {
data.clear();
for (List<BaseObject *>::ConstIterator it = objects.begin(); it != objects.end(); ++it) {
for (ObjectConstIterator it = objects.begin(); it != objects.end(); ++it) {
data.append((*it)->render(file));
}
data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data;
data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt32LE(data.size()) + data;
return BaseObject::render(file);
}
@@ -416,7 +407,7 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
unsigned int pos = 16;
const int count = data.toUInt(pos, false);
const int count = data.toUInt32LE(pos);
pos += 4;
for (int i = 0; i < count; ++i) {
@@ -424,22 +415,22 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
if (pos >= data.size())
break;
const CodecType type = static_cast<CodecType>(data.toUShort(pos, false));
const CodecType type = static_cast<CodecType>(data.toUInt16LE(pos));
pos += 2;
int nameLength = data.toUShort(pos, false);
int nameLength = data.toUInt16LE(pos);
pos += 2;
const unsigned int namePos = pos;
pos += nameLength * 2;
const int descLength = data.toUShort(pos, false);
const int descLength = data.toUInt16LE(pos);
pos += 2;
const unsigned int descPos = pos;
pos += descLength * 2;
const int infoLength = data.toUShort(pos, false);
const int infoLength = data.toUInt16LE(pos);
pos += 2 + infoLength * 2;
if (type == CodecListObject::Audio) {
@@ -489,23 +480,11 @@ ASF::File::~File() {
}
ASF::Tag *ASF::File::tag() const {
return d->tag;
}
PropertyMap ASF::File::properties() const {
return d->tag->properties();
}
void ASF::File::removeUnsupportedProperties(const StringList &properties) {
d->tag->removeUnsupportedProperties(properties);
}
PropertyMap ASF::File::setProperties(const PropertyMap &properties) {
return d->tag->setProperties(properties);
return d->tag.get();
}
ASF::AudioProperties *ASF::File::audioProperties() const {
return d->properties;
return d->properties.get();
}
bool ASF::File::save() {
@@ -521,23 +500,23 @@ bool ASF::File::save() {
}
if (!d->contentDescriptionObject) {
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
d->contentDescriptionObject.reset(new FilePrivate::ContentDescriptionObject());
d->objects.append(d->contentDescriptionObject);
}
if (!d->extendedContentDescriptionObject) {
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
d->extendedContentDescriptionObject.reset(new FilePrivate::ExtendedContentDescriptionObject());
d->objects.append(d->extendedContentDescriptionObject);
}
if (!d->headerExtensionObject) {
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
d->headerExtensionObject.reset(new FilePrivate::HeaderExtensionObject());
d->objects.append(d->headerExtensionObject);
}
if (!d->metadataObject) {
d->metadataObject = new FilePrivate::MetadataObject();
d->metadataObject.reset(new FilePrivate::MetadataObject());
d->headerExtensionObject->objects.append(d->metadataObject);
}
if (!d->metadataLibraryObject) {
d->metadataLibraryObject = new FilePrivate::MetadataLibraryObject();
d->metadataLibraryObject.reset(new FilePrivate::MetadataLibraryObject());
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
}
@@ -576,16 +555,16 @@ bool ASF::File::save() {
}
ByteVector data;
for (List<FilePrivate::BaseObject *>::ConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
for (FilePrivate::ObjectConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
data.append((*it)->render(this));
}
seek(16);
writeBlock(ByteVector::fromLongLong(data.size() + 30, false));
writeBlock(ByteVector::fromUInt(d->objects.size(), false));
writeBlock(ByteVector::fromUInt64LE(data.size() + 30));
writeBlock(ByteVector::fromUInt32LE(d->objects.size()));
writeBlock(ByteVector("\x01\x02", 2));
insert(data, 30, static_cast<unsigned long>(d->headerSize - 30));
insert(data, 30, static_cast<size_t>(d->headerSize - 30));
d->headerSize = data.size() + 30;
@@ -608,8 +587,8 @@ void ASF::File::read() {
return;
}
d->tag = new ASF::Tag();
d->properties = new ASF::AudioProperties();
d->tag.reset(new ASF::Tag());
d->properties.reset(new ASF::AudioProperties());
bool ok;
d->headerSize = readQWORD(this, &ok);
@@ -624,8 +603,8 @@ void ASF::File::read() {
}
seek(2, Current);
FilePrivate::FilePropertiesObject *filePropertiesObject = nullptr;
FilePrivate::StreamPropertiesObject *streamPropertiesObject = nullptr;
std::shared_ptr<FilePrivate::FilePropertiesObject> filePropertiesObject;
std::shared_ptr<FilePrivate::StreamPropertiesObject> streamPropertiesObject;
for (int i = 0; i < numObjects; i++) {
const ByteVector guid = readBlock(16);
if (guid.size() != 16) {
@@ -637,29 +616,29 @@ void ASF::File::read() {
setValid(false);
break;
}
FilePrivate::BaseObject *obj;
std::shared_ptr<FilePrivate::BaseObject> obj;
if (guid == filePropertiesGuid) {
filePropertiesObject = new FilePrivate::FilePropertiesObject();
filePropertiesObject.reset(new FilePrivate::FilePropertiesObject());
obj = filePropertiesObject;
}
else if (guid == streamPropertiesGuid) {
streamPropertiesObject = new FilePrivate::StreamPropertiesObject();
streamPropertiesObject.reset(new FilePrivate::StreamPropertiesObject());
obj = streamPropertiesObject;
}
else if (guid == contentDescriptionGuid) {
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
d->contentDescriptionObject.reset(new FilePrivate::ContentDescriptionObject());
obj = d->contentDescriptionObject;
}
else if (guid == extendedContentDescriptionGuid) {
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
d->extendedContentDescriptionObject.reset(new FilePrivate::ExtendedContentDescriptionObject());
obj = d->extendedContentDescriptionObject;
}
else if (guid == headerExtensionGuid) {
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
d->headerExtensionObject.reset(new FilePrivate::HeaderExtensionObject());
obj = d->headerExtensionObject;
}
else if (guid == codecListGuid) {
obj = new FilePrivate::CodecListObject();
obj.reset(new FilePrivate::CodecListObject());
}
else {
if (guid == contentEncryptionGuid ||
@@ -667,7 +646,7 @@ void ASF::File::read() {
guid == advancedContentEncryptionGuid) {
d->properties->setEncrypted(true);
}
obj = new FilePrivate::UnknownObject(guid);
obj.reset(new FilePrivate::UnknownObject(guid));
}
obj->parse(this, size);
d->objects.append(obj);

View File

@@ -70,7 +70,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
/*!
* Destroys this instance of the File.
*/
virtual ~File();
~File() override;
/*!
* Returns a pointer to the ASF tag of the file.
@@ -82,34 +82,19 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*/
virtual Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
*/
PropertyMap properties() const;
/*!
* Removes unsupported properties. Forwards to the actual Tag's removeUnsupportedProperties() function.
*/
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
*/
PropertyMap setProperties(const PropertyMap &);
Tag *tag() const override;
/*!
* Returns the ASF audio properties for this file.
*/
virtual AudioProperties *audioProperties() const;
AudioProperties *audioProperties() const override;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
virtual bool save();
bool save() override;
/*!
* Returns whether or not the given \a stream can be opened as an ASF file.

View File

@@ -23,9 +23,10 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <taglib.h>
#include <tdebug.h>
#include <trefcounter.h>
#include <memory>
#include "taglib.h"
#include "tdebug.h"
#include "asfattribute.h"
#include "asffile.h"
@@ -34,71 +35,75 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::Picture::PicturePrivate : public RefCounter {
public:
namespace {
struct PictureData {
bool valid;
Type type;
ASF::Picture::Type type;
String mimeType;
String description;
ByteVector picture;
};
} // namespace
class ASF::Picture::PicturePrivate {
public:
explicit PicturePrivate() : data(new PictureData()) {}
std::shared_ptr<PictureData> data;
};
////////////////////////////////////////////////////////////////////////////////
// Picture class members
////////////////////////////////////////////////////////////////////////////////
ASF::Picture::Picture() : d(new PicturePrivate()) {
d->valid = true;
d->data->valid = true;
}
ASF::Picture::Picture(const Picture& other) : d(other.d) {
d->ref();
}
ASF::Picture::Picture(const Picture& other) : d(new PicturePrivate(*other.d)) {}
ASF::Picture::~Picture() {
if (d->deref())
delete d;
delete d;
}
bool ASF::Picture::isValid() const {
return d->valid;
return d->data->valid;
}
String ASF::Picture::mimeType() const {
return d->mimeType;
return d->data->mimeType;
}
void ASF::Picture::setMimeType(const String& value) {
d->mimeType = value;
d->data->mimeType = value;
}
ASF::Picture::Type ASF::Picture::type() const {
return d->type;
return d->data->type;
}
void ASF::Picture::setType(const ASF::Picture::Type &t) {
d->type = t;
d->data->type = t;
}
String ASF::Picture::description() const {
return d->description;
return d->data->description;
}
void ASF::Picture::setDescription(const String& desc) {
d->description = desc;
d->data->description = desc;
}
ByteVector ASF::Picture::picture() const {
return d->picture;
return d->data->picture;
}
void ASF::Picture::setPicture(const ByteVector &p) {
d->picture = p;
d->data->picture = p;
}
int ASF::Picture::dataSize() const {
return 9 + (d->mimeType.length() + d->description.length()) * 2 +
d->picture.size();
return 9 + (d->data->mimeType.length() + d->data->description.length()) * 2 + d->data->picture.size();
}
ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other) {
@@ -117,51 +122,47 @@ ByteVector ASF::Picture::render() const {
if (!isValid())
return ByteVector();
return ByteVector(static_cast<char>(d->type)) +
ByteVector::fromUInt(d->picture.size(), false) +
renderString(d->mimeType) +
renderString(d->description) +
d->picture;
return ByteVector(static_cast<char>(d->data->type)) + ByteVector::fromUInt32LE(d->data->picture.size()) + renderString(d->data->mimeType) + renderString(d->data->description) + d->data->picture;
}
void ASF::Picture::parse(const ByteVector &bytes) {
d->valid = false;
d->data->valid = false;
if (bytes.size() < 9)
return;
int pos = 0;
d->type = static_cast<Type>(bytes[0]);
size_t pos = 0;
d->data->type = static_cast<Type>(bytes[0]);
++pos;
const unsigned int dataLen = bytes.toUInt(pos, false);
const unsigned int dataLen = bytes.toUInt32LE(pos);
pos += 4;
const ByteVector nullStringTerminator(2, 0);
int endPos = bytes.find(nullStringTerminator, pos, 2);
if (endPos < 0)
size_t endPos = bytes.find(nullStringTerminator, pos, 2);
if (endPos == ByteVector::npos())
return;
d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
d->data->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos + 2;
endPos = bytes.find(nullStringTerminator, pos, 2);
if (endPos < 0)
if (endPos == ByteVector::npos())
return;
d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
d->data->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos + 2;
if (dataLen + pos != bytes.size())
return;
d->picture = bytes.mid(pos, dataLen);
d->valid = true;
d->data->picture = bytes.mid(pos, dataLen);
d->data->valid = true;
}
ASF::Picture ASF::Picture::fromInvalid() {
Picture ret;
ret.d->valid = false;
ret.d->data->valid = false;
return ret;
}

View File

@@ -34,6 +34,7 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ASF {
class Attribute;
//! An ASF attached picture interface implementation
@@ -200,11 +201,11 @@ class TAGLIB_EXPORT Picture {
*/
int dataSize() const;
#ifndef DO_NOT_DOCUMENT
/* THIS IS PRIVATE, DON'T TOUCH IT! */
private:
friend class Attribute;
void parse(const ByteVector&);
static Picture fromInvalid();
#endif
private:
class PicturePrivate;

View File

@@ -23,21 +23,21 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tdebug.h>
#include <tstring.h>
#include "tdebug.h"
#include "tstring.h"
#include "asfproperties.h"
using namespace Strawberry_TagLib::TagLib;
class ASF::AudioProperties::AudioPropertiesPrivate {
public:
AudioPropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
bitsPerSample(0),
codec(ASF::AudioProperties::Unknown),
encrypted(false) {}
explicit AudioPropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
bitsPerSample(0),
codec(ASF::AudioProperties::Unknown),
encrypted(false) {}
int length;
int bitrate;
@@ -54,8 +54,7 @@ class ASF::AudioProperties::AudioPropertiesPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::AudioProperties::AudioProperties() : Strawberry_TagLib::TagLib::AudioProperties(AudioProperties::Average),
d(new AudioPropertiesPrivate()) {
ASF::AudioProperties::AudioProperties() : Strawberry_TagLib::TagLib::AudioProperties(), d(new AudioPropertiesPrivate()) {
}
ASF::AudioProperties::~AudioProperties() {

View File

@@ -36,6 +36,8 @@ namespace ASF {
//! An implementation of ASF audio properties
class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioProperties {
friend class File;
public:
/*!
* Audio codec types can be used in ASF file.
@@ -75,7 +77,7 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
/*!
* Destroys this ASF::AudioProperties instance.
*/
virtual ~AudioProperties();
~AudioProperties() override;
/*!
* Returns the length of the file in seconds. The length is rounded down to
@@ -83,29 +85,29 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
int lengthInSeconds() const override;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
int lengthInMilliseconds() const override;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
int bitrate() const override;
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
int sampleRate() const override;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
int channels() const override;
/*!
* Returns the number of bits per audio sample.
@@ -142,7 +144,7 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
*/
bool isEncrypted() const;
#ifndef DO_NOT_DOCUMENT
private:
void setLengthInMilliseconds(int value);
void setBitrate(int value);
void setSampleRate(int value);
@@ -152,7 +154,6 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
void setCodecName(const String &value);
void setCodecDescription(const String &value);
void setEncrypted(bool value);
#endif
private:
class AudioPropertiesPrivate;

View File

@@ -23,7 +23,8 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tpropertymap.h>
#include "tpicturemap.h"
#include "tpropertymap.h"
#include "asftag.h"
using namespace Strawberry_TagLib::TagLib;
@@ -38,8 +39,7 @@ class ASF::Tag::TagPrivate {
AttributeListMap attributeListMap;
};
ASF::Tag::Tag() : d(new TagPrivate()) {
}
ASF::Tag::Tag() : d(new TagPrivate()) {}
ASF::Tag::~Tag() {
delete d;
@@ -104,6 +104,87 @@ String ASF::Tag::genre() const {
}
PictureMap ASF::Tag::pictures() const {
PictureMap map;
if (d->attributeListMap.contains("WM/Picture")) {
AttributeList list = d->attributeListMap["WM/Picture"];
for (AttributeList::ConstIterator it = list.begin(); it != list.end(); ++it) {
ASF::Picture asfPicture = (*it).toPicture();
TagLib::Picture::Type type;
switch (asfPicture.type()) {
case ASF::Picture::FileIcon:
type = TagLib::Picture::FileIcon;
break;
case ASF::Picture::OtherFileIcon:
type = TagLib::Picture::OtherFileIcon;
break;
case ASF::Picture::FrontCover:
type = TagLib::Picture::FrontCover;
break;
case ASF::Picture::BackCover:
type = TagLib::Picture::BackCover;
break;
case ASF::Picture::LeafletPage:
type = TagLib::Picture::LeafletPage;
break;
case ASF::Picture::Media:
type = TagLib::Picture::Media;
break;
case ASF::Picture::LeadArtist:
type = TagLib::Picture::LeadArtist;
break;
case ASF::Picture::Artist:
type = TagLib::Picture::Artist;
break;
case ASF::Picture::Conductor:
type = TagLib::Picture::Conductor;
break;
case ASF::Picture::Band:
type = TagLib::Picture::Band;
break;
case ASF::Picture::Composer:
type = TagLib::Picture::Composer;
break;
case ASF::Picture::Lyricist:
type = TagLib::Picture::Lyricist;
break;
case ASF::Picture::RecordingLocation:
type = TagLib::Picture::RecordingLocation;
break;
case ASF::Picture::DuringRecording:
type = TagLib::Picture::DuringRecording;
break;
case ASF::Picture::DuringPerformance:
type = TagLib::Picture::DuringPerformance;
break;
case ASF::Picture::MovieScreenCapture:
type = TagLib::Picture::MovieScreenCapture;
break;
case ASF::Picture::ColouredFish:
type = TagLib::Picture::ColouredFish;
break;
case ASF::Picture::Illustration:
type = TagLib::Picture::Illustration;
break;
case ASF::Picture::BandLogo:
type = TagLib::Picture::BandLogo;
break;
case ASF::Picture::PublisherLogo:
type = TagLib::Picture::PublisherLogo;
break;
default:
type = TagLib::Picture::Other;
break;
}
TagLib::Picture picture(asfPicture.picture(), type, asfPicture.mimeType(), asfPicture.description());
map.insert(picture);
}
}
return PictureMap(map);
}
void ASF::Tag::setTitle(const String &value) {
d->title = value;
}
@@ -140,7 +221,89 @@ void ASF::Tag::setTrack(unsigned int value) {
setAttribute("WM/TrackNumber", String::number(value));
}
const ASF::AttributeListMap ASF::Tag::attributeListMap() const {
void ASF::Tag::setPictures(const PictureMap &l) {
removeItem("WM/Picture");
for (PictureMap::ConstIterator pictureMapIt = l.begin(); pictureMapIt != l.end(); ++pictureMapIt) {
PictureList list = pictureMapIt->second;
for (PictureList::ConstIterator pictureListIt = list.begin(); pictureListIt != list.end(); ++pictureListIt) {
const TagLib::Picture picture = (*pictureListIt);
ASF::Picture asfPicture;
asfPicture.setPicture(picture.data());
asfPicture.setMimeType(picture.mime());
asfPicture.setDescription(picture.description());
switch (picture.type()) {
case TagLib::Picture::Other:
asfPicture.setType(ASF::Picture::Other);
break;
case TagLib::Picture::FileIcon:
asfPicture.setType(ASF::Picture::FileIcon);
break;
case TagLib::Picture::OtherFileIcon:
asfPicture.setType(ASF::Picture::OtherFileIcon);
break;
case TagLib::Picture::FrontCover:
asfPicture.setType(ASF::Picture::FrontCover);
break;
case TagLib::Picture::BackCover:
asfPicture.setType(ASF::Picture::BackCover);
break;
case TagLib::Picture::LeafletPage:
asfPicture.setType(ASF::Picture::LeafletPage);
break;
case TagLib::Picture::Media:
asfPicture.setType(ASF::Picture::Media);
break;
case TagLib::Picture::LeadArtist:
asfPicture.setType(ASF::Picture::LeadArtist);
break;
case TagLib::Picture::Artist:
asfPicture.setType(ASF::Picture::Artist);
break;
case TagLib::Picture::Conductor:
asfPicture.setType(ASF::Picture::Conductor);
break;
case TagLib::Picture::Band:
asfPicture.setType(ASF::Picture::Band);
break;
case TagLib::Picture::Composer:
asfPicture.setType(ASF::Picture::Composer);
break;
case TagLib::Picture::Lyricist:
asfPicture.setType(ASF::Picture::Lyricist);
break;
case TagLib::Picture::RecordingLocation:
asfPicture.setType(ASF::Picture::RecordingLocation);
break;
case TagLib::Picture::DuringRecording:
asfPicture.setType(ASF::Picture::DuringRecording);
break;
case TagLib::Picture::DuringPerformance:
asfPicture.setType(ASF::Picture::DuringPerformance);
break;
case TagLib::Picture::MovieScreenCapture:
asfPicture.setType(ASF::Picture::MovieScreenCapture);
break;
case TagLib::Picture::ColouredFish:
asfPicture.setType(ASF::Picture::ColouredFish);
break;
case TagLib::Picture::Illustration:
asfPicture.setType(ASF::Picture::Illustration);
break;
case TagLib::Picture::BandLogo:
asfPicture.setType(ASF::Picture::BandLogo);
break;
case TagLib::Picture::PublisherLogo:
asfPicture.setType(ASF::Picture::PublisherLogo);
break;
}
addAttribute("WM/Picture", Attribute(asfPicture));
}
}
}
const ASF::AttributeListMap &ASF::Tag::attributeListMap() const {
return d->attributeListMap;
}

View File

@@ -47,32 +47,32 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
explicit Tag();
virtual ~Tag();
~Tag() override;
/*!
* Returns the track name.
*/
virtual String title() const;
String title() const override;
/*!
* Returns the artist name.
*/
virtual String artist() const;
String artist() const override;
/*!
* Returns the album name; if no album name is present in the tag String::null will be returned.
*/
virtual String album() const;
String album() const override;
/*!
* Returns the track comment.
*/
virtual String comment() const;
String comment() const override;
/*!
* Returns the genre name; if no genre is present in the tag String::null will be returned.
*/
virtual String genre() const;
String genre() const override;
/*!
* Returns the rating.
@@ -87,32 +87,34 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
/*!
* Returns the year; if there is no year set, this will return 0.
*/
virtual unsigned int year() const;
unsigned int year() const override;
/*!
* Returns the track number; if there is no track number set, this will return 0.
*/
virtual unsigned int track() const;
unsigned int track() const override;
PictureMap pictures() const override;
/*!
* Sets the title to \a s.
*/
virtual void setTitle(const String &value);
void setTitle(const String &value) override;
/*!
* Sets the artist to \a s.
*/
virtual void setArtist(const String &value);
void setArtist(const String &value) override;
/*!
* Sets the album to \a s. If \a s is String::null then this value will be cleared.
*/
virtual void setAlbum(const String &value);
void setAlbum(const String &value) override;
/*!
* Sets the comment to \a s.
*/
virtual void setComment(const String &value);
void setComment(const String &value) override;
/*!
* Sets the rating to \a s.
@@ -127,28 +129,30 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
/*!
* Sets the genre to \a s.
*/
virtual void setGenre(const String &value);
void setGenre(const String &value) override;
/*!
* Sets the year to \a i. If \a s is 0 then this value will be cleared.
*/
virtual void setYear(unsigned int value);
void setYear(unsigned int value) override;
/*!
* Sets the track to \a i. If \a s is 0 then this value will be cleared.
*/
virtual void setTrack(unsigned int value);
void setTrack(unsigned int value) override;
void setPictures(const PictureMap&) override;
/*!
* Returns true if the tag does not contain any data.
* This should be reimplemented in subclasses that provide more than the basic tagging abilities in this class.
*/
virtual bool isEmpty() const;
bool isEmpty() const override;
/*!
* Returns a reference to the item list map. This is an AttributeListMap of all of the items in the tag.
*/
const AttributeListMap attributeListMap() const;
const AttributeListMap &attributeListMap() const;
/*!
* \return True if a value for \a attribute is currently set.
@@ -181,15 +185,17 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
*/
void addAttribute(const String &name, const Attribute &attribute);
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &props);
PropertyMap setProperties(const PropertyMap &props);
PropertyMap properties() const override;
void removeUnsupportedProperties(const StringList &props) override;
PropertyMap setProperties(const PropertyMap &props) override;
private:
class TagPrivate;
TagPrivate *d;
};
} // namespace ASF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -35,39 +35,40 @@ namespace TagLib {
namespace ASF {
namespace {
inline unsigned short readWORD(File *file, bool *ok = 0) {
inline unsigned short readWORD(File *file, bool *ok = nullptr) {
const ByteVector v = file->readBlock(2);
if (v.size() != 2) {
if (ok) *ok = false;
return 0;
}
if (ok) *ok = true;
return v.toUShort(false);
return v.toUInt16LE(0);
}
inline unsigned int readDWORD(File *file, bool *ok = 0) {
inline unsigned int readDWORD(File *file, bool *ok = nullptr) {
const ByteVector v = file->readBlock(4);
if (v.size() != 4) {
if (ok) *ok = false;
return 0;
}
if (ok) *ok = true;
return v.toUInt(false);
return v.toUInt32LE(0);
}
inline long long readQWORD(File *file, bool *ok = 0) {
inline long long readQWORD(File *file, bool *ok = nullptr) {
const ByteVector v = file->readBlock(8);
if (v.size() != 8) {
if (ok) *ok = false;
return 0;
}
if (ok) *ok = true;
return v.toLongLong(false);
return v.toInt64LE(0);
}
inline String readString(File *file, int length) {
ByteVector data = file->readBlock(length);
unsigned int size = data.size();
size_t size = data.size();
while (size >= 2) {
if (data[size - 1] != '\0' || data[size - 2] != '\0') {
break;
@@ -78,12 +79,13 @@ inline String readString(File *file, int length) {
data.resize(size);
}
return String(data, String::UTF16LE);
}
inline ByteVector renderString(const String &str, bool includeLength = false) {
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromUInt16LE(0);
if (includeLength) {
data = ByteVector::fromShort(data.size(), false) + data;
data = ByteVector::fromUInt16LE(data.size()) + data;
}
return data;
}