|
#ifndef UTIL_EXCEPTION_H |
|
#define UTIL_EXCEPTION_H |
|
|
|
#include "string_stream.hh" |
|
|
|
#include <exception> |
|
#include <limits> |
|
#include <string> |
|
#include <stdint.h> |
|
|
|
namespace util { |
|
|
|
template <class Except, class Data> typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data); |
|
|
|
class Exception : public std::exception { |
|
public: |
|
Exception() throw(); |
|
virtual ~Exception() throw(); |
|
|
|
const char *what() const throw() { return what_.str().c_str(); } |
|
|
|
|
|
void SetLocation( |
|
const char *file, |
|
unsigned int line, |
|
const char *func, |
|
const char *child_name, |
|
const char *condition); |
|
|
|
private: |
|
template <class Except, class Data> friend typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data); |
|
|
|
|
|
template <class T> struct ExceptionTag { |
|
typedef T Identity; |
|
}; |
|
|
|
StringStream what_; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
template <class Except, class Data> typename Except::template ExceptionTag<Except&>::Identity operator<<(Except &e, const Data &data) { |
|
e.what_ << data; |
|
return e; |
|
} |
|
|
|
#ifdef __GNUC__ |
|
#define UTIL_FUNC_NAME __PRETTY_FUNCTION__ |
|
#else |
|
#ifdef _WIN32 |
|
#define UTIL_FUNC_NAME __FUNCTION__ |
|
#else |
|
#define UTIL_FUNC_NAME NULL |
|
#endif |
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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_ARG(Exception, Arg, Modify) \ |
|
UTIL_THROW_BACKEND(NULL, Exception, Arg, Modify) |
|
|
|
#define UTIL_THROW(Exception, Modify) \ |
|
UTIL_THROW_BACKEND(NULL, Exception, , Modify); |
|
|
|
#define UTIL_THROW2(Modify) \ |
|
UTIL_THROW_BACKEND(NULL, util::Exception, , Modify); |
|
|
|
#if __GNUC__ >= 3 |
|
#define UTIL_UNLIKELY(x) __builtin_expect (!!(x), 0) |
|
#else |
|
#define UTIL_UNLIKELY(x) (x) |
|
#endif |
|
|
|
#if __GNUC__ >= 3 |
|
#define UTIL_LIKELY(x) __builtin_expect (!!(x), 1) |
|
#else |
|
#define UTIL_LIKELY(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) |
|
|
|
#define UTIL_THROW_IF2(Condition, Modify) \ |
|
UTIL_THROW_IF_ARG(Condition, util::Exception, , Modify) |
|
|
|
|
|
class ErrnoException : public Exception { |
|
public: |
|
ErrnoException() throw(); |
|
|
|
virtual ~ErrnoException() throw(); |
|
|
|
int Error() const throw() { return errno_; } |
|
|
|
private: |
|
int errno_; |
|
}; |
|
|
|
|
|
class FileOpenException : public Exception { |
|
public: |
|
FileOpenException() throw() {} |
|
~FileOpenException() throw() {} |
|
}; |
|
|
|
|
|
class OverflowException : public Exception { |
|
public: |
|
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 static_cast<std::size_t>(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); |
|
} |
|
|
|
#if defined(_WIN32) || defined(_WIN64) |
|
|
|
class WindowsException : public Exception { |
|
public: |
|
WindowsException() throw(); |
|
~WindowsException() throw(); |
|
}; |
|
#endif |
|
|
|
} |
|
|
|
#endif |
|
|