00001 #ifndef UTIL_EXCEPTION_H
00002 #define UTIL_EXCEPTION_H
00003
00004 #include "util/string_stream.hh"
00005
00006 #include <exception>
00007 #include <limits>
00008 #include <string>
00009 #include <stdint.h>
00010
00011
00012 #include <sstream>
00013
00014 namespace util {
00015
00016 template <class Except, class Data> typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data);
00017
00018 class Exception : public std::exception {
00019 public:
00020 Exception() throw();
00021 virtual ~Exception() throw();
00022
00023 const char *what() const throw() { return what_.str().c_str(); }
00024
00025
00026 void SetLocation(
00027 const char *file,
00028 unsigned int line,
00029 const char *func,
00030 const char *child_name,
00031 const char *condition);
00032
00033 private:
00034 template <class Except, class Data> friend typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data);
00035
00036
00037 template <class T> struct ExceptionTag {
00038 typedef T Identity;
00039 };
00040
00041 StringStream what_;
00042 };
00043
00044
00045
00046
00047
00048 template <class Except, class Data> typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data) {
00049
00050 std::stringstream moses_hack;
00051 moses_hack << data;
00052 e.what_ << moses_hack.str();
00053 return e;
00054 }
00055
00056 #ifdef __GNUC__
00057 #define UTIL_FUNC_NAME __PRETTY_FUNCTION__
00058 #else
00059 #ifdef _WIN32
00060 #define UTIL_FUNC_NAME __FUNCTION__
00061 #else
00062 #define UTIL_FUNC_NAME NULL
00063 #endif
00064 #endif
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #define UTIL_THROW_BACKEND(Condition, Exception, Arg, Modify) do { \
00075 Exception UTIL_e Arg; \
00076 UTIL_e.SetLocation(__FILE__, __LINE__, UTIL_FUNC_NAME, #Exception, Condition); \
00077 UTIL_e << Modify; \
00078 throw UTIL_e; \
00079 } while (0)
00080
00081 #define UTIL_THROW_ARG(Exception, Arg, Modify) \
00082 UTIL_THROW_BACKEND(NULL, Exception, Arg, Modify)
00083
00084 #define UTIL_THROW(Exception, Modify) \
00085 UTIL_THROW_BACKEND(NULL, Exception, , Modify);
00086
00087 #define UTIL_THROW2(Modify) \
00088 UTIL_THROW_BACKEND(NULL, util::Exception, , Modify);
00089
00090 #if __GNUC__ >= 3
00091 #define UTIL_UNLIKELY(x) __builtin_expect (!!(x), 0)
00092 #else
00093 #define UTIL_UNLIKELY(x) (x)
00094 #endif
00095
00096 #if __GNUC__ >= 3
00097 #define UTIL_LIKELY(x) __builtin_expect (!!(x), 1)
00098 #else
00099 #define UTIL_LIKELY(x) (x)
00100 #endif
00101
00102 #define UTIL_THROW_IF_ARG(Condition, Exception, Arg, Modify) do { \
00103 if (UTIL_UNLIKELY(Condition)) { \
00104 UTIL_THROW_BACKEND(#Condition, Exception, Arg, Modify); \
00105 } \
00106 } while (0)
00107
00108 #define UTIL_THROW_IF(Condition, Exception, Modify) \
00109 UTIL_THROW_IF_ARG(Condition, Exception, , Modify)
00110
00111 #define UTIL_THROW_IF2(Condition, Modify) \
00112 UTIL_THROW_IF_ARG(Condition, util::Exception, , Modify)
00113
00114
00115 class ErrnoException : public Exception {
00116 public:
00117 ErrnoException() throw();
00118
00119 virtual ~ErrnoException() throw();
00120
00121 int Error() const throw() { return errno_; }
00122
00123 private:
00124 int errno_;
00125 };
00126
00127
00128 class FileOpenException : public Exception {
00129 public:
00130 FileOpenException() throw() {}
00131 ~FileOpenException() throw() {}
00132 };
00133
00134
00135 class OverflowException : public Exception {
00136 public:
00137 OverflowException() throw();
00138 ~OverflowException() throw();
00139 };
00140
00141 template <unsigned len> inline std::size_t CheckOverflowInternal(uint64_t value) {
00142 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.");
00143 return value;
00144 }
00145
00146 template <> inline std::size_t CheckOverflowInternal<8>(uint64_t value) {
00147 return value;
00148 }
00149
00150 inline std::size_t CheckOverflow(uint64_t value) {
00151 return CheckOverflowInternal<sizeof(std::size_t)>(value);
00152 }
00153
00154 #if defined(_WIN32) || defined(_WIN64)
00155
00156 class WindowsException : public Exception {
00157 public:
00158 WindowsException() throw();
00159 ~WindowsException() throw();
00160 };
00161 #endif
00162
00163 }
00164
00165 #endif // UTIL_EXCEPTION_H