blocxx

Exception.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2006, Novell, Inc. All rights reserved.
00004 * 
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 * 
00008 *     * Redistributions of source code must retain the above copyright notice,
00009 *       this list of conditions and the following disclaimer.
00010 *     * Redistributions in binary form must reproduce the above copyright
00011 *       notice, this list of conditions and the following disclaimer in the
00012 *       documentation and/or other materials provided with the distribution.
00013 *     * Neither the name of 
00014 *       Vintela, Inc., 
00015 *       nor Novell, Inc., 
00016 *       nor the names of its contributors or employees may be used to 
00017 *       endorse or promote products derived from this software without 
00018 *       specific prior written permission.
00019 * 
00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030 * POSSIBILITY OF SUCH DAMAGE.
00031 *******************************************************************************/
00032 
00033 
00039 #ifndef BLOCXX_EXCEPTION_HPP_INCLUDE_GUARD_
00040 #define BLOCXX_EXCEPTION_HPP_INCLUDE_GUARD_
00041 #include "blocxx/BLOCXX_config.h"
00042 #include "blocxx/AutoPtr.hpp"
00043 #if defined(BLOCXX_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00044 #include "blocxx/CommonFwd.hpp" // for Mutex
00045 #endif
00046 #include <iosfwd>
00047 #include <exception>
00048 #include <new>
00049 
00050 #include <cerrno>
00051 
00052 namespace BLOCXX_NAMESPACE
00053 {
00054 
00065 class BLOCXX_COMMON_API Exception : public std::exception
00066 {
00067 protected:
00071    Exception(const char* file, int line, const char* msg) BLOCXX_DEPRECATED; // in 3.1.0
00088    Exception(const char* file, int line, const char* msg, int errorCode, const Exception* otherException = 0, int subClassId = UNKNOWN_SUBCLASS_ID);
00089 
00090    Exception(int subClassId, const char* file, int line, const char* msg, int errorCode,
00091       const Exception* otherException = 0) BLOCXX_DEPRECATED; // in 3.1.0 -
00092       // Had to change the order of the parameters so the subClassId could be
00093       // defaulted and the subclasses' signature could match the base class signature.
00094 
00095 #ifdef BLOCXX_WIN32
00096    // Can't seem to catch exceptions by reference if copy CTOR is
00097    // protected on Windoz
00098 public:
00099 #endif
00100    Exception(const Exception& e);
00101    Exception& operator= (const Exception& rhs);
00102 #ifdef BLOCXX_WIN32
00103 protected:
00104 #endif
00105    void swap(Exception& x);
00106    void setSubClassId(int subClassId);
00107    void setErrorCode(int errorCode);
00108 
00109 public:
00110    virtual ~Exception() throw();
00111 
00112    static const int UNKNOWN_SUBCLASS_ID = -1;
00113    static const int UNKNOWN_ERROR_CODE = -1;
00114 
00119    virtual const char* type() const;
00124    virtual const char* getMessage() const;
00128    const char* getFile() const;
00129    int getLine() const;
00130    int getSubClassId() const;
00134    const Exception* getSubException() const;
00140    int getErrorCode() const;
00141 
00145    virtual const char* what() const throw();
00146 
00158    virtual Exception* clone() const;
00159 
00164    virtual void rethrow() const;
00165 
00172    char* dupString(const char* str);
00173 
00174 private:
00175    char* m_file;
00176    int m_line;
00177    char* m_msg;
00178    int m_subClassId;
00179    const Exception* m_subException;
00180    int m_errorCode;
00181 
00182 #if defined(BLOCXX_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00183    static Mutex* m_mutex;
00184 #endif
00185 
00186 };
00187 
00188 
00189 namespace ExceptionDetail
00190 {
00191 
00192    // Reconciles GNU strerror_r and POSIX strerror_r.
00193    //
00194    BLOCXX_COMMON_API void portable_strerror_r(int errnum, char * buf, unsigned n);
00195 
00196    struct BLOCXX_COMMON_API FormatMsgImpl;
00197 
00198    class BLOCXX_COMMON_API FormatMsg
00199    {
00200 
00201 #ifdef BLOCXX_WIN32
00202 #pragma warning (push)
00203 #pragma warning (disable: 4251)
00204 #endif
00205 
00206       AutoPtr<FormatMsgImpl> pImpl;
00207 
00208 #ifdef BLOCXX_WIN32
00209 #pragma warning (pop)
00210 #endif
00211 
00212    public:
00213       FormatMsg(char const * msg, int errnum);
00214       ~FormatMsg();
00215       char const * get() const;
00216    private:
00217       FormatMsg(const FormatMsg&);
00218       FormatMsg& operator=(const FormatMsg&);
00219    };
00220 
00221    unsigned const BUFSZ = 1024;
00222 
00223    template <typename exType>
00224    struct Errno
00225    {
00226       static exType simple(char const * file, int line, int errnum)
00227       {
00228          char buf[BUFSZ];
00229          portable_strerror_r(errnum, buf, BUFSZ);
00230          return exType(file, line, buf, errnum);
00231       }
00232 
00233       template <typename Mtype>
00234       static exType format(char const * file, int line,
00235                            Mtype const & msg, int errnum)
00236       {
00237          return format(file, line, msg.c_str(), errnum);
00238       }
00239 
00240       static exType format(char const * file, int line,
00241                            char const * msg, int errnum)
00242       {
00243          FormatMsg fm(msg, errnum);
00244          return exType(file, line, fm.get(), errnum);
00245       }
00246    }; // struct Errno
00247 
00248 } // namespace ExceptionDetail
00249 
00254 BLOCXX_COMMON_API std::ostream& operator<< (std::ostream& os, const Exception& e);
00255 
00263 #define BLOCXX_THROW(exType, msg) throw exType(__FILE__, __LINE__, (msg))
00264 
00268 #define BLOCXX_THROWL(exType, line, msg) throw exType(__FILE__, (line), (msg))
00269 
00277 #define BLOCXX_THROW_SUBEX(exType, msg, subex) \
00278 throw exType(__FILE__, __LINE__, (msg), \
00279              ::BLOCXX_NAMESPACE::Exception::UNKNOWN_ERROR_CODE, &(subex))
00280 
00287 #define BLOCXX_THROW_ERR(exType, msg, err) \
00288 throw exType(__FILE__, __LINE__, (msg), (err))
00289 
00295 #define BLOCXX_THROW_ERRNO(exType) BLOCXX_THROW_ERRNO1(exType, errno)
00296 
00303 #define BLOCXX_THROW_ERRNO1(exType, errnum) \
00304 throw ::BLOCXX_NAMESPACE::ExceptionDetail::Errno< exType >::simple(__FILE__, __LINE__, (errnum))
00305 
00312 #define BLOCXX_THROW_ERRNO_MSG(exType, msg) \
00313 BLOCXX_THROW_ERRNO_MSG1(exType, (msg), errno)
00314 
00322 #define BLOCXX_THROW_ERRNO_MSG1(exType, msg, errnum) \
00323 throw ::BLOCXX_NAMESPACE::ExceptionDetail::Errno< exType >:: \
00324       format(__FILE__, __LINE__, (msg), (errnum))
00325 
00334 #define BLOCXX_THROW_ERR_SUBEX(exType, msg, err, subex) \
00335 throw exType(__FILE__, __LINE__, (msg), (err), &(subex))
00336 
00344 #define BLOCXX_DECLARE_EXCEPTION2(NAME, BASE) \
00345 class NAME##Exception : public BASE \
00346 { \
00347 public: \
00348    NAME##Exception(const char* file, int line, const char* msg, int errorCode = ::BLOCXX_NAMESPACE::Exception::UNKNOWN_ERROR_CODE, const Exception* otherException = 0, int subClassId = ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID); \
00349    virtual ~NAME##Exception() throw(); \
00350    virtual const char* type() const; \
00351    virtual NAME##Exception* clone() const; \
00352    virtual void rethrow() const; \
00353 };
00354 
00366 #define BLOCXX_DECLARE_APIEXCEPTION2(NAME, BASE, LINKAGE_SPEC) \
00367 class LINKAGE_SPEC NAME##Exception : public BASE \
00368 { \
00369 public: \
00370    NAME##Exception(const char* file, int line, const char* msg, int errorCode = ::BLOCXX_NAMESPACE::Exception::UNKNOWN_ERROR_CODE, const Exception* otherException = 0, int subClassId = ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID); \
00371    virtual ~NAME##Exception() throw(); \
00372    virtual const char* type() const; \
00373    virtual NAME##Exception* clone() const; \
00374    virtual void rethrow() const; \
00375 };
00376 
00377 
00378 
00379 
00386 #define BLOCXX_DECLARE_EXCEPTION(NAME) BLOCXX_DECLARE_EXCEPTION2(NAME, ::BLOCXX_NAMESPACE::Exception)
00387 
00396 #define BLOCXX_DECLARE_APIEXCEPTION(NAME, LINKAGE_SPEC) BLOCXX_DECLARE_APIEXCEPTION2(NAME, ::BLOCXX_NAMESPACE::Exception, LINKAGE_SPEC)
00397 
00406 #define BLOCXX_DEFINE_EXCEPTION2(NAME, BASE) \
00407 NAME##Exception::NAME##Exception(const char* file, int line, const char* msg, int errorCode, const ::BLOCXX_NAMESPACE::Exception* otherException, int subClassId) \
00408    : BASE(file, line, msg, errorCode, otherException, subClassId) {} \
00409 NAME##Exception::~NAME##Exception() throw() { } \
00410 NAME##Exception* NAME##Exception::clone() const { return new(std::nothrow) NAME##Exception(*this); } \
00411 const char* NAME##Exception::type() const { return #NAME "Exception"; }\
00412 void NAME##Exception::rethrow() const { throw *this; }
00413 
00423 #define BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, BASE, SUB_CLASS_ID) \
00424 NAME##Exception::NAME##Exception(const char* file, int line, const char* msg, int errorCode, const ::BLOCXX_NAMESPACE::Exception* otherException, int subClassId) \
00425    : BASE(file, line, msg, errorCode, otherException, subClassId == ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID ? (SUB_CLASS_ID) : subClassId) {} \
00426 NAME##Exception::~NAME##Exception() throw() { } \
00427 NAME##Exception* NAME##Exception::clone() const { return new(std::nothrow) NAME##Exception(*this); } \
00428 const char* NAME##Exception::type() const { return #NAME "Exception"; } \
00429 void NAME##Exception::rethrow() const { throw *this; }
00430 
00439 #define BLOCXX_DEFINE_EXCEPTION(NAME) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, ::BLOCXX_NAMESPACE::Exception, ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID)
00440 
00449 #define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, ::BLOCXX_NAMESPACE::Exception, ::BLOCXX_NAMESPACE::ExceptionIds::NAME##ExceptionId)
00450 
00460 #define BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID(NAME, BASE) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, BASE, ::BLOCXX_NAMESPACE::ExceptionIds::NAME##ExceptionId)
00461 
00462 } // end namespace BLOCXX_NAMESPACE
00463 
00464 #endif