00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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"
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
00088
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
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 };
00232
00233 }
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 }
00440
00441 #endif