From cf892f2cb8c578eaed9cbb08a4e981681a69e398 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 13 Sep 2013 03:47:03 +0900 Subject: [PATCH 01/32] Fixed a bug in creating String from ByteVector --- taglib/toolkit/tstring.cpp | 3 +++ tests/test_id3v1.cpp | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 56840f48..75a9833e 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -268,6 +268,9 @@ String::String(const ByteVector &v, Type t) copyFromUTF8(v.data(), v.size()); else copyFromUTF16(v.data(), v.size(), t); + + // If we hit a null in the ByteVector, shrink the string again. + d->data.resize(::wcslen(d->data.c_str())); } //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/test_id3v1.cpp b/tests/test_id3v1.cpp index 1d0a4974..7db2dbbf 100644 --- a/tests/test_id3v1.cpp +++ b/tests/test_id3v1.cpp @@ -1,7 +1,10 @@ #include #include +#include +#include #include #include +#include "utils.h" using namespace std; using namespace TagLib; @@ -16,8 +19,20 @@ public: void testStripWhiteSpace() { - ID3v1::StringHandler h; - CPPUNIT_ASSERT_EQUAL(String("Foo"), h.parse(ByteVector("Foo "))); + ScopedFileCopy copy("xing", ".mp3"); + string newname = copy.fileName(); + + { + MPEG::File f(newname.c_str()); + f.ID3v1Tag(true)->setArtist("Artist "); + f.save(); + } + + { + MPEG::File f(newname.c_str()); + CPPUNIT_ASSERT(f.ID3v1Tag(false)); + CPPUNIT_ASSERT_EQUAL(String("Artist"), f.ID3v1Tag(false)->artist()); + } } }; From 5c9360afa2563a3c11ea2d53e0de206922f2e1e4 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 13 Sep 2013 23:07:30 +0900 Subject: [PATCH 02/32] Removed some redundant code about checking chunk names of RIFF files --- taglib/riff/rifffile.cpp | 32 +++++++++++++++----------------- taglib/riff/rifffile.h | 5 +++++ taglib/riff/wav/infotag.cpp | 19 ++----------------- 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index 78335690..87b3a0fa 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -69,6 +69,20 @@ RIFF::File::~File() delete d; } +bool RIFF::File::isValidChunkName(const ByteVector &name) // static +{ + if(name.size() != 4) + return false; + + for(ByteVector::ConstIterator it = name.begin(); it != name.end(); ++it) { + const uchar c = static_cast(*it); + if(c < 32 || 127 < c) + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////////////////// // protected members //////////////////////////////////////////////////////////////////////////////// @@ -253,22 +267,6 @@ void RIFF::File::removeChunk(const ByteVector &name) // private members //////////////////////////////////////////////////////////////////////////////// -namespace -{ - bool isValidChunkID(const ByteVector &name) - { - if(name.size() != 4) { - return false; - } - for(int i = 0; i < 4; i++) { - if(name[i] < 32 || name[i] > 127) { - return false; - } - } - return true; - } -} - void RIFF::File::read() { d->type = readBlock(4); @@ -289,7 +287,7 @@ void RIFF::File::read() else chunkSize = readBlock(4).toUInt32LE(0); - if(!isValidChunkID(chunkName)) { + if(!isValidChunkName(chunkName)) { debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID"); setValid(false); break; diff --git a/taglib/riff/rifffile.h b/taglib/riff/rifffile.h index 6c2a9357..2a759f8c 100644 --- a/taglib/riff/rifffile.h +++ b/taglib/riff/rifffile.h @@ -51,6 +51,11 @@ namespace TagLib { */ virtual ~File(); + /*! + * Returns whether or not \a name is valid as a chunk name. + */ + static bool isValidChunkName(const ByteVector &name); + protected: File(FileName file, ByteOrder endianness); diff --git a/taglib/riff/wav/infotag.cpp b/taglib/riff/wav/infotag.cpp index fac8785c..2530e78f 100644 --- a/taglib/riff/wav/infotag.cpp +++ b/taglib/riff/wav/infotag.cpp @@ -26,27 +26,12 @@ #include #include +#include "rifffile.h" #include "infotag.h" using namespace TagLib; using namespace RIFF::Info; -namespace -{ - bool isValidChunkID(const ByteVector &name) - { - if(name.size() != 4) - return false; - - for(int i = 0; i < 4; i++) { - if(name[i] < 32 || 127 < name[i]) - return false; - } - - return true; - } -} - class RIFF::Info::Tag::TagPrivate { public: @@ -197,7 +182,7 @@ String RIFF::Info::Tag::fieldText(const ByteVector &id) const void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s) { // id must be four-byte long pure ASCII string. - if(!isValidChunkID(id)) + if(!RIFF::File::isValidChunkName(id)) return; if(!s.isEmpty()) From fde99fa2fbd4ead7c682f08346a298b93448836c Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Mon, 16 Sep 2013 04:56:33 +0900 Subject: [PATCH 03/32] Suppressed a useless debug message in aiffproperties.cpp --- taglib/riff/aiff/aiffproperties.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/taglib/riff/aiff/aiffproperties.cpp b/taglib/riff/aiff/aiffproperties.cpp index 6d103e83..9815800a 100644 --- a/taglib/riff/aiff/aiffproperties.cpp +++ b/taglib/riff/aiff/aiffproperties.cpp @@ -136,6 +136,9 @@ void RIFF::AIFF::AudioProperties::read(const ByteVector &data) d->bitrate = static_cast((sampleRate * d->sampleWidth * d->channels) / 1000.0); d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0; + if(data.size() == 18) + return; + if(data.size() < 23) { debug("RIFF::AIFF::AudioProperties::read() - \"COMM\" chunk is too short for AIFF-C."); return; From b7ffa04f206b4aeaa65a4a16d737779831d9d813 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Mon, 16 Sep 2013 21:54:12 +0900 Subject: [PATCH 04/32] Simplified the check for AIFF-C format --- taglib/riff/aiff/aiffproperties.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/taglib/riff/aiff/aiffproperties.cpp b/taglib/riff/aiff/aiffproperties.cpp index 9815800a..25012ecd 100644 --- a/taglib/riff/aiff/aiffproperties.cpp +++ b/taglib/riff/aiff/aiffproperties.cpp @@ -136,14 +136,8 @@ void RIFF::AIFF::AudioProperties::read(const ByteVector &data) d->bitrate = static_cast((sampleRate * d->sampleWidth * d->channels) / 1000.0); d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0; - if(data.size() == 18) - return; - - if(data.size() < 23) { - debug("RIFF::AIFF::AudioProperties::read() - \"COMM\" chunk is too short for AIFF-C."); - return; + if(data.size() >= 23) { + d->compressionType = data.mid(18, 4); + d->compressionName = String(data.mid(23, static_cast(data[22]))); } - - d->compressionType = data.mid(18, 4); - d->compressionName = String(data.mid(23, static_cast(data[22]))); } From 23b418b4e9609c270a4f6c26c39e66d61ef61820 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Tue, 17 Sep 2013 14:59:19 +0900 Subject: [PATCH 05/32] Added a missing fieldListmap() method to RIFF::Info::Tag --- taglib/riff/wav/infotag.cpp | 5 +++++ taglib/riff/wav/infotag.h | 12 ++++++++++++ tests/CMakeLists.txt | 1 + tests/test_info.cpp | 10 +++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/taglib/riff/wav/infotag.cpp b/taglib/riff/wav/infotag.cpp index 658ede88..09edfa53 100644 --- a/taglib/riff/wav/infotag.cpp +++ b/taglib/riff/wav/infotag.cpp @@ -185,6 +185,11 @@ bool RIFF::Info::Tag::isEmpty() const return d->fieldListMap.isEmpty(); } +FieldListMap RIFF::Info::Tag::fieldListMap() const +{ + return d->fieldListMap; +} + String RIFF::Info::Tag::fieldText(const ByteVector &id) const { if(d->fieldListMap.contains(id)) diff --git a/taglib/riff/wav/infotag.h b/taglib/riff/wav/infotag.h index 9a26d4cb..4007ae66 100644 --- a/taglib/riff/wav/infotag.h +++ b/taglib/riff/wav/infotag.h @@ -120,6 +120,18 @@ namespace TagLib { virtual bool isEmpty() const; + /*! + * Returns a copy of the internal fields of the tag. The returned map directly + * reflects the contents of the "INFO" chunk. + * + * \note Modifying this map does not affect the tag's internal data. + * Use setFieldText() and removeField() instead. + * + * \see setFieldText() + * \see removeField() + */ + FieldListMap fieldListMap() const; + /* * Gets the value of the field with the ID \a id. */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4e428af8..7a3d0bd5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -52,6 +52,7 @@ SET(test_runner_SRCS test_ape.cpp test_apetag.cpp test_wav.cpp + test_info.cpp test_wavpack.cpp test_mp4.cpp test_mp4item.cpp diff --git a/tests/test_info.cpp b/tests/test_info.cpp index f76fd67a..8e0d7154 100644 --- a/tests/test_info.cpp +++ b/tests/test_info.cpp @@ -1,9 +1,7 @@ -#include #include #include #include -#include -#include +#include #include "utils.h" using namespace std; @@ -23,7 +21,13 @@ public: CPPUNIT_ASSERT_EQUAL(String(""), tag.title()); tag.setTitle("Test title 1"); + tag.setFieldText("TEST", "Dummy Text"); + CPPUNIT_ASSERT_EQUAL(String("Test title 1"), tag.title()); + + RIFF::Info::FieldListMap map = tag.fieldListMap(); + CPPUNIT_ASSERT_EQUAL(String("Test title 1"), map["INAM"]); + CPPUNIT_ASSERT_EQUAL(String("Dummy Text"), map["TEST"]); } void testNumericFields() From c63dcdc4599b0fe28723df75e8910876cdd6e682 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Tue, 17 Sep 2013 23:03:57 +0900 Subject: [PATCH 06/32] Removed #include "tdebug.h" from a public header --- taglib/toolkit/tiostream.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/taglib/toolkit/tiostream.h b/taglib/toolkit/tiostream.h index 571019a0..fe1ce673 100644 --- a/taglib/toolkit/tiostream.h +++ b/taglib/toolkit/tiostream.h @@ -28,15 +28,12 @@ #include "tbytevector.h" -#ifdef _WIN32 -# include "tstring.h" -# include "tdebug.h" -#endif - namespace TagLib { #ifdef _WIN32 + class String; + class TAGLIB_EXPORT FileName { public: From e125bcb78b3c7da0dc8cb30b35b0540af3114125 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Thu, 19 Sep 2013 04:09:28 +0900 Subject: [PATCH 07/32] Fixed a possible out-of-bound access when reading WavPack files --- taglib/wavpack/wavpackproperties.cpp | 5 +++-- taglib/wavpack/wavpackproperties.h | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/taglib/wavpack/wavpackproperties.cpp b/taglib/wavpack/wavpackproperties.cpp index 3f791544..085ddf8a 100644 --- a/taglib/wavpack/wavpackproperties.cpp +++ b/taglib/wavpack/wavpackproperties.cpp @@ -126,8 +126,9 @@ TagLib::uint WavPack::Properties::sampleFrames() const // private members //////////////////////////////////////////////////////////////////////////////// -static const unsigned int sample_rates[] = { 6000, 8000, 9600, 11025, 12000, - 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; +static const unsigned int sample_rates[] = { + 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000, 192000, 0 }; #define BYTES_STORED 3 #define MONO_FLAG 4 diff --git a/taglib/wavpack/wavpackproperties.h b/taglib/wavpack/wavpackproperties.h index bd2209da..c788fdd5 100644 --- a/taglib/wavpack/wavpackproperties.h +++ b/taglib/wavpack/wavpackproperties.h @@ -75,7 +75,12 @@ namespace TagLib { virtual int length() const; virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. 0 means unknown or custom. + */ virtual int sampleRate() const; + virtual int channels() const; /*! From e6f9a06894e631e2e980b8f8f640bb2e7140b315 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 20 Sep 2013 08:26:37 +0900 Subject: [PATCH 08/32] Added missing #include for std::min() and std::max() --- taglib/riff/rifffile.cpp | 1 + taglib/toolkit/tbytevector.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index 20eec5ff..a79a4c70 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -28,6 +28,7 @@ #include #include "rifffile.h" +#include #include using namespace TagLib; diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index dc0c5e55..b6582464 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -27,6 +27,7 @@ #include #endif +#include #include #include #include From 85d76a242850f72a5fbbf3de8fc30410358559dd Mon Sep 17 00:00:00 2001 From: Festus Hagen Date: Mon, 30 Sep 2013 18:06:55 -0400 Subject: [PATCH 09/32] Update Windows INSTALL notes. --- INSTALL | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/INSTALL b/INSTALL index 3be4d131..9e6e8075 100644 --- a/INSTALL +++ b/INSTALL @@ -46,15 +46,102 @@ the include folder to the project's User Header Search Paths. Windows ------- -For building a static library on Windows with Visual Studio 2010, cd to -the TagLib folder then: +It's Windows ... Systems vary! +This means you need to adjust things to suit your system, especially paths. - cmake -DENABLE_STATIC=ON -DENABLE_STATIC_RUNTIME=ON -G "Visual Studio 10" ... +Tested with: + Microsoft Visual Studio 2010 + Gcc by mingw-w64.sf.net v4.6.3 (Strawberry Perl 32b) + MinGW32-4.8.0 + +Requirements: + 1. Tool chain, Build Environment, Whatever ya want to call it ... + Installed and working. + 2. CMake program. (Available at: www.cmake.org) + Installed and working. + +Optional: + 1. Zlib library. + Available in some Tool Chains, Not all. + Search the web, Take your choice. + +Useful configuration options used with CMake (GUI and/or Command line): + Any of the ZLIB_ variables may be used at the command line, ZLIB_ROOT is only + available on the Command line. + ZLIB_ROOT= Where to find ZLib's root directory. + Assumes parent of: \include and \lib. + ZLIB_INCLUDE_DIR= Where to find ZLib's Include directory. + ZLIB_LIBRARY= Where to find ZLib's Library. + CMAKE_INSTALL_PREFIX= Where to install Taglib. + CMAKE_BUILD_TYPE= Release, Debug, etc ... (Not available in MSVC) + +The easiest way is at the Command Prompt. + MSVS Command Prompt for MSVS Users. + (Batch file and/or Shortcuts are your friends) + + 1. Build the Makefiles: + Replace "GENERATOR" with your needs. + For MSVS : "Visual Studio X" where X is the single or two digit version. + For MinGW: "MinGW Makefiles" + + C:\GitRoot\taglib> cmake -G "GENERATOR" -DCMAKE_INSTALL_PREFIX=C:\Libraries\taglib + + Or use the CMake GUI: + 1. Open CMake GUI. + 2. Set Paths. + "Where is the source code" and "Where to build the binaries" + Example, Both would be: C:\GitRoot\taglib + 3. Tick: Advanced + 4. Select: Configure + 5. Select: Generator + 6. Tick: Use default native compilers + 7. Select: Finish + Wait until done. + 5. If using ZLib, Scroll down. + (to the bottom of the list of options ... should go over them all) + 1. Edit: ZLIB_INCLUDE_DIR + 2. Edit: ZLIB_LIBRARY + 6. Select: Generate + + 2. Build the project: + MSVS: + C:\GitRoot\taglib> msbuild all_build.vcxproj /p:Configuration=Release + OR (Depending on MSVS version or personal choice) + C:\GitRoot\taglib> devenv all_build.vcxproj /build Release + MinGW: + C:\GitRoot\taglib> gmake + OR (Depending on MinGW install) + C:\GitRoot\taglib> mingw32-make + + Or in the MSVS GUI: + 1. Open MSVS. + 2. Open taglib solution. + 3. Set build type to: Release (look in the tool bars) + 2. Hit F7 to build the solution. (project) + + 3. Install the project: + (Change 'install' to 'uninstall' to uninstall the project) + MSVS: + C:\GitRoot\taglib> msbuild install.vcxproj + OR (Depending on MSVC version or personal choice) + C:\GitRoot\taglib> devenv install.vcxproj + MinGW: + C:\GitRoot\taglib> gmake install + OR (Depending on MinGW install) + C:\GitRoot\taglib> mingw32-make install + + Or in the MSVS GUI: + 1. Open project. + 2. Open Solution Explorer. + 3. Right Click: INSTALL + 4. Select: Project Only + 5. Select: Build Only INSTALL + +To build a static library enable the following two options with CMake. + -DENABLE_STATIC=ON -DENABLE_STATIC_RUNTIME=ON Including ENABLE_STATIC_RUNTIME=ON indicates you want TagLib built using the static runtime library, rather than the DLL form of the runtime. -CMake will create a Visual Studio solution, taglib.sln that you can open and -build as normal. Unit Tests ---------- From f2c9ed4f3684de0cd53047b82d739e768f336531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sat, 5 Oct 2013 10:09:09 +0200 Subject: [PATCH 10/32] Update NEWS --- NEWS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS b/NEWS index 24d396cd..68757523 100644 --- a/NEWS +++ b/NEWS @@ -7,10 +7,18 @@ TagLib 1.9 (In Development) * Included taglib-config.cmd script for Windows. * New ID3v1::Tag methods for working directly with genre numbers. * New MPEG::File methods for checking which tags are saved in the file. + * Added support for the PropertyMap API to ASF and MP4 files. + * Added MusicBrainz identifiers to the PropertyMap API. + * Allowed reading of MP4 cover art without an explicitly specified format. * Better parsing of corrupted FLAC files. * Fixed saving of PropertyMap comments without description into ID3v2 tags. * Fixed crash when parsing certain XM files. * Fixed compilation of unit test with clang. + * Better handling of files that can't be open or have read-only permissions. + * Improved atomic reference counting. + * New hookable API for debug messages. + * More complete Windows install instructions. + * Many smaller bug fixes and performance improvements. TagLib 1.8 (Sep 6, 2012) ======================== From dcfb71bcb41a0ed2c52fbac7b30f5489e3556fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sat, 5 Oct 2013 10:53:15 +0200 Subject: [PATCH 11/32] Update version number to 1.9 --- CMakeLists.txt | 6 +++--- NEWS | 2 +- taglib/toolkit/taglib.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f410e098..ee780bbb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ if (MSVC AND ENABLE_STATIC_RUNTIME) endif() set(TAGLIB_LIB_MAJOR_VERSION "1") -set(TAGLIB_LIB_MINOR_VERSION "8") +set(TAGLIB_LIB_MINOR_VERSION "9") set(TAGLIB_LIB_PATCH_VERSION "0") set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}") @@ -56,9 +56,9 @@ set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VE # 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0. # 3. If any interfaces have been added since the last public release, then increment age. # 4. If any interfaces have been removed since the last public release, then set age to 0. -set(TAGLIB_SOVERSION_CURRENT 13) +set(TAGLIB_SOVERSION_CURRENT 14) set(TAGLIB_SOVERSION_REVISION 0) -set(TAGLIB_SOVERSION_AGE 12) +set(TAGLIB_SOVERSION_AGE 13) math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}") math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}") diff --git a/NEWS b/NEWS index 68757523..651b1341 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -TagLib 1.9 (In Development) +TagLib 1.9 (Oct 6, 2013) ========================== * Added support for the Ogg Opus file format. diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index f93f280d..620e95bc 100755 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -29,7 +29,7 @@ #include "taglib_config.h" #define TAGLIB_MAJOR_VERSION 1 -#define TAGLIB_MINOR_VERSION 8 +#define TAGLIB_MINOR_VERSION 9 #define TAGLIB_PATCH_VERSION 0 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) From 95776b59054582d0547786568ec2cf0214ecc472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sun, 6 Oct 2013 17:11:01 +0200 Subject: [PATCH 12/32] These files should not be marked as executable --- CMakeLists.txt | 0 ConfigureChecks.cmake | 0 taglib-config.cmd.cmake | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 CMakeLists.txt mode change 100755 => 100644 ConfigureChecks.cmake mode change 100755 => 100644 taglib-config.cmd.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake old mode 100755 new mode 100644 diff --git a/taglib-config.cmd.cmake b/taglib-config.cmd.cmake old mode 100755 new mode 100644 From 079e3e0b87911e034ecf1764fe9a5944e51d0cde Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Mon, 7 Oct 2013 17:00:58 +0900 Subject: [PATCH 13/32] Fixed detecting RIFF files with invalid chunk sizes --- taglib/riff/rifffile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index a79a4c70..a39fce61 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -273,7 +273,7 @@ void RIFF::File::read() break; } - if(tell() + chunkSize > uint(length())) { + if(static_cast(tell()) + chunkSize > static_cast(length())) { debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid size (larger than the file size)"); setValid(false); break; From 873df184fea239b382376950c5e4e337ed4c336a Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Tue, 8 Oct 2013 19:55:44 +0900 Subject: [PATCH 14/32] Workaround for when MSVC doesn't have wchar_t as a built-in type --- taglib/toolkit/unicode.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/taglib/toolkit/unicode.h b/taglib/toolkit/unicode.h index b9de0ea2..ebf1915d 100644 --- a/taglib/toolkit/unicode.h +++ b/taglib/toolkit/unicode.h @@ -106,6 +106,11 @@ bit mask & shift operations. ------------------------------------------------------------------------ */ +// Workaround for when MSVC doesn't have wchar_t as a built-in type. +#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED) +# include +#endif + /* Some fundamental constants */ #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD #define UNI_MAX_BMP (UTF32)0x0000FFFF @@ -114,10 +119,10 @@ namespace Unicode { -typedef unsigned long UTF32; /* at least 32 bits */ -typedef wchar_t UTF16; /* TagLib assumes that wchar_t is sufficient for UTF-16. */ +typedef unsigned long UTF32; /* at least 32 bits */ +typedef wchar_t UTF16; /* TagLib assumes that wchar_t is sufficient for UTF-16. */ typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ +typedef unsigned char Boolean; /* 0 or 1 */ typedef enum { conversionOK = 0, /* conversion successful */ From a175b8356b3a4182e24bd57268ad173f0583e3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 8 Oct 2013 16:06:03 +0200 Subject: [PATCH 15/32] Reintroduce the old RefCounter from 1.8, which is needed by TagLib::Map<> and TagLib::List<> (closes #296) --- taglib/toolkit/tlist.tcc | 3 +- taglib/toolkit/tmap.tcc | 9 +++--- taglib/toolkit/trefcounter.h | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/taglib/toolkit/tlist.tcc b/taglib/toolkit/tlist.tcc index 81e29153..72d4767b 100644 --- a/taglib/toolkit/tlist.tcc +++ b/taglib/toolkit/tlist.tcc @@ -39,7 +39,8 @@ namespace TagLib { // A base for the generic and specialized private class types. New // non-templatized members should be added here. -class ListPrivateBase : public RefCounter +// BIC change to RefCounter +class ListPrivateBase : public RefCounterOld { public: ListPrivateBase() : autoDelete(false) {} diff --git a/taglib/toolkit/tmap.tcc b/taglib/toolkit/tmap.tcc index d6f51c07..5d3abcad 100644 --- a/taglib/toolkit/tmap.tcc +++ b/taglib/toolkit/tmap.tcc @@ -31,17 +31,18 @@ namespace TagLib { // public members //////////////////////////////////////////////////////////////////////////////// +// BIC change to RefCounter template template -class Map::MapPrivate : public RefCounter +class Map::MapPrivate : public RefCounterOld { public: - MapPrivate() : RefCounter() {} + MapPrivate() : RefCounterOld() {} #ifdef WANT_CLASS_INSTANTIATION_OF_MAP - MapPrivate(const std::map& m) : RefCounter(), map(m) {} + MapPrivate(const std::map& m) : RefCounterOld(), map(m) {} std::map map; #else - MapPrivate(const std::map& m) : RefCounter(), map(m) {} + MapPrivate(const std::map& m) : RefCounterOld(), map(m) {} std::map map; #endif }; diff --git a/taglib/toolkit/trefcounter.h b/taglib/toolkit/trefcounter.h index 53c6f1c0..75388b10 100644 --- a/taglib/toolkit/trefcounter.h +++ b/taglib/toolkit/trefcounter.h @@ -29,6 +29,23 @@ #include "taglib_export.h" #include "taglib.h" +#ifdef __APPLE__ +# include +# define TAGLIB_ATOMIC_MAC +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define NOMINMAX +# include +# define TAGLIB_ATOMIC_WIN +#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \ + && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(__x86_64) || defined(__ia64)) \ + && !defined(__INTEL_COMPILER) +# define TAGLIB_ATOMIC_GCC +#elif defined(__ia64) && defined(__INTEL_COMPILER) +# include +# define TAGLIB_ATOMIC_GCC +#endif + #ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class. /*! * \internal @@ -38,6 +55,7 @@ */ namespace TagLib { + class TAGLIB_EXPORT RefCounter { public: @@ -52,7 +70,42 @@ namespace TagLib class RefCounterPrivate; RefCounterPrivate *d; }; + + // BIC this old class is needed by tlist.tcc and tmap.tcc + class RefCounterOld + { + public: + RefCounterOld() : refCount(1) {} + +#ifdef TAGLIB_ATOMIC_MAC + void ref() { OSAtomicIncrement32Barrier(const_cast(&refCount)); } + bool deref() { return ! OSAtomicDecrement32Barrier(const_cast(&refCount)); } + int32_t count() { return refCount; } + private: + volatile int32_t refCount; +#elif defined(TAGLIB_ATOMIC_WIN) + void ref() { InterlockedIncrement(&refCount); } + bool deref() { return ! InterlockedDecrement(&refCount); } + long count() { return refCount; } + private: + volatile long refCount; +#elif defined(TAGLIB_ATOMIC_GCC) + void ref() { __sync_add_and_fetch(&refCount, 1); } + bool deref() { return ! __sync_sub_and_fetch(&refCount, 1); } + int count() { return refCount; } + private: + volatile int refCount; +#else + void ref() { refCount++; } + bool deref() { return ! --refCount; } + int count() { return refCount; } + private: + uint refCount; +#endif + }; + } #endif // DO_NOT_DOCUMENT #endif + From a6f759cc9a8e2529ab15fc41790621b2af658ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 8 Oct 2013 16:06:58 +0200 Subject: [PATCH 16/32] These shouldn't be executable either --- taglib/CMakeLists.txt | 0 taglib/fileref.h | 0 taglib/toolkit/taglib.h | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 taglib/CMakeLists.txt mode change 100755 => 100644 taglib/fileref.h mode change 100755 => 100644 taglib/toolkit/taglib.h diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/taglib/fileref.h b/taglib/fileref.h old mode 100755 new mode 100644 diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h old mode 100755 new mode 100644 From 02ebd0bcbe689a55e88c1bcc49bd82cb5b279a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 8 Oct 2013 16:18:30 +0200 Subject: [PATCH 17/32] Change log for 1.9.1 --- NEWS | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 651b1341..6f34d8c4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,14 @@ -TagLib 1.9 (Oct 6, 2013) +TagLib 1.9.1 (Oct 8, 2013) ========================== + * Fixed binary incompatible change in TagLib::Map and TagLib::List. + * Fixed constructing String from ByteVector. + * Fixed compilation on MSVC with the /Zc:wchar_t- option. + * Fixed detecting of RIFF files with invalid chunk sizes. + +TagLib 1.9 (Oct 6, 2013) +======================== + * Added support for the Ogg Opus file format. * Added support for INFO tags in WAV files. * Changed FileStream to use Windows file API. From 2d5abd46d22c32e6442ac98572323c31d126ffff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 8 Oct 2013 17:41:09 +0200 Subject: [PATCH 18/32] Added TagLib::MP4::PropertyMap::codec() --- NEWS | 1 + taglib/mp4/mp4properties.cpp | 16 ++++++++++++---- taglib/mp4/mp4properties.h | 9 +++++++++ tests/test_mp4.cpp | 2 ++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 6f34d8c4..72d41fba 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ TagLib 1.9.1 (Oct 8, 2013) * Fixed constructing String from ByteVector. * Fixed compilation on MSVC with the /Zc:wchar_t- option. * Fixed detecting of RIFF files with invalid chunk sizes. + * Added TagLib::MP4::PropertyMap::codec(). TagLib 1.9 (Oct 6, 2013) ======================== diff --git a/taglib/mp4/mp4properties.cpp b/taglib/mp4/mp4properties.cpp index 058cc61c..5a41c081 100644 --- a/taglib/mp4/mp4properties.cpp +++ b/taglib/mp4/mp4properties.cpp @@ -34,7 +34,7 @@ using namespace TagLib; class MP4::Properties::PropertiesPrivate { public: - PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0), encrypted(false) {} + PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0), encrypted(false), codec(MP4::Properties::Unknown) {} int length; int bitrate; @@ -42,6 +42,7 @@ public: int channels; int bitsPerSample; bool encrypted; + Codec codec; }; MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) @@ -114,6 +115,7 @@ 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->codec = AAC; d->channels = data.toShort(40U); d->bitsPerSample = data.toShort(42U); d->sampleRate = data.toUInt(46U); @@ -135,10 +137,11 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) } else if (data.mid(20, 4) == "alac") { if (atom->length == 88 && data.mid(56, 4) == "alac") { + d->codec = ALAC; d->bitsPerSample = data.at(69); - d->channels = data.at(73); - d->bitrate = data.toUInt(80U) / 1000; - d->sampleRate = data.toUInt(84U); + d->channels = data.at(73); + d->bitrate = data.toUInt(80U) / 1000; + d->sampleRate = data.toUInt(84U); } } @@ -189,3 +192,8 @@ MP4::Properties::isEncrypted() const return d->encrypted; } +MP4::Properties::Codec MP4::Properties::codec() const +{ + return d->codec; +} + diff --git a/taglib/mp4/mp4properties.h b/taglib/mp4/mp4properties.h index 7906824d..2607c366 100644 --- a/taglib/mp4/mp4properties.h +++ b/taglib/mp4/mp4properties.h @@ -40,6 +40,12 @@ namespace TagLib { class TAGLIB_EXPORT Properties : public AudioProperties { public: + enum Codec { + Unknown = 0, + AAC, + ALAC + }; + Properties(File *file, Atoms *atoms, ReadStyle style = Average); virtual ~Properties(); @@ -50,6 +56,9 @@ namespace TagLib { virtual int bitsPerSample() const; bool isEncrypted() const; + //! Audio codec used in the MP4 file + Codec codec() const; + private: class PropertiesPrivate; PropertiesPrivate *d; diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index be7ad2c3..56b60525 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -39,6 +39,7 @@ public: CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels()); CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate()); CPPUNIT_ASSERT_EQUAL(16, ((MP4::Properties *)f.audioProperties())->bitsPerSample()); + CPPUNIT_ASSERT_EQUAL(MP4::Properties::AAC, ((MP4::Properties *)f.audioProperties())->codec()); } void testPropertiesALAC() @@ -49,6 +50,7 @@ public: CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels()); CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate()); CPPUNIT_ASSERT_EQUAL(16, ((MP4::Properties *)f.audioProperties())->bitsPerSample()); + CPPUNIT_ASSERT_EQUAL(MP4::Properties::ALAC, ((MP4::Properties *)f.audioProperties())->codec()); } void testCheckValid() From 2f7af42092cefac12536ce7ecf5bc519bb2e24fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 8 Oct 2013 17:46:34 +0200 Subject: [PATCH 19/32] Update version to 1.9.1 --- CMakeLists.txt | 6 +++--- taglib/toolkit/taglib.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee780bbb..317ffa16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,7 @@ endif() set(TAGLIB_LIB_MAJOR_VERSION "1") set(TAGLIB_LIB_MINOR_VERSION "9") -set(TAGLIB_LIB_PATCH_VERSION "0") +set(TAGLIB_LIB_PATCH_VERSION "1") set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}") @@ -56,9 +56,9 @@ set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VE # 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0. # 3. If any interfaces have been added since the last public release, then increment age. # 4. If any interfaces have been removed since the last public release, then set age to 0. -set(TAGLIB_SOVERSION_CURRENT 14) +set(TAGLIB_SOVERSION_CURRENT 15) set(TAGLIB_SOVERSION_REVISION 0) -set(TAGLIB_SOVERSION_AGE 13) +set(TAGLIB_SOVERSION_AGE 14) math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}") math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}") diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index 620e95bc..cbca1074 100644 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -30,7 +30,7 @@ #define TAGLIB_MAJOR_VERSION 1 #define TAGLIB_MINOR_VERSION 9 -#define TAGLIB_PATCH_VERSION 0 +#define TAGLIB_PATCH_VERSION 1 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) #define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"") From aa61823432218fb6143a688aae1ed694d21889c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 8 Oct 2013 17:50:01 +0200 Subject: [PATCH 20/32] Fix the length of the TXXX translation mapping (closes #283) --- taglib/mpeg/id3v2/id3v2frame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp index c5c5585d..3cafcff9 100644 --- a/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/taglib/mpeg/id3v2/id3v2frame.cpp @@ -392,7 +392,7 @@ static const char *frameTranslation[][2] = { //{ "USLT", "LYRICS" }, handled specially }; -static const TagLib::uint txxxFrameTranslationSize = 7; +static const TagLib::uint txxxFrameTranslationSize = 8; static const char *txxxFrameTranslation[][2] = { { "MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" }, { "MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" }, From 69e58b5f3fbb957ed7e55838a14adc52b03c0972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?= Date: Mon, 28 Oct 2013 04:39:04 +0100 Subject: [PATCH 21/32] Win32: avoid symbol lookup if UNICODE is defined --- taglib/toolkit/tiostream.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/taglib/toolkit/tiostream.cpp b/taglib/toolkit/tiostream.cpp index c2ad2912..0284aed6 100644 --- a/taglib/toolkit/tiostream.cpp +++ b/taglib/toolkit/tiostream.cpp @@ -40,8 +40,12 @@ namespace bool supportsUnicode() { +#ifdef UNICODE + return true; +#else const FARPROC p = GetProcAddress(GetModuleHandleA("kernel32"), "CreateFileW"); return (p != NULL); +#endif } // Indicates whether the system supports Unicode file names. From ced5f262ba66541c54685eeb1d58b3b7acf82cca Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Wed, 30 Oct 2013 19:37:44 +0900 Subject: [PATCH 22/32] String::upper() no longer modifies the String itself --- taglib/toolkit/tstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 25d8db1c..52f176b2 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -390,7 +390,7 @@ String String::upper() const { static const int shift = 'A' - 'a'; - String s(*this); + String s(*d->data); for(Iterator it = s.begin(); it != s.end(); ++it) { if(*it >= 'a' && *it <= 'z') *it = *it + shift; From 0acdd2379e3729021068799f5dd5f70d4428fb43 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Wed, 30 Oct 2013 22:40:21 +0900 Subject: [PATCH 23/32] Added a test for String::upper() --- tests/test_string.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_string.cpp b/tests/test_string.cpp index 0e2807ef..779ada67 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -43,6 +43,7 @@ class TestString : public CppUnit::TestFixture CPPUNIT_TEST(testToInt); CPPUNIT_TEST(testSubstr); CPPUNIT_TEST(testNewline); + CPPUNIT_TEST(testUpper); CPPUNIT_TEST_SUITE_END(); public: @@ -237,6 +238,14 @@ public: CPPUNIT_ASSERT_EQUAL(L'\x0d', String(crlf)[3]); CPPUNIT_ASSERT_EQUAL(L'\x0a', String(crlf)[4]); } + + void testUpper() + { + String s1 = "tagLIB 012 strING"; + String s2 = s1.upper(); + CPPUNIT_ASSERT_EQUAL(String("tagLIB 012 strING"), s1); + CPPUNIT_ASSERT_EQUAL(String("TAGLIB 012 STRING"), s2); + } }; From 3bf30af66c8fd77a88d9379a0956ddb2fc70dc20 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Wed, 6 Nov 2013 17:01:21 +0900 Subject: [PATCH 24/32] Fixed ABI breakage in TagLib::String --- taglib/toolkit/tstring.cpp | 20 ++++++++++++++++++-- taglib/toolkit/tstring.h | 12 ++++++++++-- tests/test_string.cpp | 14 ++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 75a9833e..fb6e947a 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -209,8 +209,16 @@ String::String(const std::string &s, Type t) String::String(const wstring &s, Type t) : d(new StringPrivate()) { - if(t == UTF16 || t == UTF16BE || t == UTF16LE) + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + // This looks ugly but needed for the compatibility with TagLib1.8. + // Should be removed in TabLib2.0. + if (t == UTF16BE) + t = WCharByteOrder; + else if (t == UTF16LE) + t = (WCharByteOrder == UTF16LE ? UTF16BE : UTF16LE); + copyFromUTF16(s.c_str(), s.length(), t); + } else { debug("String::String() -- A TagLib::wstring should not contain Latin1 or UTF-8."); } @@ -219,8 +227,16 @@ String::String(const wstring &s, Type t) String::String(const wchar_t *s, Type t) : d(new StringPrivate()) { - if(t == UTF16 || t == UTF16BE || t == UTF16LE) + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + // This looks ugly but needed for the compatibility with TagLib1.8. + // Should be removed in TabLib2.0. + if (t == UTF16BE) + t = WCharByteOrder; + else if (t == UTF16LE) + t = (WCharByteOrder == UTF16LE ? UTF16BE : UTF16LE); + copyFromUTF16(s, ::wcslen(s), t); + } else { debug("String::String() -- A const wchar_t * should not contain Latin1 or UTF-8."); } diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index 57945bee..605b9c22 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -134,13 +134,21 @@ namespace TagLib { /*! * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless + * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior + * will be changed in TagLib2.0. */ - String(const wstring &s, Type t = WCharByteOrder); + String(const wstring &s, Type t = UTF16BE); /*! * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless + * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior + * will be changed in TagLib2.0. */ - String(const wchar_t *s, Type t = WCharByteOrder); + String(const wchar_t *s, Type t = UTF16BE); /*! * Makes a deep copy of the data in \a c. diff --git a/tests/test_string.cpp b/tests/test_string.cpp index a815a0b4..9a574b39 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -75,6 +75,20 @@ public: String unicode3(L"\u65E5\u672C\u8A9E"); CPPUNIT_ASSERT(*(unicode3.toCWString() + 1) == L'\u672C'); + String unicode4(L"\u65e5\u672c\u8a9e", String::UTF16BE); + CPPUNIT_ASSERT(unicode4[1] == L'\u672c'); + + String unicode5(L"\u65e5\u672c\u8a9e", String::UTF16LE); + CPPUNIT_ASSERT(unicode5[1] == L'\u2c67'); + + wstring stduni = L"\u65e5\u672c\u8a9e"; + + String unicode6(stduni, String::UTF16BE); + CPPUNIT_ASSERT(unicode6[1] == L'\u672c'); + + String unicode7(stduni, String::UTF16LE); + CPPUNIT_ASSERT(unicode7[1] == L'\u2c67'); + CPPUNIT_ASSERT(strcmp(String::number(0).toCString(), "0") == 0); CPPUNIT_ASSERT(strcmp(String::number(12345678).toCString(), "12345678") == 0); CPPUNIT_ASSERT(strcmp(String::number(-12345678).toCString(), "-12345678") == 0); From 4a7d31c87bf41c1de21cb725176d5b34c2a95720 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Thu, 14 Nov 2013 14:05:32 +0900 Subject: [PATCH 25/32] Rewrote ByteVector::replace() simpler --- taglib/toolkit/tbytevector.cpp | 81 +++++++++++++--------------------- tests/test_bytevector.cpp | 5 +++ 2 files changed, 35 insertions(+), 51 deletions(-) diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index b6582464..566a20fe 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -508,63 +509,41 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit if(pattern.size() == 0 || pattern.size() > size()) return *this; - const uint withSize = with.size(); - const uint patternSize = pattern.size(); - int offset = 0; + const size_t withSize = with.size(); + const size_t patternSize = pattern.size(); + const ptrdiff_t diff = withSize - patternSize; + + size_t offset = 0; + while (true) + { + offset = find(pattern, offset); + if(offset == static_cast(-1)) // Use npos in taglib2. + break; - if(withSize == patternSize) { - // I think this case might be common enough to optimize it detach(); - offset = find(pattern); - while(offset >= 0) { - ::memcpy(data() + offset, with.data(), withSize); - offset = find(pattern, offset + withSize); - } - return *this; - } - // calculate new size: - uint newSize = 0; - for(;;) { - int next = find(pattern, offset); - if(next < 0) { - if(offset == 0) - // pattern not found, do nothing: - return *this; - newSize += size() - offset; + if(diff < 0) { + ::memmove( + data() + offset + withSize, + data() + offset + patternSize, + size() - offset - patternSize); + resize(size() + diff); + } + else if(diff > 0) { + resize(size() + diff); + ::memmove( + data() + offset + withSize, + data() + offset + patternSize, + size() - diff - offset - patternSize); + } + + ::memcpy(data() + offset, with.data(), with.size()); + + offset += withSize; + if(offset > size() - patternSize) break; - } - newSize += (next - offset) + withSize; - offset = next + patternSize; } - // new private data of appropriate size: - ByteVectorPrivate *newData = new ByteVectorPrivate(newSize, 0); - char *target = DATA(newData); - const char *source = data(); - - // copy modified data into new private data: - offset = 0; - for(;;) { - int next = find(pattern, offset); - if(next < 0) { - ::memcpy(target, source + offset, size() - offset); - break; - } - int chunkSize = next - offset; - ::memcpy(target, source + offset, chunkSize); - target += chunkSize; - ::memcpy(target, with.data(), withSize); - target += withSize; - offset += chunkSize + patternSize; - } - - // replace private data: - if(d->deref()) - delete d; - - d = newData; - return *this; } diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp index 9efd23af..eca74f8f 100644 --- a/tests/test_bytevector.cpp +++ b/tests/test_bytevector.cpp @@ -239,6 +239,11 @@ public: a.replace(ByteVector("ab"), ByteVector()); CPPUNIT_ASSERT_EQUAL(ByteVector("cdf"), a); } + { + ByteVector a("abcdabf"); + a.replace(ByteVector("bf"), ByteVector("x")); + CPPUNIT_ASSERT_EQUAL(ByteVector("abcdax"), a); + } } }; From 88d55057fcb11393315096d22e676484e0440ebd Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 15 Nov 2013 15:19:20 +0900 Subject: [PATCH 26/32] Fixed a wrong default parameter of String::ctor() --- taglib/toolkit/tstring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index 32860e19..e0ab0076 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -148,7 +148,7 @@ namespace TagLib { /*! * Makes a deep copy of the data in \a c. */ - String(wchar_t c, Type t = Latin1); + String(wchar_t c, Type t = WCharByteOrder); /*! From 85e1ef1fba6e56c8fe3f28f1a51dd0ac4b1bd2bf Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 15 Nov 2013 15:25:18 +0900 Subject: [PATCH 27/32] Amended some comments about the Type parameters of String::ctor() --- taglib/toolkit/tstring.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index e0ab0076..353d6363 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -129,11 +129,21 @@ namespace TagLib { /*! * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 16-bit codecs UTF16, UTF16BE or + * UTF16LE, when used with other codecs it will simply print a warning and + * exit. UTF16BE or UTF16LE is automatically chosen as default according + * to the CPU byte order */ String(const std::wstring &s, Type t = WCharByteOrder); /*! * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 16-bit codecs UTF16, UTF16BE or + * UTF16LE, when used with other codecs it will simply print a warning and + * exit. UTF16BE or UTF16LE is automatically chosen as default according + * to the CPU byte order */ String(const wchar_t *s, Type t = WCharByteOrder); @@ -147,6 +157,11 @@ namespace TagLib { /*! * Makes a deep copy of the data in \a c. + * + * \note This should only be used with the 16-bit codecs UTF16, UTF16BE or + * UTF16LE, when used with other codecs it will simply print a warning and + * exit. UTF16BE or UTF16LE is automatically chosen as default according + * to the CPU byte order */ String(wchar_t c, Type t = WCharByteOrder); @@ -161,9 +176,6 @@ namespace TagLib { /*! * Makes a deep copy of the data in \a s. - * - * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when - * used with other codecs it will simply print a warning and exit. */ String(const ByteVector &v, Type t = Latin1); From d4adc22922e7288a804691af7df6fd7bf71cef2c Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 15 Nov 2013 15:31:23 +0900 Subject: [PATCH 28/32] Replaced wrongly used slashes with backslashes in some comments --- taglib/mpeg/id3v1/id3v1tag.h | 4 ++-- taglib/toolkit/tstring.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/taglib/mpeg/id3v1/id3v1tag.h b/taglib/mpeg/id3v1/id3v1tag.h index 7b26d023..3fd3f26e 100644 --- a/taglib/mpeg/id3v1/id3v1tag.h +++ b/taglib/mpeg/id3v1/id3v1tag.h @@ -154,14 +154,14 @@ namespace TagLib { /*! * Returns the genre in number. * - * /note Normally 255 indicates that this tag contains no genre. + * \note Normally 255 indicates that this tag contains no genre. */ TagLib::uint genreNumber() const; /*! * Sets the genre in number to \a i. * - * /note Valid value is from 0 up to 255. Normally 255 indicates that + * \note Valid value is from 0 up to 255. Normally 255 indicates that * this tag contains no genre. */ void setGenreNumber(TagLib::uint i); diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index 57945bee..9529c5c5 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -224,7 +224,7 @@ namespace TagLib { * The returned pointer remains valid until this String instance is destroyed * or any other method of this String is called. * - * /note This returns a pointer to the String's internal data without any + * \note This returns a pointer to the String's internal data without any * conversions. * * \see toWString() From 116b1fcff9b686333fdd6d2607c6781e03d708a1 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 15 Nov 2013 16:24:26 +0900 Subject: [PATCH 29/32] Unified the string formatting functions --- taglib/mp4/mp4item.cpp | 45 +++++++----------------------------- taglib/toolkit/tdebug.cpp | 36 +++-------------------------- taglib/toolkit/tstring.cpp | 26 +-------------------- taglib/toolkit/tutils.h | 47 +++++++++++++++++++++++++++++++++++++- tests/test_string.cpp | 7 ++++++ 5 files changed, 65 insertions(+), 96 deletions(-) diff --git a/taglib/mp4/mp4item.cpp b/taglib/mp4/mp4item.cpp index 379ecc80..8f6ef0fa 100644 --- a/taglib/mp4/mp4item.cpp +++ b/taglib/mp4/mp4item.cpp @@ -25,45 +25,16 @@ #include "config.h" -#include -#include - #include "taglib.h" #include "tdebug.h" #include "tsmartptr.h" #include "mp4item.h" +#include "tutils.h" using namespace TagLib; namespace { - String format(const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - - char buf[256]; - -#if defined(HAVE_SNPRINTF) - - vsnprintf(buf, sizeof(buf), fmt, args); - -#elif defined(HAVE_SPRINTF_S) - - vsprintf_s(buf, fmt, args); - -#else - - // Be careful. May cause a buffer overflow. - vsprintf(buf, fmt, args); - -#endif - - va_end(args); - - return String(buf); - } - struct ItemData { bool valid; @@ -263,26 +234,26 @@ MP4::Item::toString() const case TypeBool: return d->data->m_bool ? "true" : "false"; case TypeInt: - return format("%d", d->data->m_int); + return Utils::formatString("%d", d->data->m_int); case TypeIntPair: - return format("%d/%d", d->data->m_intPair.first, d->data->m_intPair.second); + return Utils::formatString("%d/%d", d->data->m_intPair.first, d->data->m_intPair.second); case TypeByte: - return format("%d", d->data->m_byte); + return Utils::formatString("%d", d->data->m_byte); case TypeUInt: - return format("%u", d->data->m_uint); + return Utils::formatString("%u", d->data->m_uint); case TypeLongLong: - return format("%lld", d->data->m_longlong); + return Utils::formatString("%lld", d->data->m_longlong); case TypeStringList: return d->data->m_stringList.toString(" / "); case TypeByteVectorList: for(TagLib::uint i = 0; i < d->data->m_byteVectorList.size(); i++) { - desc.append(format( + desc.append(Utils::formatString( "[%d bytes of data]", static_cast(d->data->m_byteVectorList[i].size()))); } return desc.toString(", "); case TypeCoverArtList: for(TagLib::uint i = 0; i < d->data->m_coverArtList.size(); i++) { - desc.append(format( + desc.append(Utils::formatString( "[%d bytes of data]", static_cast(d->data->m_coverArtList[i].data().size()))); } return desc.toString(", "); diff --git a/taglib/toolkit/tdebug.cpp b/taglib/toolkit/tdebug.cpp index 71350af7..acdb6cc2 100644 --- a/taglib/toolkit/tdebug.cpp +++ b/taglib/toolkit/tdebug.cpp @@ -29,44 +29,13 @@ #include "tdebug.h" #include "tstring.h" +#include "tutils.h" #include "tdebuglistener.h" #include -#include -#include using namespace TagLib; -namespace -{ - String format(const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - - char buf[256]; - -#if defined(HAVE_SNPRINTF) - - vsnprintf(buf, sizeof(buf), fmt, args); - -#elif defined(HAVE_SPRINTF_S) - - vsprintf_s(buf, fmt, args); - -#else - - // Be careful. May cause a buffer overflow. - vsprintf(buf, fmt, args); - -#endif - - va_end(args); - - return String(buf); - } -} - namespace TagLib { // The instance is defined in tdebuglistener.cpp. @@ -88,7 +57,8 @@ namespace TagLib for(size_t i = 0; i < v.size(); ++i) { std::string bits = std::bitset<8>(v[i]).to_string(); - String msg = format("*** [%d] - char '%c' - int %d, 0x%02x, 0b%s\n", + String msg = Utils::formatString( + "*** [%d] - char '%c' - int %d, 0x%02x, 0b%s\n", i, v[i], v[i], v[i], bits.c_str()); debugListener->printMessage(msg); diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 25d8db1c..b77b43b8 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -36,7 +36,6 @@ #include "tutils.h" #include -#include #include #ifdef HAVE_STD_CODECVT @@ -559,30 +558,7 @@ bool String::isAscii() const String String::number(int n) // static { - static const size_t BufferSize = 11; // Sufficient to store "-214748364". - static const char *Format = "%d"; - - char buffer[BufferSize]; - int length; - -#if defined(HAVE_SNPRINTF) - - length = snprintf(buffer, BufferSize, Format, n); - -#elif defined(HAVE_SPRINTF_S) - - length = sprintf_s(buffer, Format, n); - -#else - - length = sprintf(buffer, Format, n); - -#endif - - if(length > 0) - return String(buffer); - else - return String::null; + return Utils::formatString("%d", n); } TagLib::wchar &String::operator[](size_t i) diff --git a/taglib/toolkit/tutils.h b/taglib/toolkit/tutils.h index e6660065..e4e6c953 100644 --- a/taglib/toolkit/tutils.h +++ b/taglib/toolkit/tutils.h @@ -31,7 +31,7 @@ #ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header #ifdef HAVE_CONFIG_H -#include +# include #endif #if defined(HAVE_MSC_BYTESWAP) @@ -44,6 +44,10 @@ # include #endif +#include "tstring.h" +#include +#include + namespace TagLib { namespace Utils @@ -144,6 +148,47 @@ namespace TagLib #endif } + + inline String formatString(const char *format, ...) + { + // Sufficient buffer size for the current internal uses. + // Consider changing this value when you use this function. + + static const size_t BufferSize = 128; + + va_list args; + va_start(args, format); + + char buf[BufferSize]; + int length; + +#if defined(HAVE_SNPRINTF) + + length = vsnprintf(buf, BufferSize, format, args); + +#elif defined(HAVE_SPRINTF_S) + + length = vsprintf_s(buf, format, args); + +#else + + // The last resort. May cause a buffer overflow. + + length = vsprintf(buf, format, args); + if(length >= BufferSize) { + debug("Utils::formatString() - Buffer overflow! Returning an empty string."); + length = -1; + } + +#endif + + va_end(args); + + if(length != -1) + return String(buf); + else + return String::null; + } #ifdef SYSTEM_BYTEORDER diff --git a/tests/test_string.cpp b/tests/test_string.cpp index 0e2807ef..1ca67b22 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -41,6 +41,7 @@ class TestString : public CppUnit::TestFixture CPPUNIT_TEST(testAppendCharDetach); CPPUNIT_TEST(testAppendStringDetach); CPPUNIT_TEST(testToInt); + CPPUNIT_TEST(testFromInt); CPPUNIT_TEST(testSubstr); CPPUNIT_TEST(testNewline); CPPUNIT_TEST_SUITE_END(); @@ -215,6 +216,12 @@ public: CPPUNIT_ASSERT_EQUAL(String("-123aa").toInt(), -123); } + void testFromInt() + { + CPPUNIT_ASSERT_EQUAL(String("123"), String::number(123)); + CPPUNIT_ASSERT_EQUAL(String("-123"), String::number(-123)); + } + void testSubstr() { CPPUNIT_ASSERT_EQUAL(String("01"), String("0123456").substr(0, 2)); From 634d2ede3b85e814a10ee079e0fc7fa3706a1840 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Sat, 16 Nov 2013 10:27:23 +0900 Subject: [PATCH 30/32] Replaced a wrongly used slash with a backslash --- taglib/mpeg/id3v2/id3v2tag.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taglib/mpeg/id3v2/id3v2tag.h b/taglib/mpeg/id3v2/id3v2tag.h index c58d4d86..905ecc9b 100644 --- a/taglib/mpeg/id3v2/id3v2tag.h +++ b/taglib/mpeg/id3v2/id3v2tag.h @@ -89,7 +89,7 @@ namespace TagLib { /*! * Encode a ByteVector with the data from \a s. * - * /note Not implemented intentionally. Always returns empty \s ByteVector. + * \note Not implemented intentionally. Always returns empty \s ByteVector. */ virtual ByteVector render(const String &s) const; }; From 8a22c7ce7590eafcde8ec3294d2ca6fca4e024e2 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 15 Nov 2013 16:51:48 +0900 Subject: [PATCH 31/32] Removed some redundant code from String::operator==() --- taglib/toolkit/tstring.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp index 26a16643..03c350cd 100644 --- a/taglib/toolkit/tstring.cpp +++ b/taglib/toolkit/tstring.cpp @@ -155,11 +155,6 @@ public: { } - StringPrivate(const std::wstring &s) - : data(new std::wstring(s)) - { - } - StringPrivate(size_t n, wchar_t c) : data(new std::wstring(n, c)) { @@ -651,54 +646,43 @@ String &String::operator=(const String &s) String &String::operator=(const std::string &s) { - d->data.reset(new std::wstring()); - copyFromLatin1(s.c_str(), s.length()); - + *this = String(s); return *this; } String &String::operator=(const std::wstring &s) { - d->data.reset(new std::wstring(s)); + *this = String(s); return *this; } String &String::operator=(const wchar_t *s) { - d->data.reset(new std::wstring()); - copyFromUTF16(s, ::wcslen(s), WCharByteOrder); - + *this = String(s); return *this; } String &String::operator=(char c) { - d->data.reset(new std::wstring(1, c)); + *this = String(c); return *this; } String &String::operator=(wchar_t c) { - d->data.reset(new std::wstring(1, c)); + *this = String(c); return *this; } String &String::operator=(const char *s) { - d->data.reset(new std::wstring()); - copyFromLatin1(s, ::strlen(s)); - + *this = String(s); return *this; } String &String::operator=(const ByteVector &v) { - d->data.reset(new std::wstring()); - copyFromLatin1(v.data(), v.size()); - - // If we hit a null in the ByteVector, shrink the string again. - d->data->resize(::wcslen(d->data->c_str())); - + *this = String(v); return *this; } From f7d2935d7b55731b7e235a3ac95fddb28ffbcbb8 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Sat, 16 Nov 2013 19:16:13 +0900 Subject: [PATCH 32/32] Amended some trivial mistakes in some comments --- taglib/riff/wav/infotag.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/taglib/riff/wav/infotag.h b/taglib/riff/wav/infotag.h index 8fba7040..ff01af7a 100644 --- a/taglib/riff/wav/infotag.h +++ b/taglib/riff/wav/infotag.h @@ -38,7 +38,8 @@ namespace TagLib { class File; - //! A RIFF Info tag implementation. + //! A RIFF INFO tag implementation. + namespace RIFF { namespace Info { @@ -76,14 +77,15 @@ namespace TagLib { virtual ByteVector render(const String &s) const; }; - //! The main class in the ID3v2 implementation + //! The main class in the RIFF INFO tag implementation /*! - * This is the main class in the INFO tag implementation. RIFF INFO tag is a - * metadata format found in WAV audio and AVI video files. Though it is a part - * of Microsoft/IBM's RIFF specification, the author could not find the official - * documents about it. So, this implementation is referring to unofficial documents - * online and some applications' behaviors especially Windows Explorer. + * This is the main class in the INFO tag implementation. RIFF INFO tag is + * a metadata format found in WAV audio and AVI video files. Though it is a + * part of Microsoft/IBM's RIFF specification, the author could not find the + * official documents about it. So, this implementation is referring to + * unofficial documents on the web and some applications' behaviors especially + * Windows Explorer. */ class TAGLIB_EXPORT Tag : public TagLib::Tag {