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
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"
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;
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;
00092
00093
00094
00095 #ifdef BLOCXX_WIN32
00096
00097
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
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 };
00247
00248 }
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 }
00463
00464 #endif