diff --git a/CMakeLists.txt b/CMakeLists.txt index bbcf8d89..91e1901d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,11 @@ if(WITH_MP4) set(TAGLIB_WITH_MP4 TRUE) endif() +option(TRACE_IN_RELEASE "Output debug messages even in release mode" OFF) +if(TRACE_IN_RELEASE) + set(TRACE_IN_RELEASE TRUE) +endif() + configure_file(taglib/taglib_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h) add_subdirectory(taglib) diff --git a/config.h.cmake b/config.h.cmake index 15d2f997..f8dcbbde 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -31,4 +31,7 @@ /* Defined if you have libz */ #cmakedefine HAVE_ZLIB 1 +/* Indicates whether debug messages are shown even in release mode */ +#cmakedefine TRACE_IN_RELEASE 1 + #cmakedefine TESTS_DIR "@TESTS_DIR@" diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 352f7e2e..23fa60df 100755 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -51,6 +51,7 @@ set(tag_HDRS toolkit/tmap.tcc toolkit/tpropertymap.h toolkit/trefcounter.h + toolkit/tdebuglistener.h mpeg/mpegfile.h mpeg/mpegproperties.h mpeg/mpegheader.h @@ -291,6 +292,7 @@ set(toolkit_SRCS toolkit/tdebug.cpp toolkit/tpropertymap.cpp toolkit/trefcounter.cpp + toolkit/tdebuglistener.cpp toolkit/unicode.cpp ) diff --git a/taglib/taglib_config.h.cmake b/taglib/taglib_config.h.cmake index 1560c247..0f499e2c 100644 --- a/taglib/taglib_config.h.cmake +++ b/taglib/taglib_config.h.cmake @@ -2,4 +2,3 @@ #define TAGLIB_WITH_ASF 1 #define TAGLIB_WITH_MP4 1 - diff --git a/taglib/toolkit/tdebug.cpp b/taglib/toolkit/tdebug.cpp index 522b68c9..65c51efe 100644 --- a/taglib/toolkit/tdebug.cpp +++ b/taglib/toolkit/tdebug.cpp @@ -23,33 +23,75 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#ifndef NDEBUG -#include -#include +#include "config.h" #include "tdebug.h" #include "tstring.h" +#include "tdebuglistener.h" + +#include +#include +#include using namespace TagLib; -void TagLib::debug(const String &s) +namespace { - std::cerr << "TagLib: " << s << std::endl; -} + String format(const char *fmt, ...) + { + va_list args; + va_start(args, fmt); -void TagLib::debugData(const ByteVector &v) -{ - for(uint i = 0; i < v.size(); i++) { + char buf[256]; - std::cout << "*** [" << i << "] - '" << char(v[i]) << "' - int " << int(v[i]) - << std::endl; +#if defined(HAVE_SNPRINTF) - std::bitset<8> b(v[i]); + vsnprintf(buf, sizeof(buf), fmt, args); - for(int j = 0; j < 8; j++) - std::cout << i << ":" << j << " " << b.test(j) << std::endl; +#elif defined(HAVE_SPRINTF_S) - std::cout << std::endl; + 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. + extern DebugListener *debugListener; + + void debug(const String &s) + { +#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE) + + debugListener->printMessage("TagLib: " + s + "\n"); + #endif + } + + void debugData(const ByteVector &v) + { +#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE) + + 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", + i, v[i], v[i], v[i], bits.c_str()); + + debugListener->printMessage(msg); + } + +#endif + } +} diff --git a/taglib/toolkit/tdebug.h b/taglib/toolkit/tdebug.h index 5204fe70..bd94d159 100644 --- a/taglib/toolkit/tdebug.h +++ b/taglib/toolkit/tdebug.h @@ -32,11 +32,11 @@ namespace TagLib { class ByteVector; #ifndef DO_NOT_DOCUMENT -#ifndef NDEBUG /*! - * A simple function that prints debugging output to cerr if debugging is - * not disabled. + * A simple function that outputs the debug messages to the listener. + * The default listener redirects the messages to \a stderr when NDEBUG is + * not defined. * * \warning Do not use this outside of TagLib, it could lead to undefined * symbols in your build if TagLib is built with NDEBUG defined and your @@ -45,7 +45,7 @@ namespace TagLib { * \internal */ void debug(const String &s); - + /*! * For debugging binary data. * @@ -56,16 +56,7 @@ namespace TagLib { * \internal */ void debugData(const ByteVector &v); - -#else - - // Define these to an empty statement if debugging is disabled. - -#define debug(x) -#define debugData(x) - -#endif -#endif } #endif +#endif diff --git a/taglib/toolkit/tdebuglistener.cpp b/taglib/toolkit/tdebuglistener.cpp new file mode 100644 index 00000000..48912222 --- /dev/null +++ b/taglib/toolkit/tdebuglistener.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + 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 "tdebuglistener.h" + +#include +#include + +#ifdef _WIN32 +# include +#endif + +using namespace TagLib; + +namespace +{ + class DefaultListener : public DebugListener + { + public: + virtual void printMessage(const String &msg) + { +#ifdef _WIN32 + + const wstring wstr = msg.toWString(); + const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL); + if(len != 0) { + std::vector buf(len); + WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL); + + std::cerr << std::string(&buf[0]); + } + +#else + + std::cerr << msg; + +#endif + } + }; + + DefaultListener defaultListener; +} + +namespace TagLib +{ + DebugListener *debugListener = &defaultListener; + + DebugListener::DebugListener() + { + } + + DebugListener::~DebugListener() + { + } + + void setDebugListener(DebugListener *listener) + { + if(listener) + debugListener = listener; + else + debugListener = &defaultListener; + } +} diff --git a/taglib/toolkit/tdebuglistener.h b/taglib/toolkit/tdebuglistener.h new file mode 100644 index 00000000..a32f285f --- /dev/null +++ b/taglib/toolkit/tdebuglistener.h @@ -0,0 +1,74 @@ +/*************************************************************************** + 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_DEBUGLISTENER_H +#define TAGLIB_DEBUGLISTENER_H + +#include "taglib_export.h" +#include "tstring.h" + +namespace TagLib +{ + //! An abstraction for the listener to the debug messages. + + /*! + * This class enables you to handle the debug messages in your preferred + * way by subclassing this class, reimplementing printMessage() and setting + * your reimplementation as the default with setDebugListener(). + * + * \see setDebugListener() + */ + class TAGLIB_EXPORT DebugListener + { + public: + DebugListener(); + virtual ~DebugListener(); + + /*! + * When overridden in a derived class, redirects \a msg to your preferred + * channel such as stderr, Windows debugger or so forth. + */ + virtual void printMessage(const String &msg) = 0; + + private: + // Noncopyable + DebugListener(const DebugListener &); + DebugListener &operator=(const DebugListener &); + }; + + /*! + * Sets the listener that decides how the debug messages are redirected. + * If the parameter \a listener is null, the previous listener is released + * and default stderr listener is restored. + * + * \note The caller is responsible for deleting the previous listener + * as needed after it is released. + * + * \see DebugListener + */ + TAGLIB_EXPORT void setDebugListener(DebugListener *listener); +} + +#endif