blocxx
Exception.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
39 #ifndef BLOCXX_EXCEPTION_HPP_INCLUDE_GUARD_
40 #define BLOCXX_EXCEPTION_HPP_INCLUDE_GUARD_
41 #include "blocxx/BLOCXX_config.h"
42 #include "blocxx/AutoPtr.hpp"
43 #if defined(BLOCXX_NON_THREAD_SAFE_EXCEPTION_HANDLING)
44 #include "blocxx/CommonFwd.hpp" // for Mutex
45 #endif
46 #include <iosfwd>
47 #include <exception>
48 #include <new>
49 
50 #include <cerrno>
51 
52 namespace BLOCXX_NAMESPACE
53 {
54 
65 class BLOCXX_COMMON_API Exception : public std::exception
66 {
67 protected:
71  Exception(const char* file, int line, const char* msg) BLOCXX_DEPRECATED; // in 3.1.0
88  Exception(const char* file, int line, const char* msg, int errorCode, const Exception* otherException = 0, int subClassId = UNKNOWN_SUBCLASS_ID);
89 
90  Exception(int subClassId, const char* file, int line, const char* msg, int errorCode,
91  const Exception* otherException = 0) BLOCXX_DEPRECATED; // in 3.1.0 -
92  // Had to change the order of the parameters so the subClassId could be
93  // defaulted and the subclasses' signature could match the base class signature.
94 
95 #ifdef BLOCXX_WIN32
96  // Can't seem to catch exceptions by reference if copy CTOR is
97  // protected on Windoz
98 public:
99 #endif
100  Exception(const Exception& e);
101  Exception& operator= (const Exception& rhs);
102 #ifdef BLOCXX_WIN32
103 protected:
104 #endif
105  void swap(Exception& x);
106  void setSubClassId(int subClassId);
107  void setErrorCode(int errorCode);
108 
109 public:
110  virtual ~Exception() throw();
111 
112  static const int UNKNOWN_SUBCLASS_ID = -1;
113  static const int UNKNOWN_ERROR_CODE = -1;
114 
119  virtual const char* type() const;
124  virtual const char* getMessage() const;
128  const char* getFile() const;
129  int getLine() const;
130  int getSubClassId() const;
134  const Exception* getSubException() const;
140  int getErrorCode() const;
141 
145  virtual const char* what() const throw();
146 
158  virtual Exception* clone() const;
159 
164  virtual void rethrow() const;
165 
172  char* dupString(const char* str);
173 
174 private:
175  char* m_file;
176  int m_line;
177  char* m_msg;
178  int m_subClassId;
179  const Exception* m_subException;
180  int m_errorCode;
181 
182 #if defined(BLOCXX_NON_THREAD_SAFE_EXCEPTION_HANDLING)
183  static Mutex* m_mutex;
184 #endif
185 
186 };
187 
188 
189 namespace ExceptionDetail
190 {
191 
192  // Reconciles GNU strerror_r and POSIX strerror_r.
193  //
194  BLOCXX_COMMON_API void portable_strerror_r(int errnum, char * buf, unsigned n);
195 
196  struct BLOCXX_COMMON_API FormatMsgImpl;
197 
198  class BLOCXX_COMMON_API FormatMsg
199  {
200 
201 #ifdef BLOCXX_WIN32
202 #pragma warning (push)
203 #pragma warning (disable: 4251)
204 #endif
205 
207 
208 #ifdef BLOCXX_WIN32
209 #pragma warning (pop)
210 #endif
211 
212  public:
213  FormatMsg(char const * msg, int errnum);
214  ~FormatMsg();
215  char const * get() const;
216  private:
217  FormatMsg(const FormatMsg&);
218  FormatMsg& operator=(const FormatMsg&);
219  };
220 
221  unsigned const BUFSZ = 1024;
222 
223  template <typename exType>
224  struct Errno
225  {
226  static exType simple(char const * file, int line, int errnum)
227  {
228  char buf[BUFSZ];
229  portable_strerror_r(errnum, buf, BUFSZ);
230  return exType(file, line, buf, errnum);
231  }
232 
233  template <typename Mtype>
234  static exType format(char const * file, int line,
235  Mtype const & msg, int errnum)
236  {
237  return format(file, line, msg.c_str(), errnum);
238  }
239 
240  static exType format(char const * file, int line,
241  char const * msg, int errnum)
242  {
243  FormatMsg fm(msg, errnum);
244  return exType(file, line, fm.get(), errnum);
245  }
246  }; // struct Errno
247 
248 } // namespace ExceptionDetail
249 
254 BLOCXX_COMMON_API std::ostream& operator<< (std::ostream& os, const Exception& e);
255 
263 #define BLOCXX_THROW(exType, msg) throw exType(__FILE__, __LINE__, (msg))
264 
268 #define BLOCXX_THROWL(exType, line, msg) throw exType(__FILE__, (line), (msg))
269 
277 #define BLOCXX_THROW_SUBEX(exType, msg, subex) \
278 throw exType(__FILE__, __LINE__, (msg), \
279  ::BLOCXX_NAMESPACE::Exception::UNKNOWN_ERROR_CODE, &(subex))
280 
287 #define BLOCXX_THROW_ERR(exType, msg, err) \
288 throw exType(__FILE__, __LINE__, (msg), (err))
289 
295 #define BLOCXX_THROW_ERRNO(exType) BLOCXX_THROW_ERRNO1(exType, errno)
296 
303 #define BLOCXX_THROW_ERRNO1(exType, errnum) \
304 throw ::BLOCXX_NAMESPACE::ExceptionDetail::Errno< exType >::simple(__FILE__, __LINE__, (errnum))
305 
312 #define BLOCXX_THROW_ERRNO_MSG(exType, msg) \
313 BLOCXX_THROW_ERRNO_MSG1(exType, (msg), errno)
314 
322 #define BLOCXX_THROW_ERRNO_MSG1(exType, msg, errnum) \
323 throw ::BLOCXX_NAMESPACE::ExceptionDetail::Errno< exType >:: \
324  format(__FILE__, __LINE__, (msg), (errnum))
325 
334 #define BLOCXX_THROW_ERR_SUBEX(exType, msg, err, subex) \
335 throw exType(__FILE__, __LINE__, (msg), (err), &(subex))
336 
344 #define BLOCXX_DECLARE_EXCEPTION2(NAME, BASE) \
345 class NAME##Exception : public BASE \
346 { \
347 public: \
348  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); \
349  virtual ~NAME##Exception() throw(); \
350  virtual const char* type() const; \
351  virtual NAME##Exception* clone() const; \
352  virtual void rethrow() const; \
353 };
354 
366 #define BLOCXX_DECLARE_APIEXCEPTION2(NAME, BASE, LINKAGE_SPEC) \
367 class LINKAGE_SPEC NAME##Exception : public BASE \
368 { \
369 public: \
370  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); \
371  virtual ~NAME##Exception() throw(); \
372  virtual const char* type() const; \
373  virtual NAME##Exception* clone() const; \
374  virtual void rethrow() const; \
375 };
376 
377 
378 
379 
386 #define BLOCXX_DECLARE_EXCEPTION(NAME) BLOCXX_DECLARE_EXCEPTION2(NAME, ::BLOCXX_NAMESPACE::Exception)
387 
396 #define BLOCXX_DECLARE_APIEXCEPTION(NAME, LINKAGE_SPEC) BLOCXX_DECLARE_APIEXCEPTION2(NAME, ::BLOCXX_NAMESPACE::Exception, LINKAGE_SPEC)
397 
406 #define BLOCXX_DEFINE_EXCEPTION2(NAME, BASE) \
407 NAME##Exception::NAME##Exception(const char* file, int line, const char* msg, int errorCode, const ::BLOCXX_NAMESPACE::Exception* otherException, int subClassId) \
408  : BASE(file, line, msg, errorCode, otherException, subClassId) {} \
409 NAME##Exception::~NAME##Exception() throw() { } \
410 NAME##Exception* NAME##Exception::clone() const { return new(std::nothrow) NAME##Exception(*this); } \
411 const char* NAME##Exception::type() const { return #NAME "Exception"; }\
412 void NAME##Exception::rethrow() const { throw *this; }
413 
423 #define BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, BASE, SUB_CLASS_ID) \
424 NAME##Exception::NAME##Exception(const char* file, int line, const char* msg, int errorCode, const ::BLOCXX_NAMESPACE::Exception* otherException, int subClassId) \
425  : BASE(file, line, msg, errorCode, otherException, subClassId == ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID ? (SUB_CLASS_ID) : subClassId) {} \
426 NAME##Exception::~NAME##Exception() throw() { } \
427 NAME##Exception* NAME##Exception::clone() const { return new(std::nothrow) NAME##Exception(*this); } \
428 const char* NAME##Exception::type() const { return #NAME "Exception"; } \
429 void NAME##Exception::rethrow() const { throw *this; }
430 
439 #define BLOCXX_DEFINE_EXCEPTION(NAME) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, ::BLOCXX_NAMESPACE::Exception, ::BLOCXX_NAMESPACE::Exception::UNKNOWN_SUBCLASS_ID)
440 
449 #define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME) BLOCXX_DEFINE_EXCEPTION_WITH_BASE_AND_ID_AUX(NAME, ::BLOCXX_NAMESPACE::Exception, ::BLOCXX_NAMESPACE::ExceptionIds::NAME##ExceptionId)
450 
460 #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)
461 
462 } // end namespace BLOCXX_NAMESPACE
463 
464 #endif