4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Exception public header */
27 #define HH_Exception_ 1
34 #include <boost/preprocessor/repeat.hpp>
35 #include <boost/preprocessor/cat.hpp>
36 #include <boost/utility.hpp>
37 #include <boost/type_traits/is_convertible.hpp>
39 //#include "Exception.mpp"
40 ///////////////////////////////hh.p////////////////////////////////////////
42 /** \defgroup exception Exception classes
44 All exceptions in %senf are derived from senf::Exception. This class adds the possibility to
45 extend the exception description while it is processed. The functionality is provided by a mixin
46 class senf::ExceptionMixin:
51 // Some code which might raise an arbitrary senf exception
54 catch (senf::ExceptionMixin & e) {
55 e << "\handling user " << user;
60 This will add the user information to any %senf exception thrown. The Exception is however not a
61 stream. If you need to do more extensive formating, either use an intermediate string-stream or
62 use <a href="http://www.boost.org/libs/format/doc/format.html">Boost.Format</a>:
68 catch (senf::ExceptionMixin & e) {
69 e << boost::format("\ncall id 0x%04x@%s") % id % address;
73 senf::SystemException is thrown for all operating system errors (failures which result in the
74 operating system setting the errno value). It is also derived from senf::Exception and can
75 therefore be extended as well.
77 Defining your own exception classes derived from senf::Exception is very simple:
80 struct FooException : public senf::Exception
81 { FooException() : senf::Exception("Foo hit the fan") {} };
84 If SENF is compiled in debug mode (SENF_DEBUG is defined), the exception message will
85 automatically include a stack backtrace. For this to work, you need to add the
86 <tt>-rdynamic</tt> option to all link commands. This feature depends on <tt>gcc</tt> and
89 To apply these features (extensibility, backtrace) to a non-senf exception, the non-senf
90 exception can be wrapped and rethrown.
94 // ... code that might throw std::bad_cast or somelib::FooException
96 SENF_WRAP_EXC(std::bad_cast)
97 SENF_WRAP_EXC(somelib::FooException)
99 \endcode The re-thrown exception can then be caught as <tt>std::bad_cast</tt> or as
100 senf::ExceptionMixin as needed. It is safe, to wrap an exception twice (the macro will detect
108 catch (senf::ExceptionMixin & ex) {
109 ex << "\nadd this info";
112 catch (std::bad_cast const & ex) {
113 std::cerr << ex.what() << std::endl;
116 The final error output will include
117 \li a backtrace if compiled in debug mode
118 \li the original error message from the <tt>std::bad_cast</tt> exception
119 \li the additional error message "add this info"
121 \todo Link against libcwd to add file-name/line-number information to the backtrace and remove
122 the dependency on -rdynamic
127 /** \brief Generic extensible exception mixin
129 ExceptionMixin is a generic exception mixin which allows the exception to be later extended
130 by catching and re-throwing it (See example in \ref exception).
137 std::string const & message() const;
139 void append(std::string text); ///< Extend exception description
140 /**< Adds \a text to the description text. */
143 explicit ExceptionMixin(std::string const & description = "");
144 ///< Initialize exception with string
145 /**< \a description is the initial error description
146 string. This should probably be a string constant
147 describing the exception for most derived
154 std::string message_;
157 /** \brief Extensible exception base-class
159 This base-class is an exception which already includes the ExceptionMixin. All SENF
160 exceptions are derived from this class. Other user-exception may be defined by deriving from
168 : public ExceptionMixin, public std::exception
171 virtual ~Exception() throw();
173 virtual char const * what() const throw();
176 explicit Exception(std::string const & description = "");
179 /** \brief Wrapper for standard non-senf exceptions
181 This class wraps an exception of type \a BaseException and adds functionality from
182 senf::ExceptionMixin.
186 template <class BaseException>
188 : public ExceptionMixin, public BaseException
191 typedef BaseException Base;
193 WrapException(BaseException const & base);
194 virtual ~WrapException() throw();
196 virtual char const * what() const throw();
199 /** \brief Wrap a non-senf exception
201 This macro allows to wrap a non-senf exception adding functionality from ExceptionMixin
202 using the WrapException template. For an example, see \ref exception.
206 # define SENF_WRAP_EXC(Ex) \
207 catch (Ex const & base) { \
208 if (dynamic_cast<senf::ExceptionMixin const *>(&base)) \
211 throw senf::WrapException<Ex>(base); \
214 template <class Exc, class Arg>
215 typename boost::enable_if< boost::is_convertible<Exc*,ExceptionMixin*>, Exc & >::type
216 operator<<(Exc const & exc, Arg const & arg); ///< Extend exception description
217 /**< Adds \a arg converted to string to the end of the
218 exception description string. This operator allows to
219 use Exception instances like streams. The conversion is
220 performed using <code>boost::lexical_cast</code> and is
221 therefor identical to a streaming operation.
222 \see \ref exception */
226 # define _SENF_EXC_DEBUG_ARGS ,char const * file=0,int line=0
227 # define _SENF_EXC_DEBUG_ARGS_ND ,char const *file,int line
228 # define _SENF_EXC_DEBUG_ARGS_P ,file,line
230 # define _SENF_EXC_DEBUG_ARGS
231 # define _SENF_EXC_DEBUG_ARGS_ND
232 # define _SENF_EXC_DEBUG_ARGS_P
235 /** \brief Exception handling standard UNIX errors (errno)
237 This exception is thrown to signal generic \c errno failures. Normally the \c errno value is
238 automatically taken from the \c errno variable but it may also be specified explicitly:
241 // Standard usage: Take \c errno from environment
242 throw senf::SystemException("::open()")
243 << " while opening configuration file: " << filename;
245 // You may however explicitly specify the errno value
246 throw senf::SystemException("::open()", ENOFILE)
248 // Or leave the location information empty
249 throw senf::SystemException(ENOFILE);
250 throw senf::SystemException();
253 From within SENF (<em>and only there because it depends on the \c SENF_DEBUG symbol</em>),
254 SystemException should be thrown using wrapper macros which add additional information to
255 the exception description:
257 // Standard usage: Take \c errno from environment
258 SENF_THROW_SYSTEM_EXCEPTION()
259 << " while opening configuration file: " << filename;
261 // You may however explicitly specify the errno value
262 throw senf::SystemException("::open()", ENOFILE SENF_EXC_DEBUGINFO)
267 class SystemException : public Exception
270 ///////////////////////////////////////////////////////////////////////////
271 ///\name Structors and default members
274 explicit SystemException(std::string const & descr = "" _SENF_EXC_DEBUG_ARGS);
275 explicit SystemException(int code _SENF_EXC_DEBUG_ARGS);
276 SystemException(std::string const & descr, int code _SENF_EXC_DEBUG_ARGS);
278 virtual ~SystemException() throw();
281 ///////////////////////////////////////////////////////////////////////////
283 int errorNumber() const; ///< Error code (\c errno number)
284 char const * errorString() const; ///< Error string (\c strerror() value)
286 bool anyOf(int c0, int c1=0, int c2=0, int c3=0, int c4=0, int c5=0,
287 int c6=0, int c7=0, int c8=0, int c9=0);
288 ///< \c true, if errorNumber() is one of \a c0 ... \a c9
293 void init(std::string const & descr, int code _SENF_EXC_DEBUG_ARGS_ND);
300 # define SENF_EXC_DEBUGINFO ,__FILE__,__LINE__
302 # define SENF_EXC_DEBUGINFO
305 # define SENF_THROW_SYSTEM_EXCEPTION(desc) throw SystemException(desc SENF_EXC_DEBUGINFO)
309 ///////////////////////////////hh.e////////////////////////////////////////
310 #include "Exception.cci"
311 //#include "Exception.ct"
312 #include "Exception.cti"
319 // c-file-style: "senf"
320 // indent-tabs-mode: nil
321 // ispell-local-dictionary: "american"
322 // compile-command: "scons -u test"
323 // comment-column: 40