summaryrefslogtreecommitdiff
path: root/klm/util/exception.hh
diff options
context:
space:
mode:
Diffstat (limited to 'klm/util/exception.hh')
-rw-r--r--klm/util/exception.hh66
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__