removed some useless spaces; not very important, I know :)
[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
38 //#include "Exception.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
40
41 /** \defgroup exception System exceptions
42
43     The senf::SystemException class and it's derived class template senf::ErrnoException are used to
44     signal generic system failures based on \c errno codes. 
45
46     senf::SystemException is a generic \c errno based exception which carries an error number and
47     origin information. senf::ErrnoException is a derived class specialized for a specific error
48     code. This simplifies managing error conditions:
49
50     \code
51     try {
52         something.open(path);
53         // ...
54     }
55     catch (senf::ErrnoException<ENOFILE> & e) {
56         // Create new file
57     }
58     catch (senf::SystemException & e) {
59         // Catch all other system exceptions
60         std::cerr << "Error accessing '" << path << "': " << e.what() << std::endl;
61     }
62     \endcode
63
64     This exception is normally thrown using the senf::throwErrno() helper:
65
66     \code
67     if ((fd = ::open(path.c_str(), O_RDWR)) < 0)
68         senf::throwErrno("::open()");
69     \endcode
70
71     The senf::throwErrno() helper will throw the correct exception class based on some \c errno
72     value.
73  */
74
75 namespace senf {
76
77     /** \brief Exception handling standard UNIX errors (errno)
78
79         This exception is thrown to signal generic \c errno failures. 
80
81         This exception cannot be thrown directly. Instead the derived class ErrnoException should be
82         thrown via one of the senf::throwErrno helpers.
83
84         The error message associated with the SystemException may be extended arbitrarily by using
85         the exception like a stream:
86         \code
87         try {
88             // This throw would normally be within some function called from here.
89             senf::throwErrno("::open()");
90
91             // Or you may want to use a more descriptive argument string:
92             senf::throwErrno("::open(\"" + filename + "\")");
93
94             // Or even use boost::format here
95             senf::throwErrno((boost::format("::open(\"%s\")") % filename).str());
96         }
97         catch (SystemException & e) {
98             // You can add further error information later by catching and re-throwing the exception
99             e << " [while operating on user '" << user << "']";
100             throw;
101         }
102         \endcode
103
104         \see ErrnoException
105         \ingroup exception
106      */
107     class SystemException : public std::exception, public std::stringstream
108     {
109     public:
110         virtual char const * what() const throw(); ///< Return verbose error description
111
112         int errorNumber() const;        ///< Error code (\c errno number)
113         char const * description() const; ///< Error description (strerror() value)
114
115         bool anyOf(int c0, int c1=0, int c2=0, int c3=0, int c4=0, int c5=0, 
116                    int c6=0, int c7=0, int c8=0, int c9=0);
117                                         ///< \c true, if errorNumber() is one of \a c0 ... \a c9
118
119         virtual ~SystemException() throw();
120
121     protected:
122         SystemException(std::string const & where, int code); 
123         SystemException(SystemException const & other);
124
125     private:
126         int const code_;                // This must be const to make the derived ErrnoException
127                                         // class a valid derived class.
128         mutable std::string buffer_;
129
130         friend void throwErrno(std::string const &, int);
131     };
132
133     /** \brief Error specific system exception
134
135         This template restricts the generic SystemException to a specific, compile-time constant
136         error number \p Code. This allows a specific \c errno number to be cached explicitly.
137
138         This exception is normally thrown via one of the senf::throwErrno() helpers. These helpers
139         take the numeric \c errno value (either from the \c errno variable or from their
140         argument) and will throw the corresponding ErrnoException:
141         \code
142         if ((fd = ::open(filename, O_RDWR)) < 0)
143              senf::throwErrno("open()");
144         \endcode
145
146         \see SystemException
147
148         \ingroup exception
149      */
150     template <int Code>
151     class ErrnoException : public SystemException
152     {
153     public:
154         static int const fixed_code = Code;
155
156         explicit ErrnoException(std::string const & where);
157                                         ///< ErrnoException with error location information
158         
159         ErrnoException(ErrnoException const & other);
160     };
161
162     
163     /** \brief Throw ErrnoException based on current \c errno value
164         \ingroup exception
165      */
166     void throwErrno();
167
168     /** \brief Throw ErrnoException based on current \c errno value (with location info)
169         \ingroup exception
170      */
171     void throwErrno(std::string const & where);
172
173     /** \brief Throw ErrnoException based on given \c errno value
174         \ingroup exception
175      */
176     void throwErrno(int code);
177
178     /** \brief Throw ErrnoException based on given \c errno value (with location info)
179         \ingroup exception
180      */
181     void throwErrno(std::string const & where, int code);
182
183 }
184
185 ///////////////////////////////hh.e////////////////////////////////////////
186 #include "Exception.cci"
187 //#include "Exception.ct"
188 #include "Exception.cti"
189 #endif
190
191 \f
192 // Local Variables:
193 // mode: c++
194 // fill-column: 100
195 // c-file-style: "senf"
196 // indent-tabs-mode: nil
197 // ispell-local-dictionary: "american"
198 // compile-command: "scons -u test"
199 // comment-column: 40
200 // End: