PPI: Add simple connector type compatibility check
[senf.git] / Utils / Exception.hh
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief Exception public header */
25
26 #ifndef HH_Exception_
27 #define HH_Exception_ 1
28
29 // Custom includes
30 #include <exception>
31 #include <string>
32 #include <iostream>
33 #include <sstream>
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>
38
39 //#include "Exception.mpp"
40 ///////////////////////////////hh.p////////////////////////////////////////
41
42 /** \defgroup exception Exception classes
43
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:
46
47     \code
48     try {
49
50         // Some code which might raise an arbitrary senf exception
51
52     }
53     catch (senf::Exception & e) {
54         e << "\handling user " << user;
55         throw;
56     }
57     \endcode
58
59     This will add the user information to any %senf exception thrown. The Exception is however not a
60     stream. If you need to do more extensive formating, either use an intermediate string-stream or
61     use <a href="http://www.boost.org/libs/format/doc/format.html">Boost.Format</a>:
62
63     \code
64     try { 
65         // ...
66     }
67     catch (senf::Exception & e) {
68         e << boost::format("\ncall id 0x%04x@%s") % id % address;
69     }
70     \endcode
71
72     senf::SystemException is thrown for all operating system errors (failures which result in the
73     operating system setting the errno value). It is also derived from senf::Exception and can
74     therefore be extended as well.
75
76     Defining your own exception classes derived from senf::Exception is very simple:
77
78     \code
79     struct FooException : public senf::Exception
80     { FooException() : senf::Exception("Foo hit the fan") {} };
81     \endcode
82  */
83
84 namespace senf {
85
86     /** \brief Generic exception base-class
87
88         Exception is a generic exception base-class which allows the exception to be later extended
89         by catching and re-throwing it (See example in \ref exception).
90
91         \ingroup exception
92       */
93     class Exception
94         : public std::exception
95     {
96     public:
97         ///////////////////////////////////////////////////////////////////////////
98         ///\name Structors and default members
99         ///@{
100
101         virtual ~Exception() throw();
102
103         ///@}
104         ///////////////////////////////////////////////////////////////////////////
105
106         virtual char const * what() const throw();
107         std::string const & message() const;
108
109         void append(std::string text); ///< Extend exception description
110                                         /**< Adds \a text to the description text. */
111
112     protected:
113         Exception(std::string const & description = ""); ///< Initialize exception with string
114                                         /**< \a description is the initial error description
115                                              string. This should probably be a string constant
116                                              describing the exception for most derived
117                                              exceptions. */
118
119     private:
120         std::string message_;
121     };
122
123     template <class Exc, class Arg>
124     typename boost::enable_if< boost::is_convertible<Exc*,Exception*>, Exc & >::type
125     operator<<(Exc const & exc, Arg const & arg); ///< Extend exception description
126                                         /**< Adds \a arg converted to string to the end of the
127                                              exception description string. This operator allows to
128                                              use Exception instances like streams. The conversion is
129                                              performed using <code>boost::lexical_cast</code> and is
130                                              therefor identical to a streaming operation. 
131                                              \see \ref exception */
132
133
134 #   ifdef SENF_DEBUG
135 #       define _SENF_EXC_DEBUG_ARGS ,char const * file=0,int line=0
136 #       define _SENF_EXC_DEBUG_ARGS_ND ,char const *file,int line
137 #       define _SENF_EXC_DEBUG_ARGS_P ,file,line
138 #   else
139 #       define _SENF_EXC_DEBUG_ARGS
140 #       define _SENF_EXC_DEBUG_ARGS_ND
141 #       define _SENF_EXC_DEBUG_ARGS_P
142 #   endif
143
144     /** \brief Exception handling standard UNIX errors (errno)
145
146         This exception is thrown to signal generic \c errno failures. Normally the \c errno value is
147         automatically taken from the \c errno variable but it may also be specified explicitly:
148
149         \code
150         // Standard usage: Take \c errno from environment
151         throw senf::SystemException("::open()") 
152             << " while opening configuration file: " << filename;
153
154         // You may however explicitly specify the errno value
155         throw senf::SystemException("::open()", ENOFILE)
156
157         // Or leave the location information empty
158         throw senf::SystemException(ENOFILE);
159         throw senf::SystemException();
160         \endcode
161
162         From within SENF (<em>and only there because it depends on the \c SENF_DEBUG symbol</em>),
163         SystemException should be thrown using wrapper macros which add additional information to
164         the exception description:
165         \code
166         // Standard usage: Take \c errno from environment
167         SENF_THROW_SYSTEM_EXCEPTION()
168             << " while opening configuration file: " << filename;
169
170         // You may however explicitly specify the errno value
171         throw senf::SystemException("::open()", ENOFILE SENF_EXC_DEBUGINFO)
172         \endcode
173
174         \ingroup exception
175      */
176     class SystemException : public Exception
177     {
178     public:
179         ///////////////////////////////////////////////////////////////////////////
180         ///\name Structors and default members
181         ///@{
182
183         explicit SystemException(std::string const & descr = "" _SENF_EXC_DEBUG_ARGS);
184         explicit SystemException(int code _SENF_EXC_DEBUG_ARGS);
185         SystemException(std::string const & descr, int code _SENF_EXC_DEBUG_ARGS);
186
187         virtual ~SystemException() throw();
188
189         ///@}
190         ///////////////////////////////////////////////////////////////////////////
191
192         int errorNumber() const;        ///< Error code (\c errno number)
193         char const * errorString() const; ///< Error string (\c strerror() value)
194
195         bool anyOf(int c0, int c1=0, int c2=0, int c3=0, int c4=0, int c5=0, 
196                    int c6=0, int c7=0, int c8=0, int c9=0);
197                                         ///< \c true, if errorNumber() is one of \a c0 ... \a c9
198
199
200
201     private:
202         void init(std::string const & descr, int code _SENF_EXC_DEBUG_ARGS_ND);
203         
204         int code_;
205         std::string what_;
206     };
207
208 #   ifdef SENF_DEBUG
209 #       define SENF_EXC_DEBUGINFO ,__FILE__,__LINE__
210 #   else
211 #       define SENF_EXC_DEBUGINFO
212 #   endif
213
214 #   define SENF_THROW_SYSTEM_EXCEPTION(desc) throw SystemException(desc SENF_EXC_DEBUGINFO)
215
216 }
217
218 ///////////////////////////////hh.e////////////////////////////////////////
219 #include "Exception.cci"
220 //#include "Exception.ct"
221 #include "Exception.cti"
222 #endif
223
224 \f
225 // Local Variables:
226 // mode: c++
227 // fill-column: 100
228 // c-file-style: "senf"
229 // indent-tabs-mode: nil
230 // ispell-local-dictionary: "american"
231 // compile-command: "scons -u test"
232 // comment-column: 40
233 // End: