00001 #ifndef COMMONS_CHECK_H
00002 #define COMMONS_CHECK_H
00003
00004 #include <exception>
00005 #include <sstream>
00006 #include <string>
00007 #include <commons/die.h>
00008 #include <boost/lexical_cast.hpp>
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 namespace commons
00029 {
00030
00031 enum { buflen = 4096 };
00032
00033
00034
00035
00036
00037 using namespace boost;
00038 using namespace std;
00039
00040 class check_exception : public std::exception
00041 {
00042 public:
00043 check_exception(const string & name) : name(name) {}
00044 virtual ~check_exception() throw() {}
00045 virtual const char *what() const throw() { return name.c_str(); }
00046 private:
00047 const string name;
00048 };
00049
00050 __attribute__((format(printf, 4, 0))) inline void
00051 _vcheck(bool cond, const char *file, int line, const char *fmt, va_list ap)
00052 {
00053 if (!cond) {
00054 stringstream ss;
00055 ss << "failed check in " << file << ':' << line << ": ";
00056 if (fmt != NULL) {
00057 char buf[buflen];
00058 vsnprintf(buf, buflen, fmt, ap);
00059 ss << buf;
00060 }
00061 throw check_exception(ss.str());
00062 }
00063 }
00064
00065 __attribute__((format(printf, 4, 5))) void
00066 _check(bool cond, const char *file, int line, const char *fmt, ...)
00067 {
00068 va_list ap;
00069 va_start(ap, fmt);
00070 _vcheck(cond, file, line, fmt, ap);
00071 va_end(ap);
00072 }
00073
00074 inline void
00075 _check(bool cond, const char *file, int line)
00076 {
00077 _check(cond, file, line, NULL);
00078 }
00079
00080 template<typename T> inline T
00081 _checkpass(T x, const char *file, int line)
00082 {
00083 _check(x, file, line);
00084 return x;
00085 }
00086
00087 template<typename T> inline T
00088 _checknneg(T x, const char *file, int line)
00089 {
00090 if (x < 0) {
00091 stringstream ss;
00092 ss << "expecting non-negative, got " << x;
00093 _check(false, file, line, "%s", ss.str().c_str());
00094 }
00095 return x;
00096 }
00097
00098 template<typename T> inline T
00099 _checknnegerr(T x, const char *file, int line)
00100 {
00101 if (x < 0) {
00102 int e = errno;
00103 errno = 0;
00104 stringstream ss;
00105 ss << "expecting >=0, got " << x << ": " << strerror(e);
00106 _check(false, file, line, "%s", ss.str().c_str());
00107 }
00108 return x;
00109 }
00110
00111 template<typename T> inline T
00112 _checkerr(T x, const char *file, int line)
00113 {
00114 if (!x) {
00115 int e = errno;
00116 errno = 0;
00117 stringstream ss;
00118 ss << "expecting !=0, got " << x << ": " << strerror(e);
00119 _check(false, file, line, "%s", ss.str().c_str());
00120 }
00121 return x;
00122 }
00123
00124 template<typename T> inline void
00125 _check0(T x, const char *file, int line)
00126 {
00127
00128
00129 if (errno == 0) {
00130 _check(x == 0, file, line, "expecting 0, got %d", x);
00131 } else {
00132 int e = errno;
00133 errno = 0;
00134 _check(x == 0, file, line, "expecting 0, got %d: %s", x,
00135 strerror(e));
00136 }
00137 }
00138
00139 template<typename T, typename U> inline void
00140 _checkeq(T l, U r, const char *file, int line)
00141 {
00142 if (l != r) {
00143 stringstream ss;
00144 ss << "expecting " << l << " == " << r;
00145 _check(false, file, line, "%s", ss.str().c_str());
00146 }
00147 }
00148
00149 template<typename T, typename U> inline void
00150 _checkeqnneg(T l, U r, const char *file, int line)
00151 {
00152 if (l < 0) {
00153 int e = errno;
00154 errno = 0;
00155 stringstream ss;
00156 ss << "expecting " << r << ", got " << l << ": " << strerror(e);
00157 _check(l == r, file, line, "%s", ss.str().c_str());
00158 } else {
00159 _checkeq(l, r, file, line);
00160 }
00161 }
00162
00163 }
00164
00171 #define check(cond, msg...) _check(cond, __FILE__, __LINE__, ## msg)
00172
00180 #define checkpass(expr, msg...) _checkpass(expr, __FILE__, __LINE__, ## msg)
00181
00185 #define checkerr(expr) _checkerr(expr, __FILE__, __LINE__)
00186
00190 #define checknneg(expr, msg...) _checknneg(expr, __FILE__, __LINE__, ## msg)
00191
00195 #define checknnegerr(expr) _checknnegerr(expr, __FILE__, __LINE__)
00196
00202 #define check0x(expr, msg...) _check0(expr, __FILE__, __LINE__, ## msg)
00203
00208 #define checkeq(l, r, msg...) _checkeq(l, r, __FILE__, __LINE__, ## msg)
00209
00214 #define checkeqnneg(l, r, msg...) \
00215 _checkeqnneg(l, r, __FILE__, __LINE__, ## msg)
00216
00217 #if 0
00218 #define checkmsg(cond, msg) \
00219 bool b__ = cond; \
00220 if (!b__) _check(b__, (msg), __FILE__, __LINE__)
00221
00222 #define checkmsgf(cond, msg...) \
00223 do { \
00224 bool b__ = cond; \
00225 if (!b__) { \
00226 char s__[4096]; \
00227 snprintf(s, msg); \
00228 _check(b__, s__, __FILE__, __LINE__); \
00229 } \
00230 } while (0)
00231 #endif
00232
00237 #define check0(expr) \
00238 do { \
00239 typeof(expr) r__ = expr; \
00240 if (r__) { \
00241 return r__; \
00242 } \
00243 } while (0)
00244
00248 #define checkdie(expr, msg...) \
00249 do { \
00250 if (!expr) { \
00251 die(msg); \
00252 } \
00253 } while (0)
00254
00255 #endif
00256