Logo Search packages:      
Sourcecode: tagcoll version File versions  Download package

Exception.h

Go to the documentation of this file.
#ifndef EXCEPTION_H
#define EXCEPTION_H

/** \file
 * Generic base exception hierarchy
 */

/**
 * Copyright (C) 2003,2004,2005  Enrico Zini <enrico@debian.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 */

#include <exception>
#include <string>
#include <tagcoll/stringf.h>

namespace Tagcoll {

/**
 * Basic unexpected handler
 *
 * This is an unexpected handler provided by the library.  It prints to stderr
 * a stack trace and all possible available informations about the escaped
 * exception.
 *
 * To have the function names in the stack trace, the executables need to be
 * linked using the -rdynamic flag.
 */
void DefaultUnexpected();

/**
 * Install an unexpected handler for the duration of its scope.  Install
 * DefaultUnexpected if no handler is provided.
 *
 * This is a RAII class: when it goes out of scope, the handler is removed.
 */
00050 class InstallUnexpected
{
protected:  
      void (*old)();
public:
      InstallUnexpected(void (*func)() = DefaultUnexpected);
      ~InstallUnexpected();
};

/**
 * Base class for all exceptions
 *
 * This is the root of the exception hierarchy.  The goal of this hierarchy is
 * to provide the most possible information on what caused the exception at the
 * least possible cost for the programmer.
 *
 * Every exception is the descendent of Exception that, in turn, extends the
 * std::exception class of the STL.
 *
 * The base class interface provides an interface to get a (hopefully detailed)
 * textual description of the exception, and a tag describing the type of
 * exception.  Further functionality will be provided by subclassers
 *
 * Further descendents of Exception add functionality and automatisms to error
 * message generation:
 *
 *  - ContextException extends Exception to provide informations on the context
 *    in which the exception was raised
 *  - ConsistencyCheckException extends ContextException to be a base class for
 *    all exception raised on failure of a consistency check;
 *    IndexOutOfRangeException is one example of such exceptions, to be used
 *    when checking that a value (such as an index) fails betweed two given
 *    bounds.
 *  - SystemException extends ContextException to carry informations about
 *    error conditions reported by external services, like the Operating
 *    System, a database interface or an interface used to communicate to some
 *    network server.  In particular, it provides the logic needed to make use
 *    of the error descriptions provided by the external services, as
 *    strerror(3) does for the operating system's error conditions.
 *    FileException is an example of such exceptions, to be used to report
 *    error conditions happened during File I/O.
 * 
 * Example exception raising:
 * \code
 *          void MyFile::open(const char* fname) throw (FileException)
 *          {
 *                if ((fd = open(fname, O_RDONLY)) == -1)
 *                      throw FileException(errno, stringf::fmt("opening %s read-only", fname));
 *          }
 * \endcode
 *
 * Example exception catching:
 * \code
 *      try {
 *                myfile.open("/tmp/foo");
 *          } catch (FileException& e) {
 *                fprintf(stderr, "%.*s: aborting.\n", PFSTR(e.toString()));
 *                exit(1);
 *          }
 * \endcode
 */
00111 class Exception : public std::exception
{
public:
      Exception() throw () {}
      virtual ~Exception() throw () {}

      /// Get a string tag identifying the exception type
00118       virtual const char* type() const throw () { return "Exception"; }

      /// Get a string describing what happened that threw the exception
00121       virtual std::string desc() const throw () { return type(); }

      /// Get a string describing what happened that threw the exception, STL style
00124       virtual const char* what() const throw () { return desc().c_str(); }
};

/// Exception with a description of the throwing context
00128 class ContextException : public Exception
{
protected:
      std::string _context;

public:
      /** Construct the ContextException, providing the context description in
       * printf syntax.  The context should be phrased like "Bad thing A
       * happened when doing B"
       */
00138       ContextException(const std::string& context) throw () : _context(context) {};
      ~ContextException() throw () {}

00141       virtual const char* type() const throw () { return "ContextException"; }

00143       virtual std::string desc() const throw () { return _context; }

      virtual std::string context() const throw () { return _context; }
};

/**
 * Exception thrown when some long event is interrupted by an external event
 * (like a system call being interrupted by a signal)
 * 
 * It is a direct child of ContextException, and has the very same semantics.
 *
 * \warning Any function throwing InterruptedException must allow to be called
 * again with the same parameters to retry the operation
 */
00157 class InterruptedException : public ContextException
{
public:
      InterruptedException(const std::string& context) throw () :
            ContextException(context) {}

00163       virtual const char* type() const throw ()
      {
            return "InterruptedException";
      }
};

/**
 * Exception thrown when some system wait is interrupted by a signal
 *
 * It is a direct child of InterruptedException, and has the very same
 * semantics.
 *
 * \warning Any function throwing WaitInterruptedException must allow to be
 * called again with the same parameters to retry the operation
 */
00178 class WaitInterruptedException : public InterruptedException
{
public:
      WaitInterruptedException(const std::string& context) throw () :
            InterruptedException(context) {}

00184       virtual const char* type() const throw ()
      {
            return "WaitInterruptedException";
      }
};

/**
 * Exception thrown when some consistency check fails
 *
 * It is a direct child of ContextException, and has the very same semantics.
 */
00195 class ConsistencyCheckException : public ContextException
{
public:
      ConsistencyCheckException(const std::string& context) throw () :
            ContextException(context) {}

00201       virtual const char* type() const throw ()
      {
            return "ConsistencyCheckException";
      }
};

class OutOfRangeException : public ConsistencyCheckException
{
protected:
      std::string _var_desc;

public:
      OutOfRangeException(const std::string& context, const std::string& var_desc) throw ()
            : ConsistencyCheckException(context), _var_desc(var_desc) {}
      ~OutOfRangeException() throw () {}

      virtual const char* type() const throw ()
      {
            return "ConsistencyCheckException";
      }

      /// Get a short description of the variable that has been checked
      virtual std::string var_desc() const throw () { return _var_desc; }

      virtual std::string desc() const throw ()
      {
            return _var_desc + " out of range " + _context;
      }
};

/**
 * Exception thrown when index checking fails
 *
 * This exception is to be thrown when an index checking fails, providing
 * informations on the acceptable index range and on the offending value.
 * The context should be a description of the index, possibly preceeded by a
 * description of in what context did the index checking happen.
 * 
 * Example:
 * \code
 *  if (age < 18)
 *     throw IndexOutOfRangeException(age, 18, 0,
 *                                              "obtaining driver license, age");
 *
 *  if (i < 0 || i > 100)
 *    throw IndexOutOfRangeException(i, 0, 100, "percentage of items sold");
 * \endcode
 */
template <class C>
00250 class ValOutOfRangeException : public OutOfRangeException
{
protected:
      C _val;
      C _inf;
      C _sup;

public:
      /** Construct the exception; minBound and maxBound are the bounds of the
       * valid index range (inclusive).
       */
00261       ValOutOfRangeException(const std::string& context, const std::string& var_desc,
                                    C val, C inf, C sup) throw ()
                              : OutOfRangeException(context, var_desc),
                                    _val(val), _inf(inf), _sup(sup) {}
      
      ///@name Methods used to get informations about the index and its bounds
      //@{
      /// Get the value that caused the index to go out-of-bounds
00269       virtual C val() const throw () { return _val; }
      /// Get the minimum allowed value for this index
00271       virtual C inf() const throw () { return _inf; }
      /// Get the maximum allowed value for this index
00273       virtual C sup() const throw () { return _sup; }
      //@}

00276       virtual const char* type() const throw ()
      {
            return "ValOutOfRangeException<>";
      }

00281       virtual std::string desc() const throw ()
      {
            return _var_desc + "(" + stringf::fmt(_val) + ") out of range (" +
                        stringf::fmt(_inf) + "-" + stringf::fmt(_sup) + ") " + _context;
      }
};

/**
 * Base class for system exceptions
 *
 * This is the base class for exceptions that depend on system events, like
 * exceptions on file or network I/O, on database access and so on.
 * SystemExceptions introduces the keeping of an error code with an associated
 * string description, and by defaults provides the textual description for
 * Unix errno error codes.
 * The exception context should be phrased like "doing X".
 *
 * Example:
 * \code
 *          const char* fname = "foo.bar";
 *          if ((fd = open(fname, O_RDONLY)) == -1)
 *                // Should not throw SystemException, but a more specialized derived
 *                // class like FileException
 *                throw SystemException(errno, stringf::fmt("opening %s read-only", fname));
 * \endcode
 */
00307 class SystemException : public ContextException
{
protected:
      int _code;

public:
      SystemException(int code, const std::string& context) throw () :
            ContextException(context), _code(code) {}

00316       virtual const char* type() const throw () { return "SystemException"; }

      /// Get the system error code associated to the exception
00319       virtual int code() const throw () { return _code; }

      /// Get the description of the error code
      virtual std::string system_desc() const throw ();

00324       virtual std::string desc() const throw ()
      {
            return system_desc() + " " + _context;
      }
};

/**
 * Base class for exceptions for file I/O
 *
 * It is a direct child of SystemException, and has the very same semantics.
 * Like in SystemException, the error code description provided is a
 * description for errno values.
 */
00337 class FileException : public SystemException
{
public:
      FileException(int code, const std::string& context)   throw () :
            SystemException(code, context) {}

00343       virtual const char* type() const throw () { return "FileException"; }
};

};

// vim:set ts=4 sw=4:
#endif

Generated by  Doxygen 1.6.0   Back to index