diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index b7bda179..f68346d0 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -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 + 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 + 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 + int main() { + OSSwapInt16(0); + OSSwapInt32(0); + OSSwapInt64(0); + return 0; + } + " HAVE_MAC_BYTESWAP) + + if(NOT HAVE_MAC_BYTESWAP) + check_cxx_source_compiles(" + #include + int main() { + swap16(0); + swap32(0); + swap64(0); + return 0; + } + " HAVE_OPENBSD_BYTESWAP) + endif() + endif() + endif() +endif() + # Determine where shared_ptr is defined regardless of C++11 support. check_cxx_source_compiles(" #include @@ -56,6 +130,14 @@ check_cxx_source_compiles(" int main() { std::codecvt_utf8_utf16 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) diff --git a/config-taglib.h.cmake b/config-taglib.h.cmake index e57ff050..5d94681b 100644 --- a/config-taglib.h.cmake +++ b/config-taglib.h.cmake @@ -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 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 diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 218edf5b..32ef941f 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -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 ) diff --git a/taglib/ape/apefooter.cpp b/taglib/ape/apefooter.cpp index 25a4ca54..cb27c440 100644 --- a/taglib/ape/apefooter.cpp +++ b/taglib/ape/apefooter.cpp @@ -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; } diff --git a/taglib/ape/apeitem.cpp b/taglib/ape/apeitem.cpp index 35a7c077..779a94d6 100644 --- a/taglib/ape/apeitem.cpp +++ b/taglib/ape/apeitem.cpp @@ -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); diff --git a/taglib/ape/apeproperties.cpp b/taglib/ape/apeproperties.cpp index b8b0783e..cbb1ac1e 100644 --- a/taglib/ape/apeproperties.cpp +++ b/taglib/ape/apeproperties.cpp @@ -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(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(d->streamLength * 8L / d->length / 1000) : 0; } diff --git a/taglib/asf/asfattribute.cpp b/taglib/asf/asfattribute.cpp index 7915c83e..81fb12e3 100644 --- a/taglib/asf/asfattribute.cpp +++ b/taglib/asf/asfattribute.cpp @@ -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; } diff --git a/taglib/asf/asffile.cpp b/taglib/asf/asffile.cpp index fbddf33d..3215e7d5 100644 --- a/taglib/asf/asffile.cpp +++ b/taglib/asf/asffile.cpp @@ -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; } diff --git a/taglib/asf/asfpicture.cpp b/taglib/asf/asfpicture.cpp index 0c873b7a..0b4ff60a 100644 --- a/taglib/asf/asfpicture.cpp +++ b/taglib/asf/asfpicture.cpp @@ -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); diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp index 7900d5bb..271091cc 100644 --- a/taglib/flac/flacfile.cpp +++ b/taglib/flac/flacfile.cpp @@ -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) { diff --git a/taglib/flac/flacpicture.cpp b/taglib/flac/flacpicture.cpp index a7bcce6d..2a0131de 100644 --- a/taglib/flac/flacpicture.cpp +++ b/taglib/flac/flacpicture.cpp @@ -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; } diff --git a/taglib/flac/flacproperties.cpp b/taglib/flac/flacproperties.cpp index 2a8c8e94..3bf9d6e9 100644 --- a/taglib/flac/flacproperties.cpp +++ b/taglib/flac/flacproperties.cpp @@ -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; diff --git a/taglib/mod/modfilebase.cpp b/taglib/mod/modfilebase.cpp index ca97e75d..a277edb7 100644 --- a/taglib/mod/modfilebase.cpp +++ b/taglib/mod/modfilebase.cpp @@ -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; } diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp index 482e495f..d77a69af 100644 --- a/taglib/mp4/mp4atom.cpp +++ b/taglib/mp4/mp4atom.cpp @@ -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; diff --git a/taglib/mp4/mp4properties.cpp b/taglib/mp4/mp4properties.cpp index 3353b494..3e4dcdfb 100644 --- a/taglib/mp4/mp4properties.cpp +++ b/taglib/mp4/mp4properties.cpp @@ -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); } } diff --git a/taglib/mp4/mp4tag.cpp b/taglib/mp4/mp4tag.cpp index 7b3629a4..8b3415cb 100644 --- a/taglib/mp4/mp4tag.cpp +++ b/taglib/mp4/mp4tag.cpp @@ -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)); } } } diff --git a/taglib/mpc/mpcproperties.cpp b/taglib/mpc/mpcproperties.cpp index 440c5dd2..95cb5bf8 100644 --- a/taglib/mpc/mpcproperties.cpp +++ b/taglib/mpc/mpcproperties.cpp @@ -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; } diff --git a/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp b/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp index 86f8e355..ee7dbe54 100644 --- a/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp +++ b/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp @@ -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); } diff --git a/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp b/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp index fa3509b1..f816bb9f 100644 --- a/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp +++ b/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp @@ -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); } diff --git a/taglib/mpeg/id3v2/frames/ownershipframe.cpp b/taglib/mpeg/id3v2/frames/ownershipframe.cpp index 9451c4c4..e61cb0d6 100644 --- a/taglib/mpeg/id3v2/frames/ownershipframe.cpp +++ b/taglib/mpeg/id3v2/frames/ownershipframe.cpp @@ -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 diff --git a/taglib/mpeg/id3v2/frames/popularimeterframe.cpp b/taglib/mpeg/id3v2/frames/popularimeterframe.cpp index cbc3c7c5..337f707c 100644 --- a/taglib/mpeg/id3v2/frames/popularimeterframe.cpp +++ b/taglib/mpeg/id3v2/frames/popularimeterframe.cpp @@ -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; } diff --git a/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp b/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp index 8dd8b366..d95420f5 100644 --- a/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp +++ b/taglib/mpeg/id3v2/frames/relativevolumeframe.cpp @@ -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); } diff --git a/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp b/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp index a0e842e0..1d30b799 100644 --- a/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp +++ b/taglib/mpeg/id3v2/frames/uniquefileidentifierframe.cpp @@ -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); } diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp index d57b8234..af54ab36 100644 --- a/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/taglib/mpeg/id3v2/id3v2frame.cpp @@ -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(*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(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; diff --git a/taglib/mpeg/id3v2/id3v2frame.h b/taglib/mpeg/id3v2/id3v2frame.h index 3e257d4f..ec0b0374 100644 --- a/taglib/mpeg/id3v2/id3v2frame.h +++ b/taglib/mpeg/id3v2/id3v2frame.h @@ -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 diff --git a/taglib/mpeg/id3v2/id3v2synchdata.cpp b/taglib/mpeg/id3v2/id3v2synchdata.cpp index 05d17a1f..5e3e18d8 100644 --- a/taglib/mpeg/id3v2/id3v2synchdata.cpp +++ b/taglib/mpeg/id3v2/id3v2synchdata.cpp @@ -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; diff --git a/taglib/mpeg/mpegheader.cpp b/taglib/mpeg/mpegheader.cpp index e53c824f..e54f9b3d 100644 --- a/taglib/mpeg/mpegheader.cpp +++ b/taglib/mpeg/mpegheader.cpp @@ -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 diff --git a/taglib/mpeg/xingheader.cpp b/taglib/mpeg/xingheader.cpp index aafcdf86..04ef67b5 100644 --- a/taglib/mpeg/xingheader.cpp +++ b/taglib/mpeg/xingheader.cpp @@ -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; } diff --git a/taglib/ogg/flac/oggflacfile.cpp b/taglib/ogg/flac/oggflacfile.cpp index e71e5444..b832a0d6 100644 --- a/taglib/ogg/flac/oggflacfile.cpp +++ b/taglib/ogg/flac/oggflacfile.cpp @@ -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) { diff --git a/taglib/ogg/oggpage.cpp b/taglib/ogg/oggpage.cpp index 4a1aea8e..a79f1385 100644 --- a/taglib/ogg/oggpage.cpp +++ b/taglib/ogg/oggpage.cpp @@ -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]; diff --git a/taglib/ogg/oggpageheader.cpp b/taglib/ogg/oggpageheader.cpp index 2024464f..4d3de25c 100644 --- a/taglib/ogg/oggpageheader.cpp +++ b/taglib/ogg/oggpageheader.cpp @@ -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 diff --git a/taglib/ogg/opus/opusproperties.cpp b/taglib/ogg/opus/opusproperties.cpp index 9caf2bc0..8ec72438 100644 --- a/taglib/ogg/opus/opusproperties.cpp +++ b/taglib/ogg/opus/opusproperties.cpp @@ -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) diff --git a/taglib/ogg/speex/speexproperties.cpp b/taglib/ogg/speex/speexproperties.cpp index 49560b61..f8dd2724 100644 --- a/taglib/ogg/speex/speexproperties.cpp +++ b/taglib/ogg/speex/speexproperties.cpp @@ -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 */ diff --git a/taglib/ogg/vorbis/vorbisproperties.cpp b/taglib/ogg/vorbis/vorbisproperties.cpp index 15b89017..47934e54 100644 --- a/taglib/ogg/vorbis/vorbisproperties.cpp +++ b/taglib/ogg/vorbis/vorbisproperties.cpp @@ -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; diff --git a/taglib/ogg/xiphcomment.cpp b/taglib/ogg/xiphcomment.cpp index aaa75774..40b54d60 100644 --- a/taglib/ogg/xiphcomment.cpp +++ b/taglib/ogg/xiphcomment.cpp @@ -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 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); diff --git a/taglib/riff/aiff/aiffproperties.cpp b/taglib/riff/aiff/aiffproperties.cpp index c88cc602..af40cd04 100644 --- a/taglib/riff/aiff/aiffproperties.cpp +++ b/taglib/riff/aiff/aiffproperties.cpp @@ -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(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(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; diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index 4dcef6ab..65bc00a8 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -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((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'); diff --git a/taglib/riff/wav/infotag.cpp b/taglib/riff/wav/infotag.cpp index 7f54b286..11188541 100644 --- a/taglib/riff/wav/infotag.cpp +++ b/taglib/riff/wav/infotag.cpp @@ -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; diff --git a/taglib/riff/wav/wavproperties.cpp b/taglib/riff/wav/wavproperties.cpp index 3eb9a71f..5ab2772c 100644 --- a/taglib/riff/wav/wavproperties.cpp +++ b/taglib/riff/wav/wavproperties.cpp @@ -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; diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index a03fa9f6..f73eaed5 100755 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -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 +#elif defined(HAVE_GLIBC_BYTESWAP) +# include +#elif defined(HAVE_MAC_BYTESWAP) +# include +#elif defined(HAVE_OPENBSD_BYTESWAP) +# include #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 diff --git a/taglib/toolkit/tbyteswap.cpp b/taglib/toolkit/tbyteswap.cpp deleted file mode 100644 index 714033e8..00000000 --- a/taglib/toolkit/tbyteswap.cpp +++ /dev/null @@ -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 -# 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 -# define TAGLIB_BYTESWAP_MAC - -#elif defined(__OpenBSD__) -# include -# define TAGLIB_BYTESWAP_OPENBSD - -#elif defined(__GLIBC__) -# include -# 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(&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 -} diff --git a/taglib/toolkit/tbyteswap.h b/taglib/toolkit/tbyteswap.h deleted file mode 100644 index 012a3173..00000000 --- a/taglib/toolkit/tbyteswap.h +++ /dev/null @@ -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 diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 38cb97ef..a4f5b17f 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -29,7 +29,6 @@ #include #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 -T byteSwap(T x) +inline T byteSwap(T x) { // There should be all counterparts of to*() and from*() overloads for integral types. debug("byteSwap() -- Non specialized version should not be called"); @@ -183,57 +182,129 @@ T byteSwap(T x) } template <> -ushort byteSwap(ushort x) +inline ushort byteSwap(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 x) +inline uint byteSwap(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 x) +inline ulonglong byteSwap(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 -T toNumber(const ByteVector &v, bool mostSignificantByteFirst) +namespace { + enum Endianness { + LittleEndian, + BigEndian + }; +} + +template +inline T toNumber(const ByteVector &v, size_t offset) { - if(v.isEmpty()) { - debug("toNumber() -- 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() -- offset is out of range. Returning 0."); return 0; } - if(v.size() >= sizeof(T)) { - if(isLittleEndianSystem == mostSignificantByteFirst) - return byteSwap(*reinterpret_cast(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(tmp); else - return *reinterpret_cast(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(static_cast(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(static_cast(v[offset + i])) << shift; } return sum; } } -template -ByteVector fromNumber(T value, bool mostSignificantByteFirst) +template +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(value); - return ByteVector(reinterpret_cast(&value), size); + return ByteVector(reinterpret_cast(&value), sizeof(T)); +} + +template +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(value); + + const size_t offset = v.size(); + v.resize(offset + sizeof(T)); + ::memcpy(v.data() + offset, reinterpret_cast(&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(static_cast(value), mostSignificantByteFirst); + return fromNumber(static_cast(value)); } -ByteVector ByteVector::fromUInt32(size_t value, bool mostSignificantByteFirst) +ByteVector ByteVector::fromUInt16BE(size_t value) { - return fromNumber(static_cast(value), mostSignificantByteFirst); + return fromNumber(static_cast(value)); } -ByteVector ByteVector::fromUInt64(ulonglong value, bool mostSignificantByteFirst) +ByteVector ByteVector::fromUInt32LE(size_t value) { - return fromNumber(value, mostSignificantByteFirst); + return fromNumber(static_cast(value)); +} + +ByteVector ByteVector::fromUInt32BE(size_t value) +{ + return fromNumber(static_cast(value)); +} + +ByteVector ByteVector::fromUInt64LE(ulonglong value) +{ + return fromNumber(value); +} + +ByteVector ByteVector::fromUInt64BE(ulonglong value) +{ + return fromNumber(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(*this, mostSignificantByteFirst); + return static_cast(toNumber(*this, offset)); } -short ByteVector::toInt16(bool mostSignificantByteFirst) const +short ByteVector::toInt16BE(size_t offset) const { - return toNumber(*this, mostSignificantByteFirst); + return static_cast(toNumber(*this, offset)); } -unsigned short ByteVector::toUInt16(bool mostSignificantByteFirst) const +ushort ByteVector::toUInt16LE(size_t offset) const { - return toNumber(*this, mostSignificantByteFirst); + return toNumber(*this, offset); } -long long ByteVector::toInt64(bool mostSignificantByteFirst) const +ushort ByteVector::toUInt16BE(size_t offset) const { - return toNumber(*this, mostSignificantByteFirst); + return toNumber(*this, offset); } +uint ByteVector::toUInt24LE(size_t offset) const +{ + return toNumber(*this, offset); +} + +uint ByteVector::toUInt24BE(size_t offset) const +{ + return toNumber(*this, offset); +} + +uint ByteVector::toUInt32LE(size_t offset) const +{ + return toNumber(*this, offset); +} + +uint ByteVector::toUInt32BE(size_t offset) const +{ + return toNumber(*this, offset); +} + +long long ByteVector::toInt64LE(size_t offset) const +{ + return static_cast(toNumber(*this, offset)); +} + +long long ByteVector::toInt64BE(size_t offset) const +{ + return static_cast(toNumber(*this, offset)); +} + + const char &ByteVector::operator[](size_t index) const { return d->data->data[d->offset + index]; diff --git a/taglib/toolkit/tbytevector.h b/taglib/toolkit/tbytevector.h index ec8e7c3f..990de4be 100644 --- a/taglib/toolkit/tbytevector.h +++ b/taglib/toolkit/tbytevector.h @@ -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. diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index d4e9a233..1637f038 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -32,7 +32,6 @@ #include "tstring.h" #include "tdebug.h" #include "tstringlist.h" -#include "tbyteswap.h" #include @@ -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(s[i])); + d->data[i] = byteSwap(static_cast(s[i])); } } @@ -858,7 +870,15 @@ void String::copyFromUTF16(const char *s, size_t length, Type t) internalCopyFromUTF16(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 diff --git a/taglib/trueaudio/trueaudioproperties.cpp b/taglib/trueaudio/trueaudioproperties.cpp index ea873532..75e2e7a1 100644 --- a/taglib/trueaudio/trueaudioproperties.cpp +++ b/taglib/trueaudio/trueaudioproperties.cpp @@ -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(d->streamLength * 8L / d->length / 1000) : 0; diff --git a/taglib/wavpack/wavpackproperties.cpp b/taglib/wavpack/wavpackproperties.cpp index dab34cb8..be5cf8d5 100644 --- a/taglib/wavpack/wavpackproperties.cpp +++ b/taglib/wavpack/wavpackproperties.cpp @@ -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; } diff --git a/taglib/xm/xmfile.cpp b/taglib/xm/xmfile.cpp index c315011d..9b702c1c 100644 --- a/taglib/xm/xmfile.cpp +++ b/taglib/xm/xmfile.cpp @@ -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(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(data.size()); } diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp index 1ea5b070..7dccf598 100644 --- a/tests/test_bytevector.cpp +++ b/tests/test_bytevector.cpp @@ -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(0x11 * i); + n[i * 2 + 1] = static_cast(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() -- 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() diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index 050dc035..18b2143f 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -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; } diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index 9e14e63f..b0285616 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -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;