blocxx
|
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