Exception.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 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 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00038 #ifndef BLOCXX_EXCEPTION_HPP_INCLUDE_GUARD_
00039 #define BLOCXX_EXCEPTION_HPP_INCLUDE_GUARD_
00040 #include "blocxx/BLOCXX_config.h"
00041 #include "blocxx/AutoPtr.hpp"
00042 #if defined(BLOCXX_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00043 #include "blocxx/CommonFwd.hpp" // for Mutex
00044 #endif
00045 #include <iosfwd>
00046 #include <exception>
00047 #include <new>
00048 
00049 #include <cerrno>
00050 
00051 namespace BLOCXX_NAMESPACE
00052 {
00053 
00064 class BLOCXX_COMMON_API Exception : public std::exception
00065 {
00066 protected:
00083    Exception(const char* file, int line, const char* msg, int errorCode, const Exception* otherException = 0, int subClassId = UNKNOWN_SUBCLASS_ID);
00084 
00085 
00086 #ifdef BLOCXX_WIN32
00087    // Can't seem to catch exceptions by reference if copy CTOR is
00088    // protected on Windoz
00089 public:
00090 #endif
00091    Exception(const Exception& e);
00092    Exception& operator= (const Exception& rhs);
00093 #ifdef BLOCXX_WIN32
00094 protected:
00095 #endif
00096    void swap(Exception& x);
00097    virtual ~Exception() throw();
00098    void setSubClassId(int subClassId);
00099    void setErrorCode(int errorCode);
00100 
00101 public:
00102 
00103    static const int UNKNOWN_SUBCLASS_ID = -1;
00104    static const int UNKNOWN_ERROR_CODE = -1;
00105 
00110    virtual const char* type() const;
00115    virtual const char* getMessage() const;
00119    const char* getFile() const;
00120    int getLine() const;
00121    int getSubClassId() const;
00125    const Exception* getSubException() const;
00131    int getErrorCode() const;
00132 
00136    virtual const char* what() const throw();
00137 
00149    virtual Exception* clone() const;
00150 
00157    char* dupString(const char* str);
00158 
00159 private:
00160    char* m_file;
00161    int m_line;
00162    char* m_msg;
00163    int m_subClassId;
00164    const Exception* m_subException;
00165    int m_errorCode;
00166 
00167 #if defined(BLOCXX_NON_THREAD_SAFE_EXCEPTION_HANDLING)
00168    static Mutex* m_mutex;
00169 #endif
00170 
00171 };
00172 
00173 
00174 namespace ExceptionDetail
00175 {
00176 
00177    // Reconciles GNU strerror_r and POSIX strerror_r.
00178    //
00179    BLOCXX_COMMON_API void portable_strerror_r(int errnum, char * buf, unsigned n);
00180 
00181    struct BLOCXX_COMMON_API FormatMsgImpl;
00182 
00183    class BLOCXX_COMMON_API FormatMsg
00184    {
00185 
00186 #ifdef BLOCXX_WIN32
00187 #pragma warning (push)
00188 #pragma warning (disable: 4251)
00189 #endif
00190 
00191       AutoPtr<FormatMsgImpl> pImpl;
00192 
00193 #ifdef BLOCXX_WIN32
00194 #pragma warning (pop)
00195 #endif
00196 
00197    public:
00198       FormatMsg(char const * msg, int errnum);
00199       ~FormatMsg();
00200       char const * get() const;
00201    private:
00202       FormatMsg(const FormatMsg&);
00203       FormatMsg& operator=(const FormatMsg&);
00204    };
00205 
00206    unsigned const BUFSZ = 1024;
00207 
00208    template <typename exType>
00209    struct Errno
00210    {
00211       static exType simple(char const * file, int line, int errnum)
00212       {
00213          char buf[BUFSZ];
00214          portable_strerror_r(errnum, buf, BUFSZ);
00215          return exType(file, line, buf, errnum);
00216       }
00217 
00218       template <typename Mtype>
00219       static exType format(char const * file, int line,
00220                            Mtype const & msg, int errnum)
00221       {
00222          return format(file, line, msg.c_str(), errnum);
00223       }
00224 
00225       static exType format(char const * file, int line,
00226                            char const * msg, int errnum)
00227       {
00228          FormatMsg fm(msg, errnum);
00229          return exType(file, line, fm.get(), errnum);
00230       }
00231    }; // struct Errno
00232 
00233 } // namespace ExceptionDetail
00234 
00239 BLOCXX_COMMON_API std::ostream& operator<< (std::ostream& os, const Exception& e);
00240 
00248 #define BLOCXX_THROW(exType, msg) throw exType(__FILE__, __LINE__, (msg))
00249 
00253 #define BLOCXX_THROWL(exType, line, msg) throw exType(__FILE__, (line), (msg))
00254 
00262 #define BLOCXX_THROW_SUBEX(exType, msg, subex) \
00263 throw exType(__FILE__, __LINE__, (msg), \
00264              ::BLOCXX_NAMESPACE::Exception::UNKNOWN_ERROR_CODE, &(subex))
00265 
00272 #define BLOCXX_THROW_ERR(exType, msg, err) \
00273 throw exType(__FILE__, __LINE__, (msg), (err))
00274 
00280 #define BLOCXX_THROW_ERRNO(exType) BLOCXX_THROW_ERRNO1(exType, errno)
00281 
00287 #define BLOCXX_THROW_ERRNO1(exType, errnum) \
00288 throw ::BLOCXX_NAMESPACE::ExceptionDetail::Errno< exType >::simple(__FILE__, __LINE__, (errnum))
00289 
00295 #define BLOCXX_THROW_ERRNO_MSG(exType, msg) \
00296 BLOCXX_THROW_ERRNO_MSG1(exType, (msg), errno)
00297 
00303 #define BLOCXX_THROW_ERRNO_MSG1(exType, msg, errnum) \
00304 throw ::BLOCXX_NAMESPACE::ExceptionDetail::Errno< exType >:: \
00305       format(__FILE__, __LINE__, (msg), (errnum))
00306 
00315 #define BLOCXX_THROW_ERR_SUBEX(exType, msg, err, subex) \
00316 throw exType(__FILE__, __LINE__, (msg), (err), &(subex))
00317 
00325 #define BLOCXX_DECLARE_EXCEPTION2(NAME, BASE) \
00326 class NAME##Exception : public BASE \
00327 { \
00328 public: \
00329    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); \
00330    virtual ~NAME##Exception() throw(); \
00331    virtual const char* type() const; \
00332    virtual NAME##Exception* clone() const; \
00333 };
00334 
00346 #define BLOCXX_DECLARE_APIEXCEPTION2(NAME, BASE, LINKAGE_SPEC) \
00347 class LINKAGE_SPEC NAME##Exception : public BASE \
00348 { \
00349 public: \
00350    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); \
00351    virtual ~NAME##Exception() throw(); \
00352    virtual const char* type() const; \
00353    virtual NAME##Exception* clone() const; \
00354 };
00355 
00356 
00357 
00358 
00365 #define BLOCXX_DECLARE_EXCEPTION(NAME) BLOCXX_DECLARE_EXCEPTION2(NAME, ::BLOCXX_NAMESPACE::Exception)
00366 
00375 #define BLOCXX_DECLARE_APIEXCEPTION(NAME, LINKAGE_SPEC) BLOCXX_DECLARE_APIEXCEPTION2(NAME, ::BLOCXX_NAMESPACE::Exception, LINKAGE_SPEC)
00376 
00385 #define BLOCXX_DEFINE_EXCEPTION2(NAME, BASE) \
00386 NAME##Exception::NAME##Exception(const char* file, int line, const char* msg, int errorCode, const ::BLOCXX_NAMESPACE::Exception* otherException, int subClassId) \
00387    : BASE(file, line, msg, errorCode, otherException, subClassId) {} \
00388 NAME##Exception::~NAME##Exception() throw() { } \
00389 NAME##Exception* NAME##Exception::clone() const { return new(std::nothrow) NAME##Exception(*this); } \
00390 const char* NAME##Exception::type() const { return #NAME "Exception"; }
00391 
00401 #define BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, BASE, SUB_CLASS_ID) \
00402 NAME##Exception::NAME##Exception(const char* file, int line, const char* msg, int errorCode, const ::BLOCXX_NAMESPACE::Exception* otherException, int subClassId) \
00403    : BASE(file, line, msg, errorCode, otherException, subClassId == ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID ? (SUB_CLASS_ID) : subClassId) {} \
00404 NAME##Exception::~NAME##Exception() throw() { } \
00405 NAME##Exception* NAME##Exception::clone() const { return new(std::nothrow) NAME##Exception(*this); } \
00406 const char* NAME##Exception::type() const { return #NAME "Exception"; }
00407 
00416 #define BLOCXX_DEFINE_EXCEPTION(NAME) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, ::BLOCXX_NAMESPACE::Exception, ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID)
00417 
00426 #define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, ::BLOCXX_NAMESPACE::Exception, ::BLOCXX_NAMESPACE::ExceptionIds::NAME##ExceptionId)
00427 
00437 #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)
00438 
00439 } // end namespace BLOCXX_NAMESPACE
00440 
00441 #endif

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6