// $Id$
//
// Copyright (C) 2006
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-// Stefan Bund <stefan.bund@fokus.fraunhofer.de>
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// Custom includes
#include <exception>
#include <string>
+#include <iostream>
+#include <sstream>
+#include <boost/preprocessor/repeat.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/utility.hpp>
//#include "Exception.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-namespace senf {
+/** \defgroup exception System exceptions
- /** \brief Exception handling standard UNIX errors (errno)
+ The senf::SystemException class and it's derived class template senf::ErrnoException are used to
+ signal generic system failures based on \c errno codes.
+
+ senf::SystemException is a generic \c errno based exception which carries an error number and
+ origin information. senf::ErrnoException is a derived class specialized for a specific error
+ code. This simplifies managing error conditions:
+
+ \code
+ try {
+ something.open(path);
+ // ...
+ }
+ catch (senf::ErrnoException<ENOFILE> & e) {
+ // Create new file
+ }
+ catch (senf::SystemException & e) {
+ // Catch all other system exceptions
+ std::cerr << "Error accessing '" << path << "': " << e.what() << std::endl;
+ }
+ \endcode
- This exception is thrown to signal generic errno failures.
+ This exception is normally thrown using the senf::throwErrno() helper:
- \todo make where and err accessors and make the member vars private
+ \code
+ if ((fd = ::open(path.c_str(), O_RDWR)) < 0)
+ senf::throwErrno("::open()");
+ \endcode
- \idea Add a template class derived from SystemException which
- takes the error number as a numeric argument. This allows
- catching specific errno conditions: ErrnoException<EPIPE> etc.
+ The senf::throwErrno() helper will throw the correct exception class based on some \c errno
+ value.
+ */
+
+namespace senf {
+
+ /** \brief Exception handling standard UNIX errors (errno)
- \idea Add a generic error thrower which takes the origin
- string and errno value as an argument and will throw a
- corresponding template class instance. This would just be a
- big switch statement containing all possible errno values,
- probably created using some macro metaprogramming.
+ This exception is thrown to signal generic \c errno failures.
+
+ This exception cannot be thrown directly. Instead the derived class ErrnoException should be
+ thrown via one of the senf::throwErrno helpers.
+
+ The error message associated with the SystemException may be extended arbitrarily by using
+ the exception like a stream:
+ \code
+ try {
+ // This throw would normally be within some function called from here.
+ senf::throwErrno("::open()");
+
+ // Or you may want to use a more descriptive argument string:
+ senf::throwErrno("::open(\"" + filename + "\")");
+
+ // Or even use boost::format here
+ senf::throwErrno((boost::format("::open(\"%s\")") % filename).str());
+ }
+ catch (SystemException & e) {
+ // You can add further error information later by catching and re-throwing the exception
+ e << " [while operating on user '" << user << "']";
+ throw;
+ }
+ \endcode
+
+ \see ErrnoException
+ \ingroup exception
*/
- class SystemException : public std::exception
+ class SystemException : public std::exception, public std::stringstream
{
public:
- explicit SystemException(int err); ///< SystemException without error lokus info
- /**< \param[in] err error number (the errno value) */
- SystemException(char const * where, int err); ///< SystemException with error location info
- /**< \param[in] where description of error origin
- \param[in] err error number (the errno value) */
-
virtual char const * what() const throw(); ///< Return verbose error description
- char const * where; ///< Error origin
- int err; ///< Error number
+ int errorNumber() const; ///< Error code (\c errno number)
+ char const * description() const; ///< Error description (strerror() value)
+
+ bool anyOf(int c0, int c1=0, int c2=0, int c3=0, int c4=0, int c5=0,
+ int c6=0, int c7=0, int c8=0, int c9=0);
+ ///< \c true, if errorNumber() is one of \a c0 ... \a c9
virtual ~SystemException() throw();
+ protected:
+ SystemException(std::string const & where, int code);
+ SystemException(SystemException const & other);
+
private:
- void init();
- std::string buffer_;
+ int const code_; // This must be const to make the derived ErrnoException
+ // class a valid derived class.
+ mutable std::string buffer_;
+
+ friend void throwErrno(std::string const &, int);
+ };
+
+ /** \brief Error specific system exception
+
+ This template restricts the generic SystemException to a specific, compile-time constant
+ error number \p Code. This allows a specific \c errno number to be cached explicitly.
+
+ This exception is normally thrown via one of the senf::throwErrno() helpers. These helpers
+ take the numeric \c errno value (either from the \c errno variable or from their
+ argument) and will throw the corresponding ErrnoException:
+ \code
+ if ((fd = ::open(filename, O_RDWR)) < 0)
+ senf::throwErrno("open()");
+ \endcode
+
+ \see SystemException
+
+ \ingroup exception
+ */
+ template <int Code>
+ class ErrnoException : public SystemException
+ {
+ public:
+ static int const fixed_code = Code;
+
+ explicit ErrnoException(std::string const & where);
+ ///< ErrnoException with error location information
+
+ ErrnoException(ErrnoException const & other);
};
+
+ /** \brief Throw ErrnoException based on current \c errno value
+ \ingroup exception
+ */
+ void throwErrno();
+
+ /** \brief Throw ErrnoException based on current \c errno value (with location info)
+ \ingroup exception
+ */
+ void throwErrno(std::string const & where);
+
+ /** \brief Throw ErrnoException based on given \c errno value
+ \ingroup exception
+ */
+ void throwErrno(int code);
+
+ /** \brief Throw ErrnoException based on given \c errno value (with location info)
+ \ingroup exception
+ */
+ void throwErrno(std::string const & where, int code);
+
enum NoThrow_t { nothrow };
}
///////////////////////////////hh.e////////////////////////////////////////
#include "Exception.cci"
//#include "Exception.ct"
-//#include "Exception.cti"
+#include "Exception.cti"
#endif
\f