Redesigned toNumber/fromNumber API of ByteVector

This commit is contained in:
Tsuda Kageyu
2013-04-27 12:46:21 +09:00
parent 82e616101a
commit 362900c721
51 changed files with 802 additions and 711 deletions

View File

@@ -5,13 +5,14 @@ include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckCXXSourceCompiles)
include(TestBigEndian)
# check for libz using the cmake supplied FindZLIB.cmake
find_package(ZLIB)
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
else()
set(HAVE_ZLIB 0)
# Determine the CPU byte order.
test_big_endian(TAGLIB_BIG_ENDIAN)
if(NOT TAGLIB_BIG_ENDIAN)
set(TAGLIB_LITTLE_ENDIAN 1)
endif()
# Determine whether or not your compiler supports move semantics.
@@ -34,6 +35,79 @@ check_cxx_source_compiles("
int main() { return 0; }
" SUPPORT_TEMPLATE_ALIAS)
# Determine which kind of byte swap functions your compiler supports.
# GCC's __builtin_bswap* should be checked individually
# because some of them can be missing depends on the GCC version.
check_cxx_source_compiles("
int main() {
__builtin_bswap16(0);
return 0;
}
" HAVE_GCC_BYTESWAP_16)
check_cxx_source_compiles("
int main() {
__builtin_bswap32(0);
return 0;
}
" HAVE_GCC_BYTESWAP_32)
check_cxx_source_compiles("
int main() {
__builtin_bswap64(0);
return 0;
}
" HAVE_GCC_BYTESWAP_64)
if(NOT HAVE_GCC_BYTESWAP_16 OR NOT HAVE_GCC_BYTESWAP_32 OR NOT HAVE_GCC_BYTESWAP_64)
check_cxx_source_compiles("
#include <byteswap.h>
int main() {
__bswap_16(0);
__bswap_32(0);
__bswap_64(0);
return 0;
}
" HAVE_GLIBC_BYTESWAP)
if(NOT HAVE_GLIBC_BYTESWAP)
check_cxx_source_compiles("
#include <stdlib.h>
int main() {
_byteswap_ushort(0);
_byteswap_ulong(0);
_byteswap_uint64(0);
return 0;
}
" HAVE_MSC_BYTESWAP)
if(NOT HAVE_MSC_BYTESWAP)
check_cxx_source_compiles("
#include <libkern/OSByteOrder.h>
int main() {
OSSwapInt16(0);
OSSwapInt32(0);
OSSwapInt64(0);
return 0;
}
" HAVE_MAC_BYTESWAP)
if(NOT HAVE_MAC_BYTESWAP)
check_cxx_source_compiles("
#include <sys/endian.h>
int main() {
swap16(0);
swap32(0);
swap64(0);
return 0;
}
" HAVE_OPENBSD_BYTESWAP)
endif()
endif()
endif()
endif()
# Determine where shared_ptr<T> is defined regardless of C++11 support.
check_cxx_source_compiles("
#include <memory>
@@ -56,6 +130,14 @@ check_cxx_source_compiles("
int main() { std::codecvt_utf8_utf16<wchar_t> x; return 0; }
" HAVE_CODECVT)
# check for libz using the cmake supplied FindZLIB.cmake
find_package(ZLIB)
if(ZLIB_FOUND)
set(HAVE_ZLIB 1)
else()
set(HAVE_ZLIB 0)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
find_package(CppUnit)
if(NOT CppUnit_FOUND AND BUILD_TESTS)

View File

@@ -3,12 +3,25 @@
/* Define if you have libz */
#cmakedefine HAVE_ZLIB 1
/* Indicates the endianness of your target system */
#cmakedefine TAGLIB_LITTLE_ENDIAN 1
#cmakedefine TAGLIB_BIG_ENDIAN 1
/* Defined if your compiler supports the move semantics */
#cmakedefine SUPPORT_MOVE_SEMANTICS 1
/* Defined if your compiler supports the template alias */
#cmakedefine SUPPORT_TEMPLATE_ALIAS 1
/* Defined if your compiler supports some byte swap functions */
#cmakedefine HAVE_GCC_BYTESWAP_16 1
#cmakedefine HAVE_GCC_BYTESWAP_32 1
#cmakedefine HAVE_GCC_BYTESWAP_64 1
#cmakedefine HAVE_GLIBC_BYTESWAP 1
#cmakedefine HAVE_MSC_BYTESWAP 1
#cmakedefine HAVE_MAC_BYTESWAP 1
#cmakedefine HAVE_OPENBSD_BYTESWAP 1
/* Defined if your compiler supports shared_ptr */
#cmakedefine HAVE_STD_SHARED_PTR 1
#cmakedefine HAVE_TR1_SHARED_PTR 1
@@ -17,6 +30,9 @@
/* Defined if your compiler has <codecvt> header */
#cmakedefine HAVE_CODECVT 1
/* Define if you have libz */
#cmakedefine HAVE_ZLIB 1
#cmakedefine NO_ITUNES_HACKS 1
#cmakedefine WITH_ASF 1
#cmakedefine WITH_MP4 1

View File

@@ -51,7 +51,6 @@ set(tag_HDRS
toolkit/tmap.h
toolkit/tmap.tcc
toolkit/tpropertymap.h
toolkit/tbyteswap.h
toolkit/trefcountptr.h
mpeg/mpegfile.h
mpeg/mpegproperties.h
@@ -293,7 +292,6 @@ set(toolkit_SRCS
toolkit/tfilestream.cpp
toolkit/tdebug.cpp
toolkit/tpropertymap.cpp
toolkit/tbyteswap.cpp
toolkit/unicode.cpp
)

View File

@@ -177,19 +177,19 @@ void APE::Footer::parse(const ByteVector &data)
// Read the version number
d->version = data.mid(8, 4).toUInt32(false);
d->version = data.toUInt32LE(8);
// Read the tag size
d->tagSize = data.mid(12, 4).toUInt32(false);
d->tagSize = data.toUInt32LE(12);
// Read the item count
d->itemCount = data.mid(16, 4).toUInt32(false);
d->itemCount = data.toUInt32LE(16);
// Read the flags
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.mid(20, 4).toUInt32(false)));
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt32LE(20)));
d->headerPresent = flags[31];
d->footerPresent = !flags[30];
@@ -208,15 +208,15 @@ ByteVector APE::Footer::render(bool isHeader) const
// add the version number -- we always render a 2.000 tag regardless of what
// the tag originally was.
v.append(ByteVector::fromUInt32(2000, false));
v.append(ByteVector::fromUInt32LE(2000));
// add the tag size
v.append(ByteVector::fromUInt32(d->tagSize, false));
v.append(ByteVector::fromUInt32LE(d->tagSize));
// add the item count
v.append(ByteVector::fromUInt32(d->itemCount, false));
v.append(ByteVector::fromUInt32LE(d->itemCount));
// render and add the flags
@@ -226,11 +226,11 @@ ByteVector APE::Footer::render(bool isHeader) const
flags[30] = false; // footer is always present
flags[29] = isHeader;
v.append(ByteVector::fromUInt32(flags.to_ulong(), false));
v.append(ByteVector::fromUInt32LE(flags.to_ulong()));
// add the reserved 64bit
v.append(ByteVector::fromUInt64(0));
v.append(ByteVector::fromUInt64BE(0));
return v;
}

View File

@@ -216,8 +216,8 @@ void APE::Item::parse(const ByteVector &data)
return;
}
uint valueLength = data.mid(0, 4).toUInt32(false);
uint flags = data.mid(4, 4).toUInt32(false);
const uint valueLength = data.toUInt32LE(0);
const uint flags = data.toUInt32LE(4);
d->key = String(data.mid(8), String::UTF8);
@@ -253,8 +253,8 @@ ByteVector APE::Item::render() const
else
value.append(d->value);
data.append(ByteVector::fromUInt32(value.size(), false));
data.append(ByteVector::fromUInt32(flags, false));
data.append(ByteVector::fromUInt32LE(value.size()));
data.append(ByteVector::fromUInt32LE(flags));
data.append(d->key.data(String::UTF8));
data.append(ByteVector('\0'));
data.append(value);

View File

@@ -128,7 +128,7 @@ void APE::Properties::read()
ByteVector commonHeader=d->file->readBlock(6);
if(!commonHeader.startsWith("MAC "))
return;
d->version = commonHeader.mid(4).toUInt32(false);
d->version = commonHeader.toUInt16LE(4);
if(d->version >= 3980) {
analyzeCurrent();
@@ -182,7 +182,7 @@ void APE::Properties::analyzeCurrent()
// Read the descriptor
d->file->seek(2, File::Current);
ByteVector descriptor = d->file->readBlock(44);
uint descriptorBytes = descriptor.mid(0,4).toUInt32(false);
uint descriptorBytes = descriptor.toUInt32LE(0);
if ((descriptorBytes - 52) > 0)
d->file->seek(descriptorBytes - 52, File::Current);
@@ -191,14 +191,14 @@ void APE::Properties::analyzeCurrent()
ByteVector header = d->file->readBlock(24);
// Get the APE info
d->channels = header.mid(18, 2).toInt16(false);
d->sampleRate = header.mid(20, 4).toUInt32(false);
d->bitsPerSample = header.mid(16, 2).toInt16(false);
d->channels = header.toInt16LE(18);
d->sampleRate = header.toUInt32LE(20);
d->bitsPerSample = header.toInt16LE(16);
//d->compressionLevel =
uint totalFrames = header.mid(12, 4).toUInt32(false);
uint blocksPerFrame = header.mid(4, 4).toUInt32(false);
uint finalFrameBlocks = header.mid(8, 4).toUInt32(false);
uint totalFrames = header.toUInt32LE(12);
uint blocksPerFrame = header.toUInt32LE(4);
uint finalFrameBlocks = header.toUInt32LE(8);
d->sampleFrames = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
@@ -207,13 +207,13 @@ void APE::Properties::analyzeCurrent()
void APE::Properties::analyzeOld()
{
ByteVector header = d->file->readBlock(26);
uint totalFrames = header.mid(18, 4).toUInt32(false);
uint totalFrames = header.toUInt32LE(18);
// Fail on 0 length APE files (catches non-finalized APE files)
if(totalFrames == 0)
return;
short compressionLevel = header.mid(0, 2).toInt16(false);
short compressionLevel = header.toUInt32LE(0);
uint blocksPerFrame;
if(d->version >= 3950)
blocksPerFrame = 73728 * 4;
@@ -221,10 +221,10 @@ void APE::Properties::analyzeOld()
blocksPerFrame = 73728;
else
blocksPerFrame = 9216;
d->channels = header.mid(4, 2).toInt16(false);
d->sampleRate = header.mid(6, 4).toUInt32(false);
uint finalFrameBlocks = header.mid(22, 4).toUInt32(false);
uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->channels = header.toUInt16LE(4);
d->sampleRate = header.toUInt32LE(6);
const uint finalFrameBlocks = header.toUInt32LE(22);
const uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->length = totalBlocks / d->sampleRate;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
}

View File

@@ -281,24 +281,24 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
switch (d->type) {
case WordType:
data.append(ByteVector::fromUInt16(d->shortValue, false));
data.append(ByteVector::fromUInt16LE(d->shortValue));
break;
case BoolType:
if(kind == 0) {
data.append(ByteVector::fromUInt32(d->boolValue ? 1 : 0, false));
data.append(ByteVector::fromUInt32LE(d->boolValue ? 1 : 0));
}
else {
data.append(ByteVector::fromUInt16(d->boolValue ? 1 : 0, false));
data.append(ByteVector::fromUInt16LE(d->boolValue ? 1 : 0));
}
break;
case DWordType:
data.append(ByteVector::fromUInt32(d->intValue, false));
data.append(ByteVector::fromUInt32LE(d->intValue));
break;
case QWordType:
data.append(ByteVector::fromUInt64(d->longLongValue, false));
data.append(ByteVector::fromUInt64LE(d->longLongValue));
break;
case UnicodeType:
@@ -317,17 +317,17 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
if(kind == 0) {
data = File::renderString(name, true) +
ByteVector::fromUInt16((int)d->type, false) +
ByteVector::fromUInt16(data.size(), false) +
ByteVector::fromUInt16LE((int)d->type) +
ByteVector::fromUInt16LE(data.size()) +
data;
}
else {
ByteVector nameData = File::renderString(name);
data = ByteVector::fromUInt16(kind == 2 ? d->language : 0, false) +
ByteVector::fromUInt16(d->stream, false) +
ByteVector::fromUInt16(nameData.size(), false) +
ByteVector::fromUInt16((int)d->type, false) +
ByteVector::fromUInt32(data.size(), false) +
data = ByteVector::fromUInt16LE(kind == 2 ? d->language : 0) +
ByteVector::fromUInt16LE(d->stream) +
ByteVector::fromUInt16LE(nameData.size()) +
ByteVector::fromUInt16LE((int)d->type) +
ByteVector::fromUInt32LE(data.size()) +
nameData +
data;
}

View File

@@ -167,7 +167,7 @@ void ASF::File::BaseObject::parse(ASF::File *file, unsigned int size)
ByteVector ASF::File::BaseObject::render(ASF::File * /*file*/)
{
return guid() + ByteVector::fromUInt64(data.size() + 24, false) + data;
return guid() + ByteVector::fromUInt64LE(data.size() + 24) + data;
}
ASF::File::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid)
@@ -187,7 +187,7 @@ ByteVector ASF::File::FilePropertiesObject::guid()
void ASF::File::FilePropertiesObject::parse(ASF::File *file, uint size)
{
BaseObject::parse(file, size);
file->d->properties->setLength((int)(data.mid(40, 8).toInt64(false) / 10000000L - data.mid(56, 8).toInt64(false) / 1000L));
file->d->properties->setLength((int)(data.toInt64LE(40) / 10000000L - data.toInt64LE(56) / 1000L));
}
ByteVector ASF::File::StreamPropertiesObject::guid()
@@ -198,9 +198,9 @@ ByteVector ASF::File::StreamPropertiesObject::guid()
void ASF::File::StreamPropertiesObject::parse(ASF::File *file, uint size)
{
BaseObject::parse(file, size);
file->d->properties->setChannels(data.mid(56, 2).toInt16(false));
file->d->properties->setSampleRate(data.mid(58, 4).toUInt32(false));
file->d->properties->setBitrate(data.mid(62, 4).toUInt32(false) * 8 / 1000);
file->d->properties->setChannels(data.toInt16LE(56));
file->d->properties->setSampleRate(data.toUInt32LE(58));
file->d->properties->setBitrate(data.toInt16LE(62) * 8 / 1000);
}
ByteVector ASF::File::ContentDescriptionObject::guid()
@@ -231,11 +231,11 @@ ByteVector ASF::File::ContentDescriptionObject::render(ASF::File *file)
ByteVector v4 = file->renderString(file->d->tag->comment());
ByteVector v5 = file->renderString(file->d->tag->rating());
data.clear();
data.append(ByteVector::fromUInt16(v1.size(), false));
data.append(ByteVector::fromUInt16(v2.size(), false));
data.append(ByteVector::fromUInt16(v3.size(), false));
data.append(ByteVector::fromUInt16(v4.size(), false));
data.append(ByteVector::fromUInt16(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);
@@ -263,7 +263,7 @@ void ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*
ByteVector ASF::File::ExtendedContentDescriptionObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromUInt16(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(ByteVector::null));
return BaseObject::render(file);
}
@@ -287,7 +287,7 @@ void ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/)
ByteVector ASF::File::MetadataObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromUInt16(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(ByteVector::null));
return BaseObject::render(file);
}
@@ -311,7 +311,7 @@ void ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/)
ByteVector ASF::File::MetadataLibraryObject::render(ASF::File *file)
{
data.clear();
data.append(ByteVector::fromUInt16(attributeData.size(), false));
data.append(ByteVector::fromUInt16LE(attributeData.size()));
data.append(attributeData.toByteVector(ByteVector::null));
return BaseObject::render(file);
}
@@ -361,7 +361,7 @@ ByteVector ASF::File::HeaderExtensionObject::render(ASF::File *file)
for(unsigned int i = 0; i < objects.size(); i++) {
data.append(objects[i]->render(file));
}
data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt32(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);
}
@@ -552,7 +552,7 @@ bool ASF::File::save()
for(unsigned int i = 0; i < d->objects.size(); i++) {
data.append(d->objects[i]->render(this));
}
data = headerGuid + ByteVector::fromUInt64(data.size() + 30, false) + ByteVector::fromUInt32(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data;
data = headerGuid + ByteVector::fromUInt64LE(data.size() + 30) + ByteVector::fromUInt32LE(d->objects.size()) + ByteVector("\x01\x02", 2) + data;
insert(data, 0, (uint)d->size);
return true;
@@ -581,7 +581,7 @@ int ASF::File::readWORD(bool *ok)
return 0;
}
if(ok) *ok = true;
return v.toUInt16(false);
return v.toUInt16LE(0);
}
unsigned int ASF::File::readDWORD(bool *ok)
@@ -592,7 +592,7 @@ unsigned int ASF::File::readDWORD(bool *ok)
return 0;
}
if(ok) *ok = true;
return v.toUInt32(false);
return v.toUInt32LE(0);
}
long long ASF::File::readQWORD(bool *ok)
@@ -603,7 +603,7 @@ long long ASF::File::readQWORD(bool *ok)
return 0;
}
if(ok) *ok = true;
return v.toInt64(false);
return v.toInt64LE(0);
}
String ASF::File::readString(int length)
@@ -624,9 +624,9 @@ String ASF::File::readString(int length)
ByteVector ASF::File::renderString(const String &str, bool includeLength)
{
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromUInt16(0, false);
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromUInt16LE(0);
if(includeLength) {
data = ByteVector::fromUInt16(data.size(), false) + data;
data = ByteVector::fromUInt16LE(data.size()) + data;
}
return data;
}

View File

@@ -148,7 +148,7 @@ ByteVector ASF::Picture::render() const
return ByteVector::null;
return
ByteVector((char)d->type) +
ByteVector::fromUInt32(d->picture.size(), false) +
ByteVector::fromUInt32LE(d->picture.size()) +
ASF::File::renderString(d->mimeType) +
ASF::File::renderString(d->description) +
d->picture;
@@ -161,7 +161,7 @@ void ASF::Picture::parse(const ByteVector& bytes)
return;
size_t pos = 0;
d->type = (Type)bytes[0]; ++pos;
uint dataLen = bytes.mid(pos, 4).toUInt32(false); pos+=4;
uint dataLen = bytes.toUInt32LE(pos); pos+=4;
const ByteVector nullStringTerminator(2, 0);

View File

@@ -197,7 +197,7 @@ bool FLAC::File::save()
for(uint i = 0; i < newBlocks.size(); i++) {
FLAC::MetadataBlock *block = newBlocks[i];
ByteVector blockData = block->render();
ByteVector blockHeader = ByteVector::fromUInt32(blockData.size());
ByteVector blockHeader = ByteVector::fromUInt32BE(blockData.size());
blockHeader[0] = block->code();
data.append(blockHeader);
data.append(blockData);
@@ -210,7 +210,7 @@ bool FLAC::File::save()
if (paddingLength < 0) {
paddingLength = MinPaddingLength;
}
ByteVector padding = ByteVector::fromUInt32(paddingLength);
ByteVector padding = ByteVector::fromUInt32BE(paddingLength);
padding.resize(paddingLength + 4);
padding[0] = (char)(FLAC::MetadataBlock::Padding | LastBlockFlag);
data.append(padding);
@@ -361,7 +361,7 @@ void FLAC::File::scan()
char blockType = header[0] & 0x7f;
bool isLastBlock = (header[0] & 0x80) != 0;
uint length = header.mid(1, 3).toUInt32();
uint length = header.toUInt24BE(1);
// First block should be the stream_info metadata
@@ -381,7 +381,7 @@ void FLAC::File::scan()
header = readBlock(4);
blockType = header[0] & 0x7f;
isLastBlock = (header[0] & 0x80) != 0;
length = header.mid(1, 3).toUInt32();
length = header.toUInt24BE(1);
ByteVector data = readBlock(length);
if(data.size() != length || length == 0) {

View File

@@ -82,10 +82,10 @@ bool FLAC::Picture::parse(const ByteVector &data)
return false;
}
int pos = 0;
d->type = FLAC::Picture::Type(data.mid(pos, 4).toUInt32());
size_t pos = 0;
d->type = FLAC::Picture::Type(data.toUInt32BE(pos));
pos += 4;
uint mimeTypeLength = data.mid(pos, 4).toUInt32();
const uint mimeTypeLength = data.toUInt32BE(pos);
pos += 4;
if(pos + mimeTypeLength + 24 > data.size()) {
debug("Invalid picture block.");
@@ -93,7 +93,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
}
d->mimeType = String(data.mid(pos, mimeTypeLength), String::UTF8);
pos += mimeTypeLength;
uint descriptionLength = data.mid(pos, 4).toUInt32();
const uint descriptionLength = data.toUInt32BE(pos);
pos += 4;
if(pos + descriptionLength + 20 > data.size()) {
debug("Invalid picture block.");
@@ -101,15 +101,15 @@ bool FLAC::Picture::parse(const ByteVector &data)
}
d->description = String(data.mid(pos, descriptionLength), String::UTF8);
pos += descriptionLength;
d->width = data.mid(pos, 4).toUInt32();
d->width = data.toUInt32BE(pos);
pos += 4;
d->height = data.mid(pos, 4).toUInt32();
d->height = data.toUInt32BE(pos);
pos += 4;
d->colorDepth = data.mid(pos, 4).toUInt32();
d->colorDepth = data.toUInt32BE(pos);
pos += 4;
d->numColors = data.mid(pos, 4).toUInt32();
d->numColors = data.toUInt32BE(pos);
pos += 4;
uint dataLength = data.mid(pos, 4).toUInt32();
uint dataLength = data.toUInt32BE(pos);
pos += 4;
if(pos + dataLength > data.size()) {
debug("Invalid picture block.");
@@ -123,18 +123,18 @@ bool FLAC::Picture::parse(const ByteVector &data)
ByteVector FLAC::Picture::render() const
{
ByteVector result;
result.append(ByteVector::fromUInt32(d->type));
result.append(ByteVector::fromUInt32BE(d->type));
ByteVector mimeTypeData = d->mimeType.data(String::UTF8);
result.append(ByteVector::fromUInt32(mimeTypeData.size()));
result.append(ByteVector::fromUInt32BE(mimeTypeData.size()));
result.append(mimeTypeData);
ByteVector descriptionData = d->description.data(String::UTF8);
result.append(ByteVector::fromUInt32(descriptionData.size()));
result.append(ByteVector::fromUInt32BE(descriptionData.size()));
result.append(descriptionData);
result.append(ByteVector::fromUInt32(d->width));
result.append(ByteVector::fromUInt32(d->height));
result.append(ByteVector::fromUInt32(d->colorDepth));
result.append(ByteVector::fromUInt32(d->numColors));
result.append(ByteVector::fromUInt32(d->data.size()));
result.append(ByteVector::fromUInt32BE(d->width));
result.append(ByteVector::fromUInt32BE(d->height));
result.append(ByteVector::fromUInt32BE(d->colorDepth));
result.append(ByteVector::fromUInt32BE(d->numColors));
result.append(ByteVector::fromUInt32BE(d->data.size()));
result.append(d->data);
return result;
}

View File

@@ -132,7 +132,7 @@ void FLAC::Properties::read()
// Maximum frame size (in bytes)
pos += 3;
uint flags = d->data.mid(pos, 4).toUInt32(true);
uint flags = d->data.toUInt32BE(pos);
pos += 4;
d->sampleRate = flags >> 12;
@@ -143,7 +143,7 @@ void FLAC::Properties::read()
// stream length in samples. (Audio files measured in days)
unsigned long long hi = flags & 0xf;
unsigned long long lo = d->data.mid(pos, 4).toUInt32(true);
unsigned long long lo = d->data.toUInt32BE(pos);
pos += 4;
d->sampleFrames = (hi << 32) | lo;

View File

@@ -63,22 +63,22 @@ void Mod::FileBase::writeByte(uchar byte)
void Mod::FileBase::writeU16L(ushort number)
{
writeBlock(ByteVector::fromUInt16(number, false));
writeBlock(ByteVector::fromUInt16LE(number));
}
void Mod::FileBase::writeU32L(uint number)
{
writeBlock(ByteVector::fromUInt32(number, false));
writeBlock(ByteVector::fromUInt32LE(number));
}
void Mod::FileBase::writeU16B(ushort number)
{
writeBlock(ByteVector::fromUInt16(number, true));
writeBlock(ByteVector::fromUInt16BE(number));
}
void Mod::FileBase::writeU32B(uint number)
{
writeBlock(ByteVector::fromUInt32(number, true));
writeBlock(ByteVector::fromUInt32BE(number));
}
bool Mod::FileBase::readByte(uchar &byte)
@@ -93,14 +93,14 @@ bool Mod::FileBase::readU16L(ushort &number)
{
ByteVector data(readBlock(2));
if(data.size() < 2) return false;
number = data.toUInt16(false);
number = data.toUInt16LE(0);
return true;
}
bool Mod::FileBase::readU32L(uint &number) {
ByteVector data(readBlock(4));
if(data.size() < 4) return false;
number = data.toUInt32(false);
number = data.toUInt32LE(0);
return true;
}
@@ -108,13 +108,13 @@ bool Mod::FileBase::readU16B(ushort &number)
{
ByteVector data(readBlock(2));
if(data.size() < 2) return false;
number = data.toUInt16(true);
number = data.toUInt16BE(0);
return true;
}
bool Mod::FileBase::readU32B(uint &number) {
ByteVector data(readBlock(4));
if(data.size() < 4) return false;
number = data.toUInt32(true);
number = data.toUInt32BE(0);
return true;
}

View File

@@ -52,10 +52,10 @@ MP4::Atom::Atom(File *file)
return;
}
length = header.mid(0, 4).toUInt32();
length = header.toUInt32BE(0);
if (length == 1) {
long long longLength = file->readBlock(8).toInt64();
long long longLength = file->readBlock(8).toInt64BE(0);
if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
// The atom has a 64-bit length, but it's actually a 32-bit value
length = (long)longLength;

View File

@@ -103,8 +103,8 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
return;
}
long long unit = data.mid(28, 8).toInt64();
long long length = data.mid(36, 8).toInt64();
const long long unit = data.toInt64BE(28);
const long long length = data.toInt64BE(36);
d->length = unit ? int(length / unit) : 0;
}
else {
@@ -112,8 +112,8 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
return;
}
unsigned int unit = data.mid(20, 4).toUInt32();
unsigned int length = data.mid(24, 4).toUInt32();
const unsigned int unit = data.toUInt32BE(20);
const unsigned int length = data.toUInt32BE(24);
d->length = unit ? length / unit : 0;
}
@@ -125,10 +125,10 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
file->seek(atom->offset);
data = file->readBlock(atom->length);
if(data.mid(20, 4) == "mp4a") {
d->format = PropertiesPrivate::AAC;
d->channels = data.mid(40, 2).toInt16();
d->bitsPerSample = data.mid(42, 2).toInt16();
d->sampleRate = data.mid(46, 4).toUInt32();
d->format = PropertiesPrivate::AAC;
d->channels = data.toInt16BE(40);
d->bitsPerSample = data.toInt16BE(42);
d->sampleRate = data.toUInt32BE(46);
if(data.mid(56, 4) == "esds" && data[64] == 0x03) {
long pos = 65;
if(data.mid(pos, 3) == "\x80\x80\x80") {
@@ -141,7 +141,7 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
pos += 3;
}
pos += 10;
d->bitrate = (data.mid(pos, 4).toUInt32() + 500) / 1000;
d->bitrate = (data.toUInt32BE(pos) + 500) / 1000;
}
}
}
@@ -149,9 +149,9 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
d->format = PropertiesPrivate::ALAC;
if (atom->length == 88 && data.mid(56, 4) == "alac") {
d->bitsPerSample = data.at(69);
d->channels = data.at(73);
d->bitrate = data.mid(80, 4).toUInt32() / 1000;
d->sampleRate = data.mid(84, 4).toUInt32();
d->channels = data.at(73);
d->bitrate = data.toUInt32BE(80) / 1000;
d->sampleRate = data.toUInt32BE(84);
}
}

View File

@@ -112,11 +112,11 @@ MP4::Tag::parseData2(MP4::Atom *atom, TagLib::File *file, int expectedFlags, boo
AtomDataList result;
ByteVector data = file->readBlock(atom->length - 8);
int i = 0;
unsigned int pos = 0;
size_t pos = 0;
while(pos < data.size()) {
int length = data.mid(pos, 4).toUInt32();
int length = data.toUInt32BE(pos);
ByteVector name = data.mid(pos + 4, 4);
int flags = data.mid(pos + 8, 4).toUInt32();
int flags = data.toUInt32BE(pos + 8);
if(freeForm && i < 2) {
if(i == 0 && name != "mean") {
debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\"");
@@ -159,7 +159,7 @@ MP4::Tag::parseInt(MP4::Atom *atom, TagLib::File *file)
{
ByteVectorList data = parseData(atom, file);
if(data.size()) {
d->items.insert(atom->name, (int)data[0].toInt16());
d->items.insert(atom->name, (int)data[0].toInt16BE(0));
}
}
@@ -168,7 +168,7 @@ MP4::Tag::parseUInt(MP4::Atom *atom, TagLib::File *file)
{
ByteVectorList data = parseData(atom, file);
if(data.size()) {
d->items.insert(atom->name, data[0].toUInt32());
d->items.insert(atom->name, data[0].toUInt32BE(0));
}
}
@@ -177,7 +177,7 @@ MP4::Tag::parseLongLong(MP4::Atom *atom, TagLib::File *file)
{
ByteVectorList data = parseData(atom, file);
if(data.size()) {
d->items.insert(atom->name, data[0].toInt64());
d->items.insert(atom->name, data[0].toInt64BE(0));
}
}
@@ -195,7 +195,7 @@ MP4::Tag::parseGnre(MP4::Atom *atom, TagLib::File *file)
{
ByteVectorList data = parseData(atom, file);
if(data.size()) {
const int idx = (int)data[0].toInt16();
const int idx = (int)data[0].toInt16BE(0);
if(!d->items.contains("\251gen") && idx > 0) {
d->items.insert("\251gen", StringList(ID3v1::genre(idx - 1)));
}
@@ -207,8 +207,8 @@ MP4::Tag::parseIntPair(MP4::Atom *atom, TagLib::File *file)
{
ByteVectorList data = parseData(atom, file);
if(data.size()) {
const int a = data[0].mid(2, 2).toInt16();
const int b = data[0].mid(4, 2).toInt16();
const int a = data[0].toInt16BE(2);
const int b = data[0].toInt16BE(4);
d->items.insert(atom->name, MP4::Item(a, b));
}
}
@@ -275,11 +275,11 @@ MP4::Tag::parseCovr(MP4::Atom *atom, TagLib::File *file)
{
MP4::CoverArtList value;
ByteVector data = file->readBlock(atom->length - 8);
unsigned int pos = 0;
size_t pos = 0;
while(pos < data.size()) {
int length = data.mid(pos, 4).toUInt32();
int length = data.toUInt32BE(pos);
ByteVector name = data.mid(pos + 4, 4);
int flags = data.mid(pos + 8, 4).toUInt32();
int flags = data.toUInt32BE(pos + 8);
if(name != "data") {
debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
break;
@@ -309,7 +309,7 @@ MP4::Tag::padIlst(const ByteVector &data, int length)
ByteVector
MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data)
{
return ByteVector::fromUInt32(data.size() + 8) + name + data;
return ByteVector::fromUInt32BE(data.size() + 8) + name + data;
}
ByteVector
@@ -317,7 +317,7 @@ MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &da
{
ByteVector result;
for(unsigned int i = 0; i < data.size(); i++) {
result.append(renderAtom("data", ByteVector::fromUInt32(flags) + ByteVector(4, '\0') + data[i]));
result.append(renderAtom("data", ByteVector::fromUInt32BE(flags) + ByteVector(4, '\0') + data[i]));
}
return renderAtom(name, result);
}
@@ -334,7 +334,7 @@ ByteVector
MP4::Tag::renderInt(const ByteVector &name, MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector::fromUInt16(item.toInt()));
data.append(ByteVector::fromUInt16BE(item.toInt()));
return renderData(name, TypeInteger, data);
}
@@ -342,7 +342,7 @@ ByteVector
MP4::Tag::renderUInt(const ByteVector &name, MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector::fromUInt32(item.toUInt()));
data.append(ByteVector::fromUInt32BE(item.toUInt()));
return renderData(name, TypeInteger, data);
}
@@ -350,7 +350,7 @@ ByteVector
MP4::Tag::renderLongLong(const ByteVector &name, MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector::fromUInt64(item.toLongLong()));
data.append(ByteVector::fromUInt64BE(item.toLongLong()));
return renderData(name, TypeInteger, data);
}
@@ -367,8 +367,8 @@ MP4::Tag::renderIntPair(const ByteVector &name, MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector(2, '\0') +
ByteVector::fromUInt16(item.toIntPair().first) +
ByteVector::fromUInt16(item.toIntPair().second) +
ByteVector::fromUInt16BE(item.toIntPair().first) +
ByteVector::fromUInt16BE(item.toIntPair().second) +
ByteVector(2, '\0'));
return renderData(name, TypeImplicit, data);
}
@@ -378,8 +378,8 @@ MP4::Tag::renderIntPairNoTrailing(const ByteVector &name, MP4::Item &item)
{
ByteVectorList data;
data.append(ByteVector(2, '\0') +
ByteVector::fromUInt16(item.toIntPair().first) +
ByteVector::fromUInt16(item.toIntPair().second));
ByteVector::fromUInt16BE(item.toIntPair().first) +
ByteVector::fromUInt16BE(item.toIntPair().second));
return renderData(name, TypeImplicit, data);
}
@@ -400,7 +400,7 @@ MP4::Tag::renderCovr(const ByteVector &name, MP4::Item &item)
ByteVector data;
MP4::CoverArtList value = item.toCoverArtList();
for(unsigned int i = 0; i < value.size(); i++) {
data.append(renderAtom("data", ByteVector::fromUInt32(value[i].format()) +
data.append(renderAtom("data", ByteVector::fromUInt32BE(value[i].format()) +
ByteVector(4, '\0') + value[i].data()));
}
return renderAtom(name, data);
@@ -415,8 +415,8 @@ MP4::Tag::renderFreeForm(const String &name, MP4::Item &item)
return ByteVector::null;
}
ByteVector data;
data.append(renderAtom("mean", ByteVector::fromUInt32(0) + header[1].data(String::UTF8)));
data.append(renderAtom("name", ByteVector::fromUInt32(0) + header[2].data(String::UTF8)));
data.append(renderAtom("mean", ByteVector::fromUInt32BE(0) + header[1].data(String::UTF8)));
data.append(renderAtom("name", ByteVector::fromUInt32BE(0) + header[2].data(String::UTF8)));
AtomDataType type = item.atomDataType();
if(type == TypeUndefined) {
if(!item.toStringList().isEmpty()) {
@@ -429,13 +429,13 @@ MP4::Tag::renderFreeForm(const String &name, MP4::Item &item)
if(type == TypeUTF8) {
StringList value = item.toStringList();
for(unsigned int i = 0; i < value.size(); i++) {
data.append(renderAtom("data", ByteVector::fromUInt32(type) + ByteVector(4, '\0') + value[i].data(String::UTF8)));
data.append(renderAtom("data", ByteVector::fromUInt32BE(type) + ByteVector(4, '\0') + value[i].data(String::UTF8)));
}
}
else {
ByteVectorList value = item.toByteVectorList();
for(unsigned int i = 0; i < value.size(); i++) {
data.append(renderAtom("data", ByteVector::fromUInt32(type) + ByteVector(4, '\0') + value[i]));
data.append(renderAtom("data", ByteVector::fromUInt32BE(type) + ByteVector(4, '\0') + value[i]));
}
}
return renderAtom("----", data);
@@ -498,21 +498,21 @@ MP4::Tag::save()
void
MP4::Tag::updateParents(AtomList &path, long delta, int ignore)
{
for(unsigned int i = 0; i < path.size() - ignore; i++) {
for(size_t i = 0; i < path.size() - ignore; i++) {
d->file->seek(path[i]->offset);
long size = d->file->readBlock(4).toUInt32();
long size = d->file->readBlock(4).toUInt32BE(0);
// 64-bit
if (size == 1) {
d->file->seek(4, File::Current); // Skip name
long long longSize = d->file->readBlock(8).toInt64();
long long longSize = d->file->readBlock(8).toInt64BE(0);
// Seek the offset of the 64-bit size
d->file->seek(path[i]->offset + 8);
d->file->writeBlock(ByteVector::fromUInt64(longSize + delta));
d->file->writeBlock(ByteVector::fromUInt64BE(longSize + delta));
}
// 32-bit
else {
d->file->seek(path[i]->offset);
d->file->writeBlock(ByteVector::fromUInt32(size + delta));
d->file->writeBlock(ByteVector::fromUInt32BE(size + delta));
}
}
}
@@ -530,36 +530,36 @@ MP4::Tag::updateOffsets(long delta, offset_t offset)
}
d->file->seek(atom->offset + 12);
ByteVector data = d->file->readBlock(atom->length - 12);
unsigned int count = data.mid(0, 4).toUInt32();
unsigned int count = data.toUInt32BE(0);
d->file->seek(atom->offset + 16);
int pos = 4;
size_t pos = 4;
while(count--) {
long o = data.mid(pos, 4).toUInt32();
long o = data.toUInt32BE(pos);
if(o > offset) {
o += delta;
}
d->file->writeBlock(ByteVector::fromUInt32(o));
d->file->writeBlock(ByteVector::fromUInt32BE(o));
pos += 4;
}
}
MP4::AtomList co64 = moov->findall("co64", true);
for(unsigned int i = 0; i < co64.size(); i++) {
for(size_t i = 0; i < co64.size(); i++) {
MP4::Atom *atom = co64[i];
if(atom->offset > offset) {
atom->offset += delta;
}
d->file->seek(atom->offset + 12);
ByteVector data = d->file->readBlock(atom->length - 12);
unsigned int count = data.mid(0, 4).toUInt32();
unsigned int count = data.toUInt32BE(0);
d->file->seek(atom->offset + 16);
int pos = 4;
size_t pos = 4;
while(count--) {
long long o = data.mid(pos, 8).toInt64();
long long o = data.toInt64BE(pos);
if(o > offset) {
o += delta;
}
d->file->writeBlock(ByteVector::fromUInt64(o));
d->file->writeBlock(ByteVector::fromUInt64BE(o));
pos += 8;
}
}
@@ -568,21 +568,21 @@ MP4::Tag::updateOffsets(long delta, offset_t offset)
MP4::Atom *moof = d->atoms->find("moof");
if(moof) {
MP4::AtomList tfhd = moof->findall("tfhd", true);
for(unsigned int i = 0; i < tfhd.size(); i++) {
for(size_t i = 0; i < tfhd.size(); i++) {
MP4::Atom *atom = tfhd[i];
if(atom->offset > offset) {
atom->offset += delta;
}
d->file->seek(atom->offset + 9);
ByteVector data = d->file->readBlock(atom->length - 9);
unsigned int flags = (ByteVector(1, '\0') + data.mid(0, 3)).toUInt32();
unsigned int flags = data.toUInt24BE(0);
if(flags & 1) {
long long o = data.mid(7, 8).toInt64();
long long o = data.toInt64BE(7);
if(o > offset) {
o += delta;
}
d->file->seek(atom->offset + 16);
d->file->writeBlock(ByteVector::fromUInt64(o));
d->file->writeBlock(ByteVector::fromUInt64BE(o));
}
}
}

View File

@@ -155,7 +155,7 @@ int MPC::Properties::albumPeak() const
// private members
////////////////////////////////////////////////////////////////////////////////
unsigned long readSize(File *file, TagLib::uint &sizelength)
unsigned long readSize(File *file, size_t &sizelength)
{
unsigned char tmp;
unsigned long size = 0;
@@ -169,7 +169,7 @@ unsigned long readSize(File *file, TagLib::uint &sizelength)
return size;
}
unsigned long readSize(const ByteVector &data, TagLib::uint &sizelength)
unsigned long readSize(const ByteVector &data, size_t &sizelength)
{
unsigned char tmp;
unsigned long size = 0;
@@ -191,9 +191,9 @@ void MPC::Properties::readSV8(File *file)
while(!readSH && !readRG) {
ByteVector packetType = file->readBlock(2);
uint packetSizeLength = 0;
unsigned long packetSize = readSize(file, packetSizeLength);
unsigned long dataSize = packetSize - 2 - packetSizeLength;
size_t packetSizeLength = 0;
size_t packetSize = readSize(file, packetSizeLength);
size_t dataSize = packetSize - 2 - packetSizeLength;
if(packetType == "SH") {
// Stream Header
@@ -201,13 +201,13 @@ void MPC::Properties::readSV8(File *file)
ByteVector data = file->readBlock(dataSize);
readSH = true;
TagLib::uint pos = 4;
size_t pos = 4;
d->version = data[pos];
pos += 1;
d->sampleFrames = readSize(data.mid(pos), pos);
uint begSilence = readSize(data.mid(pos), pos);
std::bitset<16> flags(TAGLIB_CONSTRUCT_BITSET(data.mid(pos, 2).toUInt16(true)));
std::bitset<16> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt16BE(pos)));
pos += 2;
d->sampleRate = sftable[flags[15] * 4 + flags[14] * 2 + flags[13]];
@@ -228,10 +228,10 @@ void MPC::Properties::readSV8(File *file)
int replayGainVersion = data[0];
if(replayGainVersion == 1) {
d->trackGain = data.mid(1, 2).toUInt32(true);
d->trackPeak = data.mid(3, 2).toUInt32(true);
d->albumGain = data.mid(5, 2).toUInt32(true);
d->albumPeak = data.mid(7, 2).toUInt32(true);
d->trackGain = data.toUInt16BE(1);
d->trackPeak = data.toUInt16BE(3);
d->albumGain = data.toUInt16BE(5);
d->albumPeak = data.toUInt16BE(7);
}
}
@@ -252,18 +252,18 @@ void MPC::Properties::readSV7(const ByteVector &data)
if(d->version < 7)
return;
d->totalFrames = data.mid(4, 4).toUInt32(false);
d->totalFrames = data.toUInt32LE(4);
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.mid(8, 4).toUInt32(false)));
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt32LE(8)));
d->sampleRate = sftable[flags[17] * 2 + flags[16]];
d->channels = 2;
uint gapless = data.mid(5, 4).toUInt32(false);
const uint gapless = data.toUInt32LE(5);
d->trackGain = data.mid(14,2).toInt16(false);
d->trackPeak = data.mid(12,2).toUInt32(false);
d->albumGain = data.mid(18,2).toInt16(false);
d->albumPeak = data.mid(16,2).toUInt32(false);
d->trackGain = data.toUInt16LE(14);
d->trackPeak = data.toUInt16LE(12);
d->albumGain = data.toUInt16LE(18);
d->albumPeak = data.toUInt16LE(16);
// convert gain info
if(d->trackGain != 0) {
@@ -293,7 +293,7 @@ void MPC::Properties::readSV7(const ByteVector &data)
d->sampleFrames = d->totalFrames * 1152 - 576;
}
else {
uint headerData = data.mid(0, 4).toUInt32(false);
uint headerData = data.toUInt32LE(0);
d->bitrate = (headerData >> 23) & 0x01ff;
d->version = (headerData >> 11) & 0x03ff;
@@ -301,9 +301,9 @@ void MPC::Properties::readSV7(const ByteVector &data)
d->channels = 2;
if(d->version >= 5)
d->totalFrames = data.mid(4, 4).toUInt32(false);
d->totalFrames = data.toUInt32LE(4);
else
d->totalFrames = data.mid(6, 2).toUInt32(false);
d->totalFrames = data.toUInt16LE(6);
d->sampleFrames = d->totalFrames * 1152 - 576;
}

View File

@@ -133,17 +133,17 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
d->textEncoding = String::Type(data[0]);
int pos = 1;
size_t pos = 1;
d->mimeType = readStringField(data, String::Latin1, &pos);
d->mimeType = readStringField(data, String::Latin1, pos);
/* Now we need at least two more bytes available */
if (uint(pos) + 1 >= data.size()) {
if (pos + 1 >= data.size()) {
debug("Truncated picture frame.");
return;
}
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->description = readStringField(data, d->textEncoding, &pos);
d->description = readStringField(data, d->textEncoding, pos);
d->data = data.mid(pos);
}
@@ -188,7 +188,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
d->textEncoding = String::Type(data[0]);
int pos = 1;
size_t pos = 1;
String fixedString = String(data.mid(pos, 3), String::Latin1);
pos += 3;
@@ -203,7 +203,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
}
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->description = readStringField(data, d->textEncoding, &pos);
d->description = readStringField(data, d->textEncoding, pos);
d->data = data.mid(pos);
}

View File

@@ -140,11 +140,11 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
d->textEncoding = String::Type(data[0]);
int pos = 1;
size_t pos = 1;
d->mimeType = readStringField(data, String::Latin1, &pos);
d->fileName = readStringField(data, d->textEncoding, &pos);
d->description = readStringField(data, d->textEncoding, &pos);
d->mimeType = readStringField(data, String::Latin1, pos);
d->fileName = readStringField(data, d->textEncoding, pos);
d->description = readStringField(data, d->textEncoding, pos);
d->data = data.mid(pos);
}

View File

@@ -112,14 +112,14 @@ void OwnershipFrame::setTextEncoding(String::Type encoding)
void OwnershipFrame::parseFields(const ByteVector &data)
{
int pos = 0;
size_t pos = 0;
// Get the text encoding
d->textEncoding = String::Type(data[0]);
pos += 1;
// Read the price paid this is a null terminate string
d->pricePaid = readStringField(data, String::Latin1, &pos);
d->pricePaid = readStringField(data, String::Latin1, pos);
// If we don't have at least 8 bytes left then don't parse the rest of the
// data

View File

@@ -100,16 +100,17 @@ void PopularimeterFrame::setCounter(TagLib::uint s)
void PopularimeterFrame::parseFields(const ByteVector &data)
{
int pos = 0, size = int(data.size());
size_t pos = 0;
const size_t size = data.size();
d->email = readStringField(data, String::Latin1, &pos);
d->email = readStringField(data, String::Latin1, pos);
d->rating = 0;
d->counter = 0;
if(pos < size) {
d->rating = (unsigned char)(data[pos++]);
if(pos < size) {
d->counter = data.mid(pos, 4).toUInt32();
d->counter = data.toUInt32BE(pos);
}
}
}
@@ -121,7 +122,7 @@ ByteVector PopularimeterFrame::renderFields() const
data.append(d->email.data(String::Latin1));
data.append(textDelimiter(String::Latin1));
data.append(char(d->rating));
data.append(ByteVector::fromUInt32(d->counter));
data.append(ByteVector::fromUInt32BE(d->counter));
return data;
}

View File

@@ -148,12 +148,12 @@ void RelativeVolumeFrame::setIdentification(const String &s)
void RelativeVolumeFrame::parseFields(const ByteVector &data)
{
int pos = 0;
d->identification = readStringField(data, String::Latin1, &pos);
size_t pos = 0;
d->identification = readStringField(data, String::Latin1, pos);
// Each channel is at least 4 bytes.
while(pos <= (int)data.size() - 4) {
while(pos + 4 <= data.size()) {
ChannelType type = ChannelType(data[pos]);
@@ -161,7 +161,7 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data)
ChannelData &channel = d->channels[type];
channel.volumeAdjustment = data.mid(pos, 2).toInt16();
channel.volumeAdjustment = data.toInt16BE(pos);
pos += 2;
channel.peakVolume.bitsRepresentingPeak = data[pos];
@@ -187,7 +187,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
const ChannelData &channel = (*it).second;
data.append(char(type));
data.append(ByteVector::fromUInt16(channel.volumeAdjustment));
data.append(ByteVector::fromUInt16BE(channel.volumeAdjustment));
data.append(char(channel.peakVolume.bitsRepresentingPeak));
data.append(channel.peakVolume.peakVolume);
}

View File

@@ -124,8 +124,8 @@ void UniqueFileIdentifierFrame::parseFields(const ByteVector &data)
return;
}
int pos = 0;
d->owner = readStringField(data, String::Latin1, &pos);
size_t pos = 0;
d->owner = readStringField(data, String::Latin1, pos);
d->identifier = data.mid(pos);
}

View File

@@ -267,26 +267,21 @@ ByteVector Frame::fieldData(const ByteVector &frameData) const
return frameData.mid(frameDataOffset, frameDataLength);
}
String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position)
String Frame::readStringField(const ByteVector &data, String::Type encoding, size_t &position)
{
int start = 0;
if(!position)
position = &start;
ByteVector delimiter = textDelimiter(encoding);
const size_t end = data.find(delimiter, *position, delimiter.size());
if(end == ByteVector::npos || end < static_cast<size_t>(*position))
const size_t end = data.find(delimiter, position, delimiter.size());
if(end == ByteVector::npos || end < position)
return String::null;
String str;
if(encoding == String::Latin1)
str = Tag::latin1StringHandler()->parse(data.mid(*position, end - *position));
str = Tag::latin1StringHandler()->parse(data.mid(position, end - position));
else
str = String(data.mid(*position, end - *position), encoding);
str = String(data.mid(position, end - position), encoding);
*position = static_cast<int>(end + delimiter.size());
position = end + delimiter.size();
return str;
}
@@ -641,7 +636,7 @@ void Frame::Header::setData(const ByteVector &data, uint version)
return;
}
d->frameSize = data.mid(3, 3).toUInt32();
d->frameSize = data.toUInt24BE(3);
break;
}
@@ -669,7 +664,7 @@ void Frame::Header::setData(const ByteVector &data, uint version)
// Set the size -- the frame size is the four bytes starting at byte four in
// the frame header (structure 4)
d->frameSize = data.mid(4, 4).toUInt32();
d->frameSize = data.toUInt32BE(4);
{ // read the first byte of flags
std::bitset<8> flags(data[8]);
@@ -716,7 +711,7 @@ void Frame::Header::setData(const ByteVector &data, uint version)
// iTunes writes v2.4 tags with v2.3-like frame sizes
if(d->frameSize > 127) {
if(!isValidFrameID(data.mid(d->frameSize + 10, 4))) {
unsigned int uintSize = data.mid(4, 4).toUInt32();
unsigned int uintSize = data.toUInt32BE(4);
if(isValidFrameID(data.mid(uintSize + 10, 4))) {
d->frameSize = uintSize;
}
@@ -830,7 +825,7 @@ ByteVector Frame::Header::render() const
ByteVector v = d->frameID +
(d->version == 3
? ByteVector::fromUInt32(d->frameSize)
? ByteVector::fromUInt32BE(d->frameSize)
: SynchData::fromUInt(d->frameSize)) +
flags;

View File

@@ -223,8 +223,7 @@ namespace TagLib {
* updated to replect the position just after the string that has been read.
* This is useful for reading strings sequentially.
*/
String readStringField(const ByteVector &data, String::Type encoding,
int *positon = 0);
String readStringField(const ByteVector &data, String::Type encoding, size_t &positon);
/*!
* Checks a the list of string values to see if they can be used with the

View File

@@ -49,7 +49,14 @@ TagLib::uint SynchData::toUInt(const ByteVector &data)
// Invalid data; assume this was created by some buggy software that just
// put normal integers here rather than syncsafe ones, and try it that
// way.
sum = (data.size() > 4) ? data.mid(0, 4).toUInt32() : data.toUInt32();
if(data.size() >= 4) {
sum = data.toUInt32BE(0);
}
else {
ByteVector tmp(data);
tmp.resize(4);
sum = tmp.toUInt32BE(0);
}
}
return sum;

View File

@@ -182,7 +182,7 @@ void MPEG::Header::parse(const ByteVector &data)
return;
}
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt32()));
std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt32BE(0)));
// Check for the second byte's part of the MPEG synch

View File

@@ -108,8 +108,8 @@ void MPEG::XingHeader::parse(const ByteVector &data)
return;
}
d->frames = data.mid(8, 4).toUInt32();
d->size = data.mid(12, 4).toUInt32();
d->frames = data.toUInt32BE(8);
d->size = data.toUInt32BE(12);
d->valid = true;
}

View File

@@ -119,7 +119,7 @@ bool Ogg::FLAC::File::save()
// Put the size in the first 32 bit (I assume no more than 24 bit are used)
ByteVector v = ByteVector::fromUInt32(d->xiphCommentData.size());
ByteVector v = ByteVector::fromUInt32BE(d->xiphCommentData.size());
// Set the type of the metadata-block to be a Xiph / Vorbis comment
@@ -241,7 +241,7 @@ void Ogg::FLAC::File::scan()
char blockType = header[0] & 0x7f;
bool lastBlock = (header[0] & 0x80) != 0;
uint length = header.mid(1, 3).toUInt32();
uint length = header.toUInt24BE(1);
overhead += length;
// Sanity: First block should be the stream_info metadata
@@ -264,7 +264,7 @@ void Ogg::FLAC::File::scan()
header = metadataHeader.mid(0, 4);
blockType = header[0] & 0x7f;
lastBlock = (header[0] & 0x80) != 0;
length = header.mid(1, 3).toUInt32();
length = header.toUInt24BE(1);
overhead += length;
if(blockType == 1) {

View File

@@ -188,7 +188,7 @@ ByteVector Ogg::Page::render() const
// the entire page with the 4 bytes reserved for the checksum zeroed and then
// inserted in bytes 22-25 of the page header.
ByteVector checksum = ByteVector::fromUInt32(data.checksum(), false);
ByteVector checksum = ByteVector::fromUInt32LE(data.checksum());
for(int i = 0; i < 4; i++)
data[i + 22] = checksum[i];

View File

@@ -203,15 +203,15 @@ ByteVector Ogg::PageHeader::render() const
// absolute granular position
data.append(ByteVector::fromUInt64(d->absoluteGranularPosition, false));
data.append(ByteVector::fromUInt64LE(d->absoluteGranularPosition));
// stream serial number
data.append(ByteVector::fromUInt32(d->streamSerialNumber, false));
data.append(ByteVector::fromUInt32LE(d->streamSerialNumber));
// page sequence number
data.append(ByteVector::fromUInt32(d->pageSequenceNumber, false));
data.append(ByteVector::fromUInt32LE(d->pageSequenceNumber));
// checksum -- this is left empty and should be filled in by the Ogg::Page
// class
@@ -255,9 +255,9 @@ void Ogg::PageHeader::read()
d->firstPageOfStream = flags.test(1);
d->lastPageOfStream = flags.test(2);
d->absoluteGranularPosition = data.mid(6, 8).toInt64(false);
d->streamSerialNumber = data.mid(14, 4).toUInt32(false);
d->pageSequenceNumber = data.mid(18, 4).toUInt32(false);
d->absoluteGranularPosition = data.toInt64LE(6);
d->streamSerialNumber = data.toUInt32LE(14);
d->pageSequenceNumber = data.toUInt32LE(18);
// Byte number 27 is the number of page segments, which is the only variable
// length portion of the page header. After reading the number of page

View File

@@ -129,11 +129,11 @@ void Opus::Properties::read()
pos += 1;
// *Pre-skip* (16 bits, unsigned, little endian)
ushort preSkip = data.mid(pos, 2).toUInt16(false);
ushort preSkip = data.toUInt16LE(pos);
pos += 2;
// *Input Sample Rate* (32 bits, unsigned, little endian)
d->inputSampleRate = data.mid(pos, 4).toUInt32(false);
d->inputSampleRate = data.toUInt32LE(pos);
pos += 4;
// *Output Gain* (16 bits, signed, little endian)

View File

@@ -113,32 +113,32 @@ void Speex::Properties::read()
ByteVector data = d->file->packet(0);
int pos = 28;
size_t pos = 28;
// speex_version_id; /**< Version for Speex (for checking compatibility) */
d->speexVersion = data.mid(pos, 4).toUInt32(false);
d->speexVersion = data.toUInt32LE(pos);
pos += 4;
// header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */
pos += 4;
// rate; /**< Sampling rate used */
d->sampleRate = data.mid(pos, 4).toUInt32(false);
d->sampleRate = data.toUInt32LE(pos);
pos += 4;
// mode; /**< Mode used (0 for narrowband, 1 for wideband) */
d->mode = data.mid(pos, 4).toUInt32(false);
d->mode = data.toUInt32LE(pos);
pos += 4;
// mode_bitstream_version; /**< Version ID of the bit-stream */
pos += 4;
// nb_channels; /**< Number of channels encoded */
d->channels = data.mid(pos, 4).toUInt32(false);
d->channels = data.toUInt32LE(pos);
pos += 4;
// bitrate; /**< Bit-rate used */
d->bitrate = data.mid(pos, 4).toUInt32(false);
d->bitrate = data.toUInt32LE(pos);
pos += 4;
// frame_size; /**< Size of frames */
@@ -146,7 +146,7 @@ void Speex::Properties::read()
pos += 4;
// vbr; /**< 1 for a VBR encoding, 0 otherwise */
d->vbr = data.mid(pos, 4).toUInt32(false) == 1;
d->vbr = data.toUInt32LE(pos) == 1;
pos += 4;
// frames_per_packet; /**< Number of frames stored per Ogg packet */

View File

@@ -151,22 +151,22 @@ void Ogg::Vorbis::Properties::read()
pos += 7;
d->vorbisVersion = data.mid(pos, 4).toUInt32(false);
d->vorbisVersion = data.toUInt32LE(pos);
pos += 4;
d->channels = uchar(data[pos]);
pos += 1;
d->sampleRate = data.mid(pos, 4).toUInt32(false);
d->sampleRate = data.toUInt32LE(pos);
pos += 4;
d->bitrateMaximum = data.mid(pos, 4).toUInt32(false);
d->bitrateMaximum = data.toUInt32LE(pos);
pos += 4;
d->bitrateNominal = data.mid(pos, 4).toUInt32(false);
d->bitrateNominal = data.toUInt32LE(pos);
pos += 4;
d->bitrateMinimum = data.mid(pos, 4).toUInt32(false);
d->bitrateMinimum = data.toUInt32LE(pos);
// TODO: Later this should be only the "fast" mode.
d->bitrate = d->bitrateNominal;

View File

@@ -286,12 +286,12 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
ByteVector vendorData = d->vendorID.data(String::UTF8);
data.append(ByteVector::fromUInt32(vendorData.size(), false));
data.append(ByteVector::fromUInt32LE(vendorData.size()));
data.append(vendorData);
// Add the number of fields.
data.append(ByteVector::fromUInt32(fieldCount(), false));
data.append(ByteVector::fromUInt32LE(fieldCount()));
// Iterate over the the field lists. Our iterator returns a
// std::pair<String, StringList> where the first String is the field name and
@@ -311,7 +311,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
fieldData.append('=');
fieldData.append((*valuesIt).data(String::UTF8));
data.append(ByteVector::fromUInt32(fieldData.size(), false));
data.append(ByteVector::fromUInt32LE(fieldData.size()));
data.append(fieldData);
}
}
@@ -344,9 +344,9 @@ void Ogg::XiphComment::parse(const ByteVector &data)
// The first thing in the comment data is the vendor ID length, followed by a
// UTF8 string with the vendor ID.
uint pos = 0;
size_t pos = 0;
uint vendorLength = data.mid(0, 4).toUInt32(false);
const uint vendorLength = data.toUInt32LE(0);
pos += 4;
d->vendorID = String(data.mid(pos, vendorLength), String::UTF8);
@@ -354,7 +354,7 @@ void Ogg::XiphComment::parse(const ByteVector &data)
// Next the number of fields in the comment vector.
uint commentFields = data.mid(pos, 4).toUInt32(false);
uint commentFields = data.toUInt32LE(pos);
pos += 4;
if(commentFields > (data.size() - 8) / 4) {
@@ -366,7 +366,7 @@ void Ogg::XiphComment::parse(const ByteVector &data)
// Each comment field is in the format "KEY=value" in a UTF8 string and has
// 4 bytes before the text starts that gives the length.
uint commentLength = data.mid(pos, 4).toUInt32(false);
uint commentLength = data.toUInt32LE(pos);
pos += 4;
String comment = String(data.mid(pos, commentLength), String::UTF8);

View File

@@ -39,8 +39,16 @@
#define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
static double ConvertFromIeeeExtended(unsigned char *bytes)
using namespace TagLib;
static double ConvertFromIeeeExtended(const ByteVector &v, size_t offset)
{
if(offset > v.size() - 10) {
debug("ConvertFromIeeeExtended() - offset is out of range. Returning 0.");
return 0.0;
}
const unsigned char *bytes = reinterpret_cast<const unsigned char*>(v.data() + offset);
double f;
int expon;
unsigned long hiMant, loMant;
@@ -75,8 +83,6 @@ static double ConvertFromIeeeExtended(unsigned char *bytes)
return f;
}
using namespace TagLib;
class RIFF::AIFF::Properties::PropertiesPrivate
{
public:
@@ -150,10 +156,10 @@ TagLib::uint RIFF::AIFF::Properties::sampleFrames() const
void RIFF::AIFF::Properties::read(const ByteVector &data)
{
d->channels = data.mid(0, 2).toInt16();
d->sampleFrames = data.mid(2, 4).toUInt32();
d->sampleWidth = data.mid(6, 2).toInt16();
double sampleRate = ConvertFromIeeeExtended(reinterpret_cast<unsigned char *>(data.mid(8, 10).data()));
d->channels = data.toInt16BE(0);
d->sampleFrames = data.toUInt32BE(2);
d->sampleWidth = data.toInt16BE(6);
double sampleRate = ConvertFromIeeeExtended(data, 8);
d->sampleRate = (int)sampleRate;
d->bitrate = (int)((sampleRate * d->sampleWidth * d->channels) / 1000.0);
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;

View File

@@ -143,7 +143,10 @@ void RIFF::File::setChunkData(uint i, const ByteVector &data)
// First we update the global size
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
insert(ByteVector::fromUInt32(d->size, d->endianness == BigEndian), 4, 4);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt32BE(d->size), 4, 4);
else
insert(ByteVector::fromUInt32LE(d->size), 4, 4);
// Now update the specific chunk
@@ -186,7 +189,10 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo
// First we update the global size
d->size += static_cast<uint>((offset & 1) + data.size() + 8);
insert(ByteVector::fromUInt32(d->size, d->endianness == BigEndian), 4, 4);
if(d->endianness == BigEndian)
insert(ByteVector::fromUInt32BE(d->size), 4, 4);
else
insert(ByteVector::fromUInt32LE(d->size), 4, 4);
// Now add the chunk to the file
@@ -254,16 +260,23 @@ static bool isValidChunkID(const ByteVector &name)
void RIFF::File::read()
{
bool bigEndian = (d->endianness == BigEndian);
d->type = readBlock(4);
d->size = readBlock(4).toUInt32(bigEndian);
if(d->endianness == BigEndian)
d->size = readBlock(4).toUInt32BE(0);
else
d->size = readBlock(4).toUInt32LE(0);
d->format = readBlock(4);
// + 8: chunk header at least, fix for additional junk bytes
while(tell() + 8 <= length()) {
ByteVector chunkName = readBlock(4);
uint chunkSize = readBlock(4).toUInt32(bigEndian);
uint chunkSize;
if(d->endianness == BigEndian)
chunkSize = readBlock(4).toUInt32BE(0);
else
chunkSize = readBlock(4).toUInt32LE(0);
if(!isValidChunkID(chunkName)) {
debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
@@ -310,7 +323,12 @@ void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
combined.append(ByteVector(leadingPadding, '\x00'));
}
combined.append(name);
combined.append(ByteVector::fromUInt32(data.size(), d->endianness == BigEndian));
if(d->endianness == BigEndian)
combined.append(ByteVector::fromUInt32BE(data.size()));
else
combined.append(ByteVector::fromUInt32LE(data.size()));
combined.append(data);
if((data.size() & 0x01) != 0) {
combined.append('\x00');

View File

@@ -215,7 +215,7 @@ ByteVector RIFF::Info::Tag::render() const
continue;
data.append(it->first);
data.append(ByteVector::fromUInt32(text.size() + 1, false));
data.append(ByteVector::fromUInt32LE(text.size() + 1));
data.append(text);
do {
@@ -243,9 +243,9 @@ void RIFF::Info::Tag::setStringHandler(const TagLib::StringHandler *handler)
void RIFF::Info::Tag::parse(const ByteVector &data)
{
uint p = 4;
size_t p = 4;
while(p < data.size()) {
uint size = data.mid(p + 4, 4).toUInt32(false);
uint size = data.toUInt32LE(p + 4);
d->fieldListMap[data.mid(p, 4)] = TagPrivate::stringHandler->parse(data.mid(p + 8, size));
p += ((size + 1) & ~1) + 8;

View File

@@ -115,12 +115,12 @@ TagLib::uint RIFF::WAV::Properties::sampleFrames() const
void RIFF::WAV::Properties::read(const ByteVector &data)
{
d->format = data.mid(0, 2).toInt16(false);
d->channels = data.mid(2, 2).toInt16(false);
d->sampleRate = data.mid(4, 4).toUInt32(false);
d->sampleWidth = data.mid(14, 2).toInt16(false);
d->format = data.toInt16LE(0);
d->channels = data.toInt16LE(2);
d->sampleRate = data.toUInt32LE(4);
d->sampleWidth = data.toInt16LE(14);
uint byteRate = data.mid(8, 4).toUInt32(false);
const uint byteRate = data.toUInt32LE(8);
d->bitrate = byteRate * 8 / 1000;
d->length = byteRate > 0 ? d->streamLength / byteRate : 0;

View File

@@ -26,6 +26,8 @@
#ifndef TAGLIB_H
#define TAGLIB_H
#include "config.h"
#define TAGLIB_MAJOR_VERSION 1
#define TAGLIB_MINOR_VERSION 8
#define TAGLIB_PATCH_VERSION 0
@@ -77,28 +79,52 @@
# error TagLib assumes that long long is 64-bit wide.
#endif
// Check the widths of integral types.
// Optimized byte swap functions.
#if UCHAR_MAX != 255U
# error TagLib assumes that char is 8-bit wide.
#if defined(HAVE_MSC_BYTESWAP)
# include <stdlib.h>
#elif defined(HAVE_GLIBC_BYTESWAP)
# include <byteswap.h>
#elif defined(HAVE_MAC_BYTESWAP)
# include <libkern/OSByteOrder.h>
#elif defined(HAVE_OPENBSD_BYTESWAP)
# include <sys/endian.h>
#endif
#if USHRT_MAX != 65535U
# error TagLib assumes that short is 16-bit wide.
#if defined(HAVE_GCC_BYTESWAP_16)
# define TAGLIB_BYTESWAP_16(x) __builtin_bswap16(x)
#elif defined(HAVE_MSC_BYTESWAP)
# define TAGLIB_BYTESWAP_16(x) _byteswap_ushort(x)
#elif defined(HAVE_GLIBC_BYTESWAP)
# define TAGLIB_BYTESWAP_16(x) __bswap_16(x)
#elif defined(HAVE_MAC_BYTESWAP)
# define TAGLIB_BYTESWAP_16(x) OSSwapInt16(x)
#elif defined(HAVE_OPENBSD_BYTESWAP)
# define TAGLIB_BYTESWAP_16(x) swap16(x)
#endif
#if UINT_MAX != 4294967295U
# error TagLib assumes that int is 32-bit wide.
#if defined(HAVE_GCC_BYTESWAP_32)
# define TAGLIB_BYTESWAP_32(x) __builtin_bswap32(x)
#elif defined(HAVE_MSC_BYTESWAP)
# define TAGLIB_BYTESWAP_32(x) _byteswap_ulong(x)
#elif defined(HAVE_GLIBC_BYTESWAP)
# define TAGLIB_BYTESWAP_32(x) __bswap_32(x)
#elif defined(HAVE_MAC_BYTESWAP)
# define TAGLIB_BYTESWAP_32(x) OSSwapInt32(x)
#elif defined(HAVE_OPENBSD_BYTESWAP)
# define TAGLIB_BYTESWAP_32(x) swap32(x)
#endif
#if !defined(ULLONG_MAX) && !defined(ULONGLONG_MAX) && !defined(ULONG_LONG_MAX)
# error TagLib assumes that long long is 64-bit wide.
#elif defined(ULLONG_MAX) && ULLONG_MAX != 18446744073709551615ULL
# error TagLib assumes that long long is 64-bit wide.
#elif defined(ULONGLONG_MAX) && ULONGLONG_MAX != 18446744073709551615ULL
# error TagLib assumes that long long is 64-bit wide.
#elif defined(ULONG_LONG_MAX) && ULONG_LONG_MAX != 18446744073709551615ULL
# error TagLib assumes that long long is 64-bit wide.
#if defined(HAVE_GCC_BYTESWAP_64)
# define TAGLIB_BYTESWAP_64(x) __builtin_bswap64(x)
#elif defined(HAVE_MSC_BYTESWAP)
# define TAGLIB_BYTESWAP_64(x) _byteswap_uint64(x)
#elif defined(HAVE_GLIBC_BYTESWAP)
# define TAGLIB_BYTESWAP_64(x) __bswap_64(x)
#elif defined(HAVE_MAC_BYTESWAP)
# define TAGLIB_BYTESWAP_64(x) OSSwapInt64(x)
#elif defined(HAVE_OPENBSD_BYTESWAP)
# define TAGLIB_BYTESWAP_64(x) swap64(x)
#endif
//! A namespace for all TagLib related classes and functions

View File

@@ -1,197 +0,0 @@
/***************************************************************************
copyright : (C) 2013 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 "taglib.h"
#include "tbyteswap.h"
// Determines if compiler intrinsic functions are available.
// MSVC: Intrinsic _byteswap_* functions.
#if defined(_MSC_VER) && _MSC_VER >= 1400
# include <stdlib.h>
# define TAGLIB_BYTESWAP_MSC
// GCC 4.8 or above: __builtin_bswap16(), 32 and 64.
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
# define TAGLIB_BYTESWAP_GCC 2
// GCC 4.3 or above: __builtin_bswap16 is missing.
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
# define TAGLIB_BYTESWAP_GCC 1
#endif
// Determines if platform or library specific functions are available.
#if defined(__APPLE__)
# include <libkern/OSByteOrder.h>
# define TAGLIB_BYTESWAP_MAC
#elif defined(__OpenBSD__)
# include <sys/endian.h>
# define TAGLIB_BYTESWAP_OPENBSD
#elif defined(__GLIBC__)
# include <byteswap.h>
# define TAGLIB_BYTESWAP_GLIBC
#endif
// Determines CPU byte order at compile time rather than run time if possible.
#if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))) \
|| (defined(__GNUC__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \
|| (defined(__clang__) && defined(__LITTLE_ENDIAN__))
# define TAGLIB_LITTLE_ENDIAN
#elif (defined(__GNUC__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) \
|| (defined(__clang__) && defined(__BIG_ENDIAN__))
# define TAGLIB_BIG_ENDIAN
#else
namespace {
bool isLittleEndian()
{
TagLib::ushort x = 1;
return (*reinterpret_cast<TagLib::uchar*>(&x) == 1);
}
}
#endif
namespace TagLib
{
ushort byteSwap16(ushort x)
{
#if defined(TAGLIB_BYTESWAP_MSC)
return _byteswap_ushort(x);
#elif defined(TAGLIB_BYTESWAP_GCC) && TAGLIB_BYTESWAP_GCC == 2
return __builtin_bswap16(x);
#elif defined(TAGLIB_BYTESWAP_MAC)
return OSSwapInt16(x);
#elif defined(TAGLIB_BYTESWAP_OPENBSD)
return swap16(x);
#elif defined(TAGLIB_BYTESWAP_GLIBC)
return __bswap_16(x);
#else
return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
#endif
}
uint byteSwap32(uint x)
{
#if defined(TAGLIB_BYTESWAP_MSC)
return _byteswap_ulong(x);
#elif defined(TAGLIB_BYTESWAP_GCC)
return __builtin_bswap32(x);
#elif defined(TAGLIB_BYTESWAP_MAC)
return OSSwapInt32(x);
#elif defined(TAGLIB_BYTESWAP_OPENBSD)
return swap32(x);
#elif defined(TAGLIB_BYTESWAP_GLIBC)
return __bswap_32(x);
#else
return ((x & 0xff000000) >> 24)
| ((x & 0x00ff0000) >> 8)
| ((x & 0x0000ff00) << 8)
| ((x & 0x000000ff) << 24);
#endif
}
ulonglong byteSwap64(ulonglong x)
{
#if defined(TAGLIB_BYTESWAP_MSC)
return _byteswap_uint64(x);
#elif defined(TAGLIB_BYTESWAP_GCC)
return __builtin_bswap64(x);
#elif defined(TAGLIB_BYTESWAP_MAC)
return OSSwapInt64(x);
#elif defined(TAGLIB_BYTESWAP_OPENBSD)
return swap64(x);
#elif defined(TAGLIB_BYTESWAP_GLIBC)
return __bswap_64(x);
#else
return ((x & 0xff00000000000000ull) >> 56)
| ((x & 0x00ff000000000000ull) >> 40)
| ((x & 0x0000ff0000000000ull) >> 24)
| ((x & 0x000000ff00000000ull) >> 8)
| ((x & 0x00000000ff000000ull) << 8)
| ((x & 0x0000000000ff0000ull) << 24)
| ((x & 0x000000000000ff00ull) << 40)
| ((x & 0x00000000000000ffull) << 56);
#endif
}
#if defined(TAGLIB_LITTLE_ENDIAN)
const bool isLittleEndianSystem = true;
#elif defined(TAGLIB_BIG_ENDIAN)
const bool isLittleEndianSystem = false;
#else
const bool isLittleEndianSystem = isLittleEndianSystem();
#endif
}

View File

@@ -1,55 +0,0 @@
/***************************************************************************
copyright : (C) 2013 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_BYTESWAP_H
#define TAGLIB_BYTESWAP_H
namespace TagLib
{
// Cross-platform byte order conversion functions.
/*!
* Converts the byte order of \a x as a 16-bit unsigned integer.
*/
ushort byteSwap16(ushort x);
/*!
* Converts the byte order of \a x as a 32-bit unsigned integer.
*/
uint byteSwap32(uint x);
/*!
* Converts the byte order of \a x as a 64-bit unsigned integer.
*/
ulonglong byteSwap64(ulonglong x);
/*!
* Indicates the system byte order.
* \a true if little endian, \a false if big endian.
*/
extern const bool isLittleEndianSystem;
}
#endif

View File

@@ -29,7 +29,6 @@
#include <string.h>
#include "tbytevector.h"
#include "tbyteswap.h"
// This is a bit ugly to keep writing over and over again.
@@ -175,7 +174,7 @@ size_t findVector(
}
template <class T>
T byteSwap(T x)
inline T byteSwap(T x)
{
// There should be all counterparts of to*() and from*() overloads for integral types.
debug("byteSwap<T>() -- Non specialized version should not be called");
@@ -183,57 +182,129 @@ T byteSwap(T x)
}
template <>
ushort byteSwap<ushort>(ushort x)
inline ushort byteSwap<ushort>(ushort x)
{
return byteSwap16(x);
#ifdef TAGLIB_BYTESWAP_16
return TAGLIB_BYTESWAP_16(x);
#else
return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
#endif
}
template <>
uint byteSwap<uint>(uint x)
inline uint byteSwap<uint>(uint x)
{
return byteSwap32(x);
#ifdef TAGLIB_BYTESWAP_32
return TAGLIB_BYTESWAP_32(x);
#else
return ((x & 0xff000000u) >> 24)
| ((x & 0x00ff0000u) >> 8)
| ((x & 0x0000ff00u) << 8)
| ((x & 0x000000ffu) << 24);
#endif
}
template <>
ulonglong byteSwap<ulonglong>(ulonglong x)
inline ulonglong byteSwap<ulonglong>(ulonglong x)
{
return byteSwap64(x);
#ifdef TAGLIB_BYTESWAP_64
return TAGLIB_BYTESWAP_64(x);
#else
return ((x & 0xff00000000000000ull) >> 56)
| ((x & 0x00ff000000000000ull) >> 40)
| ((x & 0x0000ff0000000000ull) >> 24)
| ((x & 0x000000ff00000000ull) >> 8)
| ((x & 0x00000000ff000000ull) << 8)
| ((x & 0x0000000000ff0000ull) << 24)
| ((x & 0x000000000000ff00ull) << 40)
| ((x & 0x00000000000000ffull) << 56);
#endif
}
template <class T>
T toNumber(const ByteVector &v, bool mostSignificantByteFirst)
namespace {
enum Endianness {
LittleEndian,
BigEndian
};
}
template <typename T, size_t LENGTH, Endianness ENDIAN>
inline T toNumber(const ByteVector &v, size_t offset)
{
if(v.isEmpty()) {
debug("toNumber<T>() -- data is empty, returning 0");
#ifdef TAGLIB_LITTLE_ENDIAN
static const bool swap = (ENDIAN == BigEndian);
#else
static const bool swap = (ENDIAN == LittleEndian);
#endif
if(offset + LENGTH > v.size()) {
debug("toNumber<T>() -- offset is out of range. Returning 0.");
return 0;
}
if(v.size() >= sizeof(T)) {
if(isLittleEndianSystem == mostSignificantByteFirst)
return byteSwap<T>(*reinterpret_cast<const T*>(v.data()));
if(LENGTH >= sizeof(T)) {
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
T tmp;
::memcpy(&tmp, v.data() + offset, sizeof(T));
if(swap)
return byteSwap<T>(tmp);
else
return *reinterpret_cast<const T*>(v.data());
return tmp;
}
else {
T sum = 0;
for(size_t i = 0; i < v.size(); i++) {
const size_t shift = (mostSignificantByteFirst ? v.size() - 1 - i : i) * 8;
sum |= static_cast<T>(static_cast<uchar>(v[i]) << shift);
for(size_t i = 0; i < LENGTH; i++) {
const size_t shift = (ENDIAN == LittleEndian ? i : LENGTH - 1 - i) * 8;
sum |= static_cast<T>(static_cast<uchar>(v[offset + i])) << shift;
}
return sum;
}
}
template <class T>
ByteVector fromNumber(T value, bool mostSignificantByteFirst)
template <typename T, Endianness ENDIAN>
inline ByteVector fromNumber(T value)
{
const size_t size = sizeof(T);
#ifdef TAGLIB_LITTLE_ENDIAN
static const bool swap = (ENDIAN == BigEndian);
#else
static const bool swap = (ENDIAN == LittleEndian);
#endif
if(isLittleEndianSystem == mostSignificantByteFirst)
if(swap)
value = byteSwap<T>(value);
return ByteVector(reinterpret_cast<const char *>(&value), size);
return ByteVector(reinterpret_cast<const char *>(&value), sizeof(T));
}
template <class T, bool IS_LITTLE_ENDIAN>
inline void appendNumber(ByteVector &v, T value)
{
#ifdef TAGLIB_LITTLE_ENDIAN
static const bool swap = !IS_LITTLE_ENDIAN;
#else
static const bool swap = IS_LITTLE_ENDIAN;
#endif
if(swap)
value = byteSwap<T>(value);
const size_t offset = v.size();
v.resize(offset + sizeof(T));
::memcpy(v.data() + offset, reinterpret_cast<const char *>(&value), sizeof(T));
}
class DataPrivate
@@ -341,19 +412,34 @@ ByteVector ByteVector::fromCString(const char *s, size_t length)
return ByteVector(s, length);
}
ByteVector ByteVector::fromUInt16(size_t value, bool mostSignificantByteFirst)
ByteVector ByteVector::fromUInt16LE(size_t value)
{
return fromNumber<ushort>(static_cast<ushort>(value), mostSignificantByteFirst);
return fromNumber<ushort, LittleEndian>(static_cast<ushort>(value));
}
ByteVector ByteVector::fromUInt32(size_t value, bool mostSignificantByteFirst)
ByteVector ByteVector::fromUInt16BE(size_t value)
{
return fromNumber<uint>(static_cast<uint>(value), mostSignificantByteFirst);
return fromNumber<ushort, BigEndian>(static_cast<ushort>(value));
}
ByteVector ByteVector::fromUInt64(ulonglong value, bool mostSignificantByteFirst)
ByteVector ByteVector::fromUInt32LE(size_t value)
{
return fromNumber<ulonglong>(value, mostSignificantByteFirst);
return fromNumber<uint, LittleEndian>(static_cast<uint>(value));
}
ByteVector ByteVector::fromUInt32BE(size_t value)
{
return fromNumber<uint, BigEndian>(static_cast<uint>(value));
}
ByteVector ByteVector::fromUInt64LE(ulonglong value)
{
return fromNumber<ulonglong, LittleEndian>(value);
}
ByteVector ByteVector::fromUInt64BE(ulonglong value)
{
return fromNumber<ulonglong, BigEndian>(value);
}
////////////////////////////////////////////////////////////////////////////////
@@ -593,6 +679,12 @@ ByteVector &ByteVector::append(const ByteVector &v)
return *this;
}
ByteVector &ByteVector::append(char c)
{
resize(size() + 1, c);
return *this;
}
ByteVector &ByteVector::clear()
{
detach();
@@ -677,26 +769,57 @@ TagLib::uint ByteVector::checksum() const
return sum;
}
TagLib::uint ByteVector::toUInt32(bool mostSignificantByteFirst) const
short ByteVector::toInt16LE(size_t offset) const
{
return toNumber<uint>(*this, mostSignificantByteFirst);
return static_cast<short>(toNumber<ushort, 2, LittleEndian>(*this, offset));
}
short ByteVector::toInt16(bool mostSignificantByteFirst) const
short ByteVector::toInt16BE(size_t offset) const
{
return toNumber<unsigned short>(*this, mostSignificantByteFirst);
return static_cast<short>(toNumber<ushort, 2, BigEndian>(*this, offset));
}
unsigned short ByteVector::toUInt16(bool mostSignificantByteFirst) const
ushort ByteVector::toUInt16LE(size_t offset) const
{
return toNumber<unsigned short>(*this, mostSignificantByteFirst);
return toNumber<ushort, 2, LittleEndian>(*this, offset);
}
long long ByteVector::toInt64(bool mostSignificantByteFirst) const
ushort ByteVector::toUInt16BE(size_t offset) const
{
return toNumber<unsigned long long>(*this, mostSignificantByteFirst);
return toNumber<ushort, 2, BigEndian>(*this, offset);
}
uint ByteVector::toUInt24LE(size_t offset) const
{
return toNumber<uint, 3, LittleEndian>(*this, offset);
}
uint ByteVector::toUInt24BE(size_t offset) const
{
return toNumber<uint, 3, BigEndian>(*this, offset);
}
uint ByteVector::toUInt32LE(size_t offset) const
{
return toNumber<uint, 4, LittleEndian>(*this, offset);
}
uint ByteVector::toUInt32BE(size_t offset) const
{
return toNumber<uint, 4, BigEndian>(*this, offset);
}
long long ByteVector::toInt64LE(size_t offset) const
{
return static_cast<long long>(toNumber<ulonglong, 8, LittleEndian>(*this, offset));
}
long long ByteVector::toInt64BE(size_t offset) const
{
return static_cast<long long>(toNumber<ulonglong, 8, BigEndian>(*this, offset));
}
const char &ByteVector::operator[](size_t index) const
{
return d->data->data[d->offset + index];

View File

@@ -212,6 +212,11 @@ namespace TagLib {
*/
ByteVector &append(const ByteVector &v);
/*!
* Appends \a c to the end of the ByteVector.
*/
ByteVector &append(char c);
/*!
* Clears the data.
*/
@@ -291,84 +296,132 @@ namespace TagLib {
uint checksum() const;
/*!
* Converts the first 2 bytes of the vector to a short.
* 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 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromUInt16()
* \see fromUInt16LE()
*/
short toInt16(bool mostSignificantByteFirst = true) const;
short toInt16LE(size_t offset) const;
/*!
* Converts the first 2 bytes of the vector to a unsigned short.
* 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 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1.
*
* \see fromUInt16()
* \see fromUInt16BE()
*/
unsigned short toUInt16(bool mostSignificantByteFirst = true) const;
/*!
* Converts the first 4 bytes of the vector to an unsigned integer.
*
* If \a mostSignificantByteFirst is true this will operate left to right
* evaluating the integer. For example if \a mostSignificantByteFirst is
* true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 ==
* 0x01000000 == 1.
*
* \see fromUInt32()
*/
uint toUInt32(bool mostSignificantByteFirst = true) const;
short toInt16BE(size_t offset) const;
/*!
* Converts the first 8 bytes of the vector to a (signed) long long.
* Converts the 2 bytes at \a offset of the vector to a ushort 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 00 00 00 00 01 == 0x0000000000000001 == 1,
* if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1.
*
* \see fromUInt64()
* \see fromUInt16LE()
*/
long long toInt64(bool mostSignificantByteFirst = true) const;
ushort toUInt16LE(size_t offset) const;
/*!
* 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.
* Converts the 2 bytes at \a offset of the vector to a ushort as an unsigned
* 16-bit big-endian integer.
*
* \see fromUInt16BE()
*/
ushort toUInt16BE(size_t offset) const;
/*!
* Converts the 3 bytes at \a offset of the vector to a uint as an unsigned
* 24-bit little-endian integer.
*/
uint toUInt24LE(size_t offset) const;
/*!
* Converts the 3 bytes at \a offset of the vector to a uint as an unsigned
* 24-bit big-endian integer.
*/
uint toUInt24BE(size_t offset) const;
/*!
* Converts the 4 bytes at \a offset of the vector to a uint as an unsigned
* 32-bit little-endian integer.
*
* \see fromUInt32LE()
*/
uint toUInt32LE(size_t offset) const;
/*!
* Converts the 4 bytes at \a offset of the vector to a ushort as an unsigned
* 32-bit big-endian integer.
*
* \see fromUInt32BE()
*/
uint toUInt32BE(size_t offset) const;
/*!
* Converts the 8 bytes at \a offset of the vector to a long long as a signed
* 64-bit little-endian integer.
*
* \see fromUInt64LE()
*/
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;
/*!
* Creates a 2 byte ByteVector based on \a value as an unsigned 16-bit
* little-endian integer.
*
* \note If \a value is larger than 16-bit, the lowest 16 bits are used.
* \see toInt16()
* \see toUInt16LE()
*/
static ByteVector fromUInt16(size_t value, bool mostSignificantByteFirst = true);
static ByteVector fromUInt16LE(size_t value);
/*!
* 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
* big-endian integer.
*
* \note If \a value is larger than 16-bit, the lowest 16 bits are used.
* \see toUInt16BE()
*/
static ByteVector fromUInt16BE(size_t value);
/*!
* Creates a 4 byte ByteVector based on \a value as an unsigned 32-bit
* little-endian integer.
*
* \note If \a value is larger than 32-bit, the lowest 32 bits are used.
* \see toUInt32()
* \see toUInt32LE()
*/
static ByteVector fromUInt32(size_t value, bool mostSignificantByteFirst = true);
static ByteVector fromUInt32LE(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
* big-endian integer.
*
* \see toInt64()
* \note If \a value is larger than 32-bit, the lowest 32 bits are used.
* \see toUInt32BE()
*/
static ByteVector fromUInt64(ulonglong value, bool mostSignificantByteFirst = true);
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(ulonglong value);
/*!
* Creates a 8 byte ByteVector based on \a value as an unsigned 64-bit
* big-endian integer.
*
* \see toUInt64BE()
*/
static ByteVector fromUInt64BE(ulonglong value);
/*!
* Returns a ByteVector based on the CString \a s.

View File

@@ -32,7 +32,6 @@
#include "tstring.h"
#include "tdebug.h"
#include "tstringlist.h"
#include "tbyteswap.h"
#include <string.h>
@@ -45,7 +44,20 @@
# include "unicode.h"
#endif
namespace {
namespace
{
inline TagLib::ushort byteSwap(TagLib::ushort x)
{
#ifdef TAGLIB_BYTESWAP_16
return TAGLIB_BYTESWAP_16(x);
#else
return((x >> 8) & 0xff) | ((x & 0xff) << 8);
#endif
}
inline unsigned short combine(unsigned char c1, unsigned char c2)
{
@@ -812,7 +824,7 @@ void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
if(swap) {
for(size_t i = 0; i < length; ++i)
d->data[i] = byteSwap16(static_cast<unsigned short>(s[i]));
d->data[i] = byteSwap(static_cast<unsigned short>(s[i]));
}
}
@@ -858,7 +870,15 @@ void String::copyFromUTF16(const char *s, size_t length, Type t)
internalCopyFromUTF16<sizeof(wchar_t)>(s, length, t);
}
const String::Type String::WCharByteOrder = isLittleEndianSystem ? String::UTF16LE : String::UTF16BE;
#ifdef TAGLIB_LITTLE_ENDIAN
const String::Type String::WCharByteOrder = String::UTF16LE;
#else
const String::Type String::WCharByteOrder = String::UTF16BE;
#endif
////////////////////////////////////////////////////////////////////////////////
// related functions

View File

@@ -133,16 +133,16 @@ void TrueAudio::Properties::read()
// Skip the audio format
pos += 2;
d->channels = d->data.mid(pos, 2).toInt16(false);
d->channels = d->data.toInt16LE(pos);
pos += 2;
d->bitsPerSample = d->data.mid(pos, 2).toInt16(false);
d->bitsPerSample = d->data.toInt16LE(pos);
pos += 2;
d->sampleRate = d->data.mid(pos, 4).toUInt32(false);
d->sampleRate = d->data.toUInt32LE(pos);
pos += 4;
d->sampleFrames = d->data.mid(pos, 4).toUInt32(false);
d->sampleFrames = d->data.toUInt32LE(pos);
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;

View File

@@ -141,17 +141,17 @@ void WavPack::Properties::read()
if(!d->data.startsWith("wvpk"))
return;
d->version = d->data.mid(8, 2).toInt16(false);
d->version = d->data.toInt16LE(8);
if(d->version < MIN_STREAM_VERS || d->version > MAX_STREAM_VERS)
return;
unsigned int flags = d->data.mid(24, 4).toUInt32(false);
const uint flags = d->data.toUInt32LE(24);
d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 -
((flags & SHIFT_MASK) >> SHIFT_LSB);
d->sampleRate = sample_rates[(flags & SRATE_MASK) >> SRATE_LSB];
d->channels = (flags & MONO_FLAG) ? 1 : 2;
unsigned int samples = d->data.mid(12, 4).toUInt32(false);
uint samples = d->data.toUInt32LE(12);
if(samples == ~0u) {
if(d->style != Fast) {
samples = seekFinalIndex();
@@ -179,14 +179,14 @@ unsigned int WavPack::Properties::seekFinalIndex()
ByteVector data = d->file->readBlock(32);
if(data.size() != 32)
return 0;
int version = data.mid(8, 2).toInt16(false);
const int version = data.toInt16LE(8);
if(version < MIN_STREAM_VERS || version > MAX_STREAM_VERS)
continue;
unsigned int flags = data.mid(24, 4).toUInt32(false);
const uint flags = data.toUInt32LE(24);
if(!(flags & FINAL_BLOCK))
return 0;
unsigned int blockIndex = data.mid(16, 4).toUInt32(false);
unsigned int blockSamples = data.mid(20, 4).toUInt32(false);
const uint blockIndex = data.toUInt32LE(16);
const uint blockSamples = data.toUInt32LE(20);
return blockIndex + blockSamples;
}

View File

@@ -188,7 +188,12 @@ public:
uint read(TagLib::File &file, uint limit)
{
ByteVector data = file.readBlock(std::min(2U,limit));
value = data.toUInt16(bigEndian);
if(bigEndian)
value = data.toUInt16BE(0);
else
value = data.toUInt16LE(0);
return static_cast<uint>(data.size());
}
@@ -209,7 +214,12 @@ public:
uint read(TagLib::File &file, uint limit)
{
ByteVector data = file.readBlock(std::min(4U,limit));
value = data.toUInt32(bigEndian);
if(bigEndian)
value = data.toUInt32BE(0);
else
value = data.toUInt32LE(0);
return static_cast<uint>(data.size());
}

View File

@@ -38,29 +38,12 @@ class TestByteVector : public CppUnit::TestFixture
CPPUNIT_TEST(testRfind1);
CPPUNIT_TEST(testRfind2);
CPPUNIT_TEST(testToHex);
CPPUNIT_TEST(testToUShort);
CPPUNIT_TEST(testNumericCoversion);
CPPUNIT_TEST(testReplace);
CPPUNIT_TEST_SUITE_END();
public:
void testConversion(unsigned int i, unsigned char a, unsigned char b, unsigned char c, unsigned char d)
{
ByteVector v(4, 0);
v[3] = a;
v[2] = b;
v[1] = c;
v[0] = d;
CPPUNIT_ASSERT(v.toUInt32(false) == i);
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
CPPUNIT_ASSERT(v.toUInt32() == i);
}
void testByteVector()
{
ByteVector v("foobar");
@@ -68,32 +51,6 @@ public:
CPPUNIT_ASSERT(v.find("ob") == 2);
CPPUNIT_ASSERT(v.find('b') == 3);
ByteVector n(4, 0);
n[0] = 1;
CPPUNIT_ASSERT(n.toUInt32(true) == 16777216);
CPPUNIT_ASSERT(n.toUInt32(false) == 1);
CPPUNIT_ASSERT(ByteVector::fromUInt32(16777216, true) == n);
CPPUNIT_ASSERT(ByteVector::fromUInt32(1, false) == n);
CPPUNIT_ASSERT(ByteVector::fromUInt32(0xa0).toUInt32() == 0xa0);
testConversion(0x000000a0, 0x00, 0x00, 0x00, 0xa0);
testConversion(0xd50bf072, 0xd5, 0x0b, 0xf0, 0x72);
ByteVector intVector(2, 0);
intVector[0] = char(0xfc);
intVector[1] = char(0x00);
CPPUNIT_ASSERT(intVector.toInt16() == -1024);
intVector[0] = char(0x04);
intVector[1] = char(0x00);
CPPUNIT_ASSERT(intVector.toInt16() == 1024);
CPPUNIT_ASSERT(ByteVector::fromUInt64(1).toInt64() == 1);
CPPUNIT_ASSERT(ByteVector::fromUInt64(0).toInt64() == 0);
CPPUNIT_ASSERT(ByteVector::fromUInt64(0xffffffffffffffffLL).toInt64() == -1);
CPPUNIT_ASSERT(ByteVector::fromUInt64(0xfffffffffffffffeLL).toInt64() == -2);
CPPUNIT_ASSERT(ByteVector::fromUInt64(1024).toInt64() == 1024);
ByteVector a1("foo");
a1.append("bar");
CPPUNIT_ASSERT(a1 == "foobar");
@@ -183,13 +140,43 @@ public:
CPPUNIT_ASSERT_EQUAL(ByteVector("f0e1d2c3b4a5968778695a4b3c2d1e0f"), v.toHex());
}
void testToUShort()
void testNumericCoversion()
{
CPPUNIT_ASSERT_EQUAL((unsigned short)0xFFFF, ByteVector("\xff\xff", 2).toUInt16());
CPPUNIT_ASSERT_EQUAL((unsigned short)0x0001, ByteVector("\x00\x01", 2).toUInt16());
CPPUNIT_ASSERT_EQUAL((unsigned short)0x0100, ByteVector("\x00\x01", 2).toUInt16(false));
CPPUNIT_ASSERT_EQUAL((unsigned short)0xFF01, ByteVector("\xFF\x01", 2).toUInt16());
CPPUNIT_ASSERT_EQUAL((unsigned short)0x01FF, ByteVector("\xFF\x01", 2).toUInt16(false));
ByteVector n(16, 0);
for(size_t i = 0; i < 8; ++i) {
n[i * 2 ] = static_cast<unsigned char>(0x11 * i);
n[i * 2 + 1] = static_cast<unsigned char>(0x11 * (i + 8));
}
CPPUNIT_ASSERT(n.toUInt16LE(1) == 4488);
CPPUNIT_ASSERT(n.toUInt16BE(2) == 4505);
CPPUNIT_ASSERT(n.toUInt24LE(3) == 11149977);
CPPUNIT_ASSERT(n.toUInt24BE(4) == 2271795);
CPPUNIT_ASSERT(n.toUInt32LE(5) == 1153119146);
CPPUNIT_ASSERT(n.toUInt32BE(6) == 867910860);
CPPUNIT_ASSERT(n.toInt16LE(3) == 8857);
CPPUNIT_ASSERT(n.toInt16BE(7) == -17596);
CPPUNIT_ASSERT(n.toInt16LE(10) == -8875);
CPPUNIT_ASSERT(n.toInt16BE(14) == 30719);
CPPUNIT_ASSERT(n.toInt64LE(5) == 7412174897536512938ll);
CPPUNIT_ASSERT(n.toInt64BE(3) == -7412174897536512939ll);
CPPUNIT_ASSERT(n.toInt64LE(6) == -1268082884489200845ll);
CPPUNIT_ASSERT(n.toInt64BE(4) == 2497865822736504285ll);
// Shows the message "toNumber<T>() -- offset is out of range. Returning 0." 2 times.
CPPUNIT_ASSERT(n.toUInt32LE(13) == 0);
CPPUNIT_ASSERT(n.toUInt16BE(15) == 0);
CPPUNIT_ASSERT(ByteVector::fromUInt16LE(n.toInt16LE(5)) == n.mid(5, 2));
CPPUNIT_ASSERT(ByteVector::fromUInt16BE(n.toInt16BE(9)) == n.mid(9, 2));
CPPUNIT_ASSERT(ByteVector::fromUInt32LE(n.toUInt32LE(4)) == n.mid(4, 4));
CPPUNIT_ASSERT(ByteVector::fromUInt32BE(n.toUInt32BE(7)) == n.mid(7, 4));
CPPUNIT_ASSERT(ByteVector::fromUInt64LE(n.toInt64LE(1)) == n.mid(1, 8));
CPPUNIT_ASSERT(ByteVector::fromUInt64BE(n.toInt64BE(6)) == n.mid(6, 8));
CPPUNIT_ASSERT(ByteVector::fromUInt16LE(4386) == ByteVector::fromUInt16BE(8721));
CPPUNIT_ASSERT(ByteVector::fromUInt32LE(287454020) == ByteVector::fromUInt32BE(1144201745));
CPPUNIT_ASSERT(ByteVector::fromUInt64LE(1234605615291183940) == ByteVector::fromUInt64BE(4914309075945333265));
}
void testReplace()

View File

@@ -27,9 +27,11 @@ class PublicFrame : public ID3v2::Frame
{
public:
PublicFrame() : ID3v2::Frame(ByteVector("XXXX\0\0\0\0\0\0", 10)) {}
String readStringField(const ByteVector &data, String::Type encoding,
int *positon = 0)
{ return ID3v2::Frame::readStringField(data, encoding, positon); }
String readStringField(const ByteVector &data, String::Type encoding)
{
size_t position = 0;
return ID3v2::Frame::readStringField(data, encoding, position);
}
virtual String toString() const { return String::null; }
virtual void parseFields(const ByteVector &) {}
virtual ByteVector renderFields() const { return ByteVector::null; }

View File

@@ -73,10 +73,10 @@ public:
MP4::Atom *stco = a.find("moov")->findall("stco", true)[0];
f->seek(stco->offset + 12);
ByteVector data = f->readBlock(stco->length - 12);
unsigned int count = data.mid(0, 4).toUInt32();
int pos = 4;
unsigned int count = data.toUInt32BE(0);
size_t pos = 4;
while (count--) {
unsigned int offset = data.mid(pos, 4).toUInt32();
unsigned int offset = data.toUInt32BE(pos);
f->seek(offset);
data1.append(f->readBlock(20));
pos += 4;
@@ -92,10 +92,10 @@ public:
MP4::Atom *stco = a.find("moov")->findall("stco", true)[0];
f->seek(stco->offset + 12);
ByteVector data = f->readBlock(stco->length - 12);
unsigned int count = data.mid(0, 4).toUInt32();
int pos = 4, i = 0;
unsigned int count = data.toUInt32BE(0);
size_t pos = 4, i = 0;
while (count--) {
unsigned int offset = data.mid(pos, 4).toUInt32();
unsigned int offset = data.toUInt32BE(pos);
f->seek(offset);
CPPUNIT_ASSERT_EQUAL(data1[i], f->readBlock(20));
pos += 4;