Blame include/exiv2/error.hpp

Packit 01d647
// ***************************************************************** -*- C++ -*-
Packit 01d647
/*
Packit 01d647
 * Copyright (C) 2004-2018 Exiv2 authors
Packit 01d647
 * This program is part of the Exiv2 distribution.
Packit 01d647
 *
Packit 01d647
 * This program is free software; you can redistribute it and/or
Packit 01d647
 * modify it under the terms of the GNU General Public License
Packit 01d647
 * as published by the Free Software Foundation; either version 2
Packit 01d647
 * of the License, or (at your option) any later version.
Packit 01d647
 *
Packit 01d647
 * This program is distributed in the hope that it will be useful,
Packit 01d647
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 01d647
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 01d647
 * GNU General Public License for more details.
Packit 01d647
 *
Packit 01d647
 * You should have received a copy of the GNU General Public License
Packit 01d647
 * along with this program; if not, write to the Free Software
Packit 01d647
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit 01d647
 */
Packit 01d647
/*!
Packit 01d647
  @file    error.hpp
Packit 01d647
  @brief   Error class for exceptions, log message class
Packit 01d647
  @author  Andreas Huggel (ahu)
Packit 01d647
           ahuggel@gmx.net
Packit 01d647
  @date    15-Jan-04, ahu: created
Packit 01d647
           11-Feb-04, ahu: isolated as a component
Packit 01d647
 */
Packit 01d647
#ifndef ERROR_HPP_
Packit 01d647
#define ERROR_HPP_
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
#include "exiv2lib_export.h"
Packit 01d647
Packit 01d647
// included header files
Packit 01d647
#include "types.hpp"
Packit 01d647
Packit 01d647
// + standard includes
Packit 01d647
#include <exception>
Packit 01d647
#include <string>
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// namespace extensions
Packit 01d647
namespace Exiv2 {
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class definitions
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Class for a log message, used by the library. Applications can set
Packit 01d647
             the log level and provide a customer log message handler (callback
Packit 01d647
             function).
Packit 01d647
Packit 01d647
             This class is meant to be used as a temporary object with the
Packit 01d647
             related macro-magic like this:
Packit 01d647
Packit 01d647
             
Packit 01d647
             EXV_WARNING << "Warning! Something looks fishy.\n";
Packit 01d647
             
Packit 01d647
Packit 01d647
             which translates to
Packit 01d647
Packit 01d647
             
Packit 01d647
             if (LogMsg::warn >= LogMsg::level() && LogMsg::handler())
Packit 01d647
                 LogMsg(LogMsg::warn).os() << "Warning! Something looks fishy.\n";
Packit 01d647
             
Packit 01d647
Packit 01d647
             The macros EXV_DEBUG, EXV_INFO, EXV_WARNING and EXV_ERROR are
Packit 01d647
             shorthands and ensure efficient use of the logging facility: If a
Packit 01d647
             log message doesn't need to be generated because of the log level
Packit 01d647
             setting, the temp object is not even created.
Packit 01d647
Packit 01d647
             Caveat: The entire log message is not processed in this case. So don't
Packit 01d647
             make that call any logic that always needs to be executed.
Packit 01d647
     */
Packit 01d647
    class EXIV2API LogMsg {
Packit 01d647
        //! Prevent copy-construction: not implemented.
Packit 01d647
        LogMsg(const LogMsg&);
Packit 01d647
        //! Prevent assignment: not implemented.
Packit 01d647
        LogMsg& operator=(const LogMsg&);
Packit 01d647
    public:
Packit 01d647
        /*!
Packit 01d647
          @brief Defined log levels. To suppress all log messages, either set the
Packit 01d647
                 log level to \c mute or set the log message handler to 0.
Packit 01d647
         */
Packit 01d647
        enum Level { debug = 0, info = 1, warn = 2, error = 3, mute = 4 };
Packit 01d647
        /*!
Packit 01d647
          @brief Type for a log message handler function. The function receives
Packit 01d647
                 the log level and message and can process it in an application
Packit 01d647
                 specific way.  The default handler sends the log message to
Packit 01d647
                 standard error.
Packit 01d647
         */
Packit 01d647
        typedef void (*Handler)(int, const char*);
Packit 01d647
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Constructor, takes the log message type as an argument
Packit 01d647
        explicit LogMsg(Level msgType);
Packit 01d647
Packit 01d647
        //! Destructor, passes the log message to the message handler depending on the log level
Packit 01d647
        ~LogMsg();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        //! Return a reference to the ostringstream which holds the log message
Packit 01d647
        std::ostringstream& os();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        /*!
Packit 01d647
          @brief Set the log level. Only log messages with a level greater or
Packit 01d647
                 equal \em level are sent to the log message handler. Default
Packit 01d647
                 log level is \c warn. To suppress all log messages, set the log
Packit 01d647
                 level to \c mute (or set the log message handler to 0).
Packit 01d647
        */
Packit 01d647
        static void setLevel(Level level);
Packit 01d647
        /*!
Packit 01d647
          @brief Set the log message handler. The default handler writes log
Packit 01d647
                 messages to standard error. To suppress all log messages, set
Packit 01d647
                 the log message handler to 0 (or set the log level to \c mute).
Packit 01d647
         */
Packit 01d647
        static void setHandler(Handler handler);
Packit 01d647
        //! Return the current log level
Packit 01d647
        static Level level();
Packit 01d647
        //! Return the current log message handler
Packit 01d647
        static Handler handler();
Packit 01d647
        //! The default log handler. Sends the log message to standard error.
Packit 01d647
        static void defaultHandler(int level, const char* s);
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        // DATA
Packit 01d647
        // The output level. Only messages with type >= level_ will be written
Packit 01d647
        static Level level_;
Packit 01d647
        // The log handler in use
Packit 01d647
        static Handler handler_;
Packit 01d647
        // The type of this log message
Packit 01d647
        const Level msgType_;
Packit 01d647
        // Holds the log message until it is passed to the message handler
Packit 01d647
        std::ostringstream os_;
Packit 01d647
Packit 01d647
    }; // class LogMsg
Packit 01d647
Packit 01d647
// Macros for simple access
Packit 01d647
//! Shorthand to create a temp debug log message object and return its ostringstream
Packit 01d647
#define EXV_DEBUG   if (LogMsg::debug >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::debug).os()
Packit 01d647
//! Shorthand for a temp info log message object and return its ostringstream
Packit 01d647
#define EXV_INFO    if (LogMsg::info  >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::info).os()
Packit 01d647
//! Shorthand for a temp warning log message object and return its ostringstream
Packit 01d647
#define EXV_WARNING if (LogMsg::warn  >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::warn).os()
Packit 01d647
//! Shorthand for a temp error log message object and return its ostringstream
Packit 01d647
#define EXV_ERROR   if (LogMsg::error >= LogMsg::level() && LogMsg::handler()) LogMsg(LogMsg::error).os()
Packit 01d647
Packit 01d647
#ifdef _MSC_VER
Packit 01d647
// Disable MSVC warnings "non - DLL-interface classkey 'identifier' used as base
Packit 01d647
// for DLL-interface classkey 'identifier'"
Packit 01d647
# pragma warning( disable : 4275 )
Packit 01d647
#endif
Packit 01d647
Packit 01d647
    //! Generalised toString function
Packit 01d647
    template<typename charT, typename T>
Packit 01d647
    std::basic_string<charT> toBasicString(const T& arg)
Packit 01d647
    {
Packit 01d647
        std::basic_ostringstream<charT> os;
Packit 01d647
        os << arg;
Packit 01d647
        return os.str();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Error class interface. Allows the definition and use of a hierarchy
Packit 01d647
             of error classes which can all be handled in one catch block.
Packit 01d647
             Inherits from the standard exception base-class, to make life
Packit 01d647
             easier for library users (they have the option of catching most
Packit 01d647
             things via std::exception).
Packit 01d647
     */
Packit 01d647
    class EXIV2API AnyError : public std::exception {
Packit 01d647
    public:
Packit 01d647
        AnyError();
Packit 01d647
        AnyError(const AnyError& o);
Packit 01d647
Packit 01d647
        virtual ~AnyError() throw();
Packit 01d647
        ///@brief  Return the error code.
Packit 01d647
        virtual int code() const throw() =0;
Packit 01d647
    };
Packit 01d647
Packit 01d647
    //! %AnyError output operator
Packit 01d647
    inline std::ostream& operator<<(std::ostream& os, const AnyError& error)
Packit 01d647
    {
Packit 01d647
        return os << error.what();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    //! Complete list of all Exiv2 error codes
Packit 01d647
    enum ErrorCode {
Packit 01d647
        kerGeneralError = -1,
Packit 01d647
        kerSuccess = 0,
Packit 01d647
        kerErrorMessage,
Packit 01d647
        kerCallFailed,
Packit 01d647
        kerNotAnImage,
Packit 01d647
        kerInvalidDataset,
Packit 01d647
        kerInvalidRecord,
Packit 01d647
        kerInvalidKey,
Packit 01d647
        kerInvalidTag,
Packit 01d647
        kerValueNotSet,
Packit 01d647
        kerDataSourceOpenFailed,
Packit 01d647
        kerFileOpenFailed,
Packit 01d647
        kerFileContainsUnknownImageType,
Packit 01d647
        kerMemoryContainsUnknownImageType,
Packit 01d647
        kerUnsupportedImageType,
Packit 01d647
        kerFailedToReadImageData,
Packit 01d647
        kerNotAJpeg,
Packit 01d647
        kerFailedToMapFileForReadWrite,
Packit 01d647
        kerFileRenameFailed,
Packit 01d647
        kerTransferFailed,
Packit 01d647
        kerMemoryTransferFailed,
Packit 01d647
        kerInputDataReadFailed,
Packit 01d647
        kerImageWriteFailed,
Packit 01d647
        kerNoImageInInputData,
Packit 01d647
        kerInvalidIfdId,
Packit 01d647
        //! Entry::setValue: Value too large
Packit 01d647
        kerValueTooLarge,
Packit 01d647
        //! Entry::setDataArea: Value too large
Packit 01d647
        kerDataAreaValueTooLarge,
Packit 01d647
        kerOffsetOutOfRange,
Packit 01d647
        kerUnsupportedDataAreaOffsetType,
Packit 01d647
        kerInvalidCharset,
Packit 01d647
        kerUnsupportedDateFormat,
Packit 01d647
        kerUnsupportedTimeFormat,
Packit 01d647
        kerWritingImageFormatUnsupported,
Packit 01d647
        kerInvalidSettingForImage,
Packit 01d647
        kerNotACrwImage,
Packit 01d647
        kerFunctionNotSupported,
Packit 01d647
        kerNoNamespaceInfoForXmpPrefix,
Packit 01d647
        kerNoPrefixForNamespace,
Packit 01d647
        kerTooLargeJpegSegment,
Packit 01d647
        kerUnhandledXmpdatum,
Packit 01d647
        kerUnhandledXmpNode,
Packit 01d647
        kerXMPToolkitError,
Packit 01d647
        kerDecodeLangAltPropertyFailed,
Packit 01d647
        kerDecodeLangAltQualifierFailed,
Packit 01d647
        kerEncodeLangAltPropertyFailed,
Packit 01d647
        kerPropertyNameIdentificationFailed,
Packit 01d647
        kerSchemaNamespaceNotRegistered,
Packit 01d647
        kerNoNamespaceForPrefix,
Packit 01d647
        kerAliasesNotSupported,
Packit 01d647
        kerInvalidXmpText,
Packit 01d647
        kerTooManyTiffDirectoryEntries,
Packit 01d647
        kerMultipleTiffArrayElementTagsInDirectory,
Packit 01d647
        kerWrongTiffArrayElementTagType,
Packit 01d647
        kerInvalidKeyXmpValue,
Packit 01d647
        kerInvalidIccProfile,
Packit 01d647
        kerInvalidXMP,
Packit 01d647
        kerTiffDirectoryTooLarge,
Packit 01d647
        kerInvalidTypeValue,
Packit 01d647
        kerInvalidMalloc,
Packit 01d647
        kerCorruptedMetadata,
Packit 01d647
        kerArithmeticOverflow,
Packit 01d647
        kerMallocFailed,
Packit 01d647
    };
Packit 01d647
Packit 01d647
    /*!
Packit 01d647
      @brief Simple error class used for exceptions. An output operator is
Packit 01d647
             provided to print errors to a stream.
Packit 01d647
     */
Packit 01d647
    template<typename charT>
Packit 01d647
    class EXIV2API BasicError : public AnyError {
Packit 01d647
    public:
Packit 01d647
        //! @name Creators
Packit 01d647
        //@{
Packit 01d647
        //! Constructor taking only an error code
Packit 01d647
        explicit inline BasicError(ErrorCode code);
Packit 01d647
Packit 01d647
        //! Constructor taking an error code and one argument
Packit 01d647
        template<typename A>
Packit 01d647
        inline BasicError(ErrorCode code, const A& arg1);
Packit 01d647
Packit 01d647
        //! Constructor taking an error code and two arguments
Packit 01d647
        template<typename A, typename B>
Packit 01d647
        inline BasicError(ErrorCode code, const A& arg1, const B& arg2);
Packit 01d647
Packit 01d647
        //! Constructor taking an error code and three arguments
Packit 01d647
        template<typename A, typename B, typename C>
Packit 01d647
        inline BasicError(ErrorCode code, const A& arg1, const B& arg2, const C& arg3);
Packit 01d647
Packit 01d647
        //! Virtual destructor. (Needed because of throw())
Packit 01d647
        virtual inline ~BasicError() throw();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        //! @name Accessors
Packit 01d647
        //@{
Packit 01d647
        virtual inline int code() const throw();
Packit 01d647
        /*!
Packit 01d647
          @brief Return the error message as a C-string. The pointer returned by what()
Packit 01d647
                 is valid only as long as the BasicError object exists.
Packit 01d647
         */
Packit 01d647
        virtual inline const char* what() const throw();
Packit 01d647
#ifdef EXV_UNICODE_PATH
Packit 01d647
        /*!
Packit 01d647
          @brief Return the error message as a wchar_t-string. The pointer returned by
Packit 01d647
                 wwhat() is valid only as long as the BasicError object exists.
Packit 01d647
         */
Packit 01d647
        virtual inline const wchar_t* wwhat() const throw();
Packit 01d647
#endif
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
    private:
Packit 01d647
        //! @name Manipulators
Packit 01d647
        //@{
Packit 01d647
        //! Assemble the error message from the arguments
Packit 01d647
        void setMsg();
Packit 01d647
        //@}
Packit 01d647
Packit 01d647
        // DATA
Packit 01d647
        ErrorCode code_;                       //!< Error code
Packit 01d647
        int count_;                             //!< Number of arguments
Packit 01d647
        std::basic_string<charT> arg1_;         //!< First argument
Packit 01d647
        std::basic_string<charT> arg2_;         //!< Second argument
Packit 01d647
        std::basic_string<charT> arg3_;         //!< Third argument
Packit 01d647
        std::string              msg_;          //!< Complete error message
Packit 01d647
#ifdef EXV_UNICODE_PATH
Packit 01d647
        std::wstring             wmsg_;         //!< Complete error message as a wide string
Packit 01d647
#endif
Packit 01d647
    }; // class BasicError
Packit 01d647
Packit 01d647
    //! Error class used for exceptions (std::string based)
Packit 01d647
    typedef BasicError<char> Error;
Packit 01d647
#ifdef EXV_UNICODE_PATH
Packit 01d647
    //! Error class used for exceptions (std::wstring based)
Packit 01d647
    typedef BasicError<wchar_t> WError;
Packit 01d647
#endif
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// free functions, template and inline definitions
Packit 01d647
Packit 01d647
    //! Return the error message for the error with code \em code.
Packit 01d647
    const char* errMsg(int code);
Packit 01d647
Packit 01d647
    template<typename charT>
Packit 01d647
    BasicError<charT>::BasicError(ErrorCode code)
Packit 01d647
        : code_(code), count_(0)
Packit 01d647
    {
Packit 01d647
        setMsg();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    template<typename charT> template<typename A>
Packit 01d647
    BasicError<charT>::BasicError(ErrorCode code, const A& arg1)
Packit 01d647
        : code_(code), count_(1), arg1_(toBasicString<charT>(arg1))
Packit 01d647
    {
Packit 01d647
        setMsg();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    template<typename charT> template<typename A, typename B>
Packit 01d647
    BasicError<charT>::BasicError(ErrorCode code, const A& arg1, const B& arg2)
Packit 01d647
        : code_(code), count_(2),
Packit 01d647
          arg1_(toBasicString<charT>(arg1)),
Packit 01d647
          arg2_(toBasicString<charT>(arg2))
Packit 01d647
    {
Packit 01d647
        setMsg();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    template<typename charT> template<typename A, typename B, typename C>
Packit 01d647
    BasicError<charT>::BasicError(ErrorCode code, const A& arg1, const B& arg2, const C& arg3)
Packit 01d647
        : code_(code), count_(3),
Packit 01d647
          arg1_(toBasicString<charT>(arg1)),
Packit 01d647
          arg2_(toBasicString<charT>(arg2)),
Packit 01d647
          arg3_(toBasicString<charT>(arg3))
Packit 01d647
    {
Packit 01d647
        setMsg();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    template<typename charT>
Packit 01d647
    BasicError<charT>::~BasicError() throw()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    template<typename charT>
Packit 01d647
    int BasicError<charT>::code() const throw()
Packit 01d647
    {
Packit 01d647
        return code_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    template<typename charT>
Packit 01d647
    const char* BasicError<charT>::what() const throw()
Packit 01d647
    {
Packit 01d647
        return msg_.c_str();
Packit 01d647
    }
Packit 01d647
Packit 01d647
#ifdef EXV_UNICODE_PATH
Packit 01d647
    template<typename charT>
Packit 01d647
    const wchar_t* BasicError<charT>::wwhat() const throw()
Packit 01d647
    {
Packit 01d647
        return wmsg_.c_str();
Packit 01d647
    }
Packit 01d647
#endif
Packit 01d647
Packit 01d647
#ifdef _MSC_VER
Packit 01d647
# pragma warning( default : 4275 )
Packit 01d647
#endif
Packit 01d647
Packit 01d647
}                                       // namespace Exiv2
Packit 01d647
#endif                                  // #ifndef ERROR_HPP_