From 710166e32d12c9fe0b0dc5f5f6fed15b6b9f1e32 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Sun, 21 Feb 2016 23:16:48 +0900 Subject: [PATCH] Separate zlib related code rather than having several #ifdef blocks. --- taglib/CMakeLists.txt | 1 + taglib/mpeg/id3v2/id3v2frame.cpp | 61 ++------------ taglib/mpeg/id3v2/id3v2framefactory.cpp | 10 +-- taglib/toolkit/tzlib.cpp | 107 ++++++++++++++++++++++++ taglib/toolkit/tzlib.h | 54 ++++++++++++ tests/test_id3v2.cpp | 40 ++++----- 6 files changed, 190 insertions(+), 83 deletions(-) create mode 100644 taglib/toolkit/tzlib.cpp create mode 100644 taglib/toolkit/tzlib.h diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index c30929fc..f248d0d1 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -309,6 +309,7 @@ set(toolkit_SRCS toolkit/tpropertymap.cpp toolkit/trefcounter.cpp toolkit/tdebuglistener.cpp + toolkit/tzlib.cpp ) if(NOT WIN32) diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp index a9d48f71..d065f2ae 100644 --- a/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/taglib/mpeg/id3v2/id3v2frame.cpp @@ -23,22 +23,16 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#ifdef HAVE_CONFIG_H -#include -#endif - -#if HAVE_ZLIB -#include -#endif - #include #include #include +#include #include "id3v2tag.h" #include "id3v2frame.h" #include "id3v2synchdata.h" + #include "tpropertymap.h" #include "frames/textidentificationframe.h" #include "frames/urllinkframe.h" @@ -251,60 +245,21 @@ ByteVector Frame::fieldData(const ByteVector &frameData) const frameDataOffset += 4; } -#if HAVE_ZLIB - if(d->header->compression() && - !d->header->encryption()) - { + if(zlib::isAvailable() && d->header->compression() && !d->header->encryption()) { if(frameData.size() <= frameDataOffset) { debug("Compressed frame doesn't have enough data to decode"); return ByteVector(); } - z_stream stream = {}; - - if(inflateInit(&stream) != Z_OK) - return ByteVector(); - - ByteVector inData = frameData; - - stream.avail_in = static_cast(inData.size() - frameDataOffset); - stream.next_in = reinterpret_cast(inData.data() + frameDataOffset); - - static const unsigned int chunkSize = 1024; - - ByteVector outData; - ByteVector chunk(chunkSize); - - do { - stream.avail_out = static_cast(chunk.size()); - stream.next_out = reinterpret_cast(chunk.data()); - - int result = inflate(&stream, Z_NO_FLUSH); - - if(result == Z_STREAM_ERROR || - result == Z_NEED_DICT || - result == Z_DATA_ERROR || - result == Z_MEM_ERROR) - { - if(result != Z_STREAM_ERROR) - inflateEnd(&stream); - debug("Error reading compressed stream"); - return ByteVector(); - } - - outData.append(stream.avail_out == 0 ? chunk : chunk.mid(0, chunk.size() - stream.avail_out)); - } while(stream.avail_out == 0); - - inflateEnd(&stream); - - if(frameDataLength != outData.size()) + const ByteVector outData = zlib::decompress(frameData.mid(frameDataOffset)); + if(frameDataLength != outData.size()) { debug("frameDataLength does not match the data length returned by zlib"); + } return outData; } - else -#endif - return frameData.mid(frameDataOffset, frameDataLength); + + return frameData.mid(frameDataOffset, frameDataLength); } String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position) diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index cfa6be23..bbeb56f0 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -23,11 +23,8 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#ifdef HAVE_CONFIG_H -#include -#endif - #include +#include #include "id3v2framefactory.h" #include "id3v2synchdata.h" @@ -174,12 +171,11 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) // TagLib doesn't mess with encrypted frames, so just treat them // as unknown frames. -#if !defined(HAVE_ZLIB) || HAVE_ZLIB == 0 - if(header->compression()) { + if(!zlib::isAvailable() && header->compression()) { debug("Compressed frames are currently not supported."); return new UnknownFrame(data, header); } -#endif + if(header->encryption()) { debug("Encrypted frames are currently not supported."); return new UnknownFrame(data, header); diff --git a/taglib/toolkit/tzlib.cpp b/taglib/toolkit/tzlib.cpp new file mode 100644 index 00000000..7198b630 --- /dev/null +++ b/taglib/toolkit/tzlib.cpp @@ -0,0 +1,107 @@ +/*************************************************************************** + copyright : (C) 2016 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/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_ZLIB +# include +#endif + +#include +#include + +#include "tzlib.h" + +using namespace TagLib; + +bool zlib::isAvailable() +{ +#ifdef HAVE_ZLIB + + return true; + +#else + + return false; + +#endif +} + +ByteVector zlib::decompress(const ByteVector &data) +{ +#ifdef HAVE_ZLIB + + z_stream stream = {}; + + if(inflateInit(&stream) != Z_OK) { + debug("zlib::decompress() - Failed to initizlize zlib."); + return ByteVector(); + } + + ByteVector inData = data; + + stream.avail_in = static_cast(inData.size()); + stream.next_in = reinterpret_cast(inData.data()); + + const unsigned int chunkSize = 1024; + + ByteVector outData; + + do { + const size_t offset = outData.size(); + outData.resize(outData.size() + chunkSize); + + stream.avail_out = static_cast(chunkSize); + stream.next_out = reinterpret_cast(outData.data() + offset); + + const int result = inflate(&stream, Z_NO_FLUSH); + + if(result == Z_STREAM_ERROR || + result == Z_NEED_DICT || + result == Z_DATA_ERROR || + result == Z_MEM_ERROR) + { + if(result != Z_STREAM_ERROR) + inflateEnd(&stream); + + debug("zlib::decompress() - Error reading compressed stream."); + return ByteVector(); + } + + outData.resize(outData.size() - stream.avail_out); + } while(stream.avail_out == 0); + + inflateEnd(&stream); + + return outData; + +#else + + return ByteVector(); + +#endif +} diff --git a/taglib/toolkit/tzlib.h b/taglib/toolkit/tzlib.h new file mode 100644 index 00000000..b1f1fcaf --- /dev/null +++ b/taglib/toolkit/tzlib.h @@ -0,0 +1,54 @@ +/*************************************************************************** + copyright : (C) 2016 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_TZLIB_H +#define TAGLIB_TZLIB_H + +#include + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib { + + namespace zlib { + + /*! + * Returns whether or not zlib is installed and ready to use. + */ + bool isAvailable(); + + /*! + * Decompress \a data by zlib. + */ + ByteVector decompress(const ByteVector &data); + + } +} + +#endif + +#endif diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index 8b9e5b3f..a560658b 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -23,10 +23,6 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#ifdef HAVE_CONFIG_H -#include -#endif - #include #include #include @@ -48,6 +44,7 @@ #include #include #include +#include #include #include "utils.h" @@ -767,26 +764,23 @@ public: MPEG::File f(TEST_FILE_PATH_C("compressed_id3_frame.mp3"), false); CPPUNIT_ASSERT(f.ID3v2Tag()->frameListMap().contains("APIC")); -#ifdef HAVE_ZLIB - - ID3v2::AttachedPictureFrame *frame - = dynamic_cast(f.ID3v2Tag()->frameListMap()["APIC"].front()); - CPPUNIT_ASSERT(frame); - CPPUNIT_ASSERT_EQUAL(String("image/bmp"), frame->mimeType()); - CPPUNIT_ASSERT_EQUAL(ID3v2::AttachedPictureFrame::Other, frame->type()); - CPPUNIT_ASSERT_EQUAL(String(""), frame->description()); - CPPUNIT_ASSERT_EQUAL((unsigned int)86414, frame->picture().size()); - -#else - - // Skip the test if ZLIB is not installed. - // The message "Compressed frames are currently not supported." will be displayed. - - ID3v2::UnknownFrame *frame - = dynamic_cast(f.ID3v2Tag()->frameListMap()["APIC"].front()); - CPPUNIT_ASSERT(frame); + if(zlib::isAvailable()) { + ID3v2::AttachedPictureFrame *frame + = dynamic_cast(f.ID3v2Tag()->frameListMap()["APIC"].front()); + CPPUNIT_ASSERT(frame); + CPPUNIT_ASSERT_EQUAL(String("image/bmp"), frame->mimeType()); + CPPUNIT_ASSERT_EQUAL(ID3v2::AttachedPictureFrame::Other, frame->type()); + CPPUNIT_ASSERT_EQUAL(String(""), frame->description()); + CPPUNIT_ASSERT_EQUAL((unsigned int)86414, frame->picture().size()); + } + else { + // Skip the test if ZLIB is not installed. + // The message "Compressed frames are currently not supported." will be displayed. -#endif + ID3v2::UnknownFrame *frame + = dynamic_cast(f.ID3v2Tag()->frameListMap()["APIC"].front()); + CPPUNIT_ASSERT(frame); + } } void testW000() -- 2.40.0