diff options
Diffstat (limited to 'klm/util/exception.hh')
-rw-r--r-- | klm/util/exception.hh | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/klm/util/exception.hh b/klm/util/exception.hh index 6d6a37cb..74046cf9 100644 --- a/klm/util/exception.hh +++ b/klm/util/exception.hh @@ -2,9 +2,12 @@ #define UTIL_EXCEPTION__ #include <exception> +#include <limits> #include <sstream> #include <string> +#include <stdint.h> + namespace util { template <class Except, class Data> typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data); @@ -41,7 +44,7 @@ class Exception : public std::exception { }; /* This implements the normal operator<< for Exception and all its children. - * SNIFAE means it only applies to Exception. Think of this as an ersatz + * SFINAE means it only applies to Exception. Think of this as an ersatz * boost::enable_if. */ template <class Except, class Data> typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data) { @@ -59,40 +62,43 @@ template <class Except, class Data> typename Except::template ExceptionTag<Excep #endif #endif -#define UTIL_SET_LOCATION(UTIL_e, child, condition) do { \ - (UTIL_e).SetLocation(__FILE__, __LINE__, UTIL_FUNC_NAME, (child), (condition)); \ -} while (0) - /* Create an instance of Exception, add the message Modify, and throw it. * Modify is appended to the what() message and can contain << for ostream * operations. * * do .. while kludge to swallow trailing ; character * http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html . + * Arg can be a constructor argument to the exception. */ -#define UTIL_THROW(Exception, Modify) do { \ - Exception UTIL_e; \ - UTIL_SET_LOCATION(UTIL_e, #Exception, NULL); \ +#define UTIL_THROW_BACKEND(Condition, Exception, Arg, Modify) do { \ + Exception UTIL_e Arg; \ + UTIL_e.SetLocation(__FILE__, __LINE__, UTIL_FUNC_NAME, #Exception, Condition); \ UTIL_e << Modify; \ throw UTIL_e; \ } while (0) -#define UTIL_THROW_VAR(Var, Modify) do { \ - Exception &UTIL_e = (Var); \ - UTIL_SET_LOCATION(UTIL_e, NULL, NULL); \ - UTIL_e << Modify; \ - throw UTIL_e; \ -} while (0) +#define UTIL_THROW_ARG(Exception, Arg, Modify) \ + UTIL_THROW_BACKEND(NULL, Exception, Arg, Modify) + +#define UTIL_THROW(Exception, Modify) \ + UTIL_THROW_BACKEND(NULL, Exception, , Modify); -#define UTIL_THROW_IF(Condition, Exception, Modify) do { \ - if (Condition) { \ - Exception UTIL_e; \ - UTIL_SET_LOCATION(UTIL_e, #Exception, #Condition); \ - UTIL_e << Modify; \ - throw UTIL_e; \ +#if __GNUC__ >= 3 +#define UTIL_UNLIKELY(x) __builtin_expect (!!(x), 0) +#else +#define UTIL_UNLIKELY(x) (x) +#endif + +#define UTIL_THROW_IF_ARG(Condition, Exception, Arg, Modify) do { \ + if (UTIL_UNLIKELY(Condition)) { \ + UTIL_THROW_BACKEND(#Condition, Exception, Arg, Modify); \ } \ } while (0) +#define UTIL_THROW_IF(Condition, Exception, Modify) \ + UTIL_THROW_IF_ARG(Condition, Exception, , Modify) + +// Exception that records errno and adds it to the message. class ErrnoException : public Exception { public: ErrnoException() throw(); @@ -105,12 +111,26 @@ class ErrnoException : public Exception { int errno_; }; -class EndOfFileException : public Exception { +// Utilities for overflow checking. +class OverflowException : public Exception { public: - EndOfFileException() throw(); - ~EndOfFileException() throw(); + OverflowException() throw(); + ~OverflowException() throw(); }; +template <unsigned len> inline std::size_t CheckOverflowInternal(uint64_t value) { + UTIL_THROW_IF(value > static_cast<uint64_t>(std::numeric_limits<std::size_t>::max()), OverflowException, "Integer overflow detected. This model is too big for 32-bit code."); + return value; +} + +template <> inline std::size_t CheckOverflowInternal<8>(uint64_t value) { + return value; +} + +inline std::size_t CheckOverflow(uint64_t value) { + return CheckOverflowInternal<sizeof(std::size_t)>(value); +} + } // namespace util #endif // UTIL_EXCEPTION__ |