[Assorted-commits] SF.net SVN: assorted: [741] cpp-commons/trunk/src/commons/check.h
Brought to you by:
yangzhang
From: <yan...@us...> - 2008-05-08 19:25:06
|
Revision: 741 http://assorted.svn.sourceforge.net/assorted/?rev=741&view=rev Author: yangzhang Date: 2008-05-08 12:24:40 -0700 (Thu, 08 May 2008) Log Message: ----------- added checkdie; reformatting; sprinkled documentation; added some todos; added more functions to back the macros Modified Paths: -------------- cpp-commons/trunk/src/commons/check.h Modified: cpp-commons/trunk/src/commons/check.h =================================================================== --- cpp-commons/trunk/src/commons/check.h 2008-05-08 19:22:53 UTC (rev 740) +++ cpp-commons/trunk/src/commons/check.h 2008-05-08 19:24:40 UTC (rev 741) @@ -1,13 +1,20 @@ #ifndef COMMONS_CHECK_H #define COMMONS_CHECK_H +#define buflen 4096 + #include <exception> #include <sstream> #include <string> +#include <commons/die.h> namespace commons { + // TODO: deal with va args + // TODO: provide strerror in other functions too + // TODO: better way to deal with errno? (rather than resetting it) + using namespace std; class check_exception : public exception @@ -15,54 +22,155 @@ public: check_exception(const string & name) : name(name) {} virtual ~check_exception() throw() {} + const char *what() const throw() { return name.c_str(); } private: const string name; }; inline void - _check(bool cond, const char *msg, const char *file, int line) + _vcheck(bool cond, const char *file, int line, const char *fmt, va_list ap) { if (!cond) { stringstream ss; - ss << file << ':' << line << ": "; - if (msg != NULL) ss << msg; + ss << "failed check in " << file << ':' << line << ": "; + if (fmt != NULL) { + char buf[buflen]; + vsnprintf(buf, buflen, fmt, ap); + ss << buf; + } ss << endl; throw check_exception(ss.str()); } } + inline void + _check(bool cond, const char *file, int line, const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + _vcheck(cond, file, line, fmt, ap); + va_end(ap); + } + + inline void + _check(bool cond, const char *file, int line) + { + _check(cond, file, line, NULL); + } + + template<typename T> inline T + _checkpass(T x, const char *file, int line) + { + _check(x, file, line); + return x; + } + + template<typename T> inline T + _checknneg(T x, const char *file, int line) + { + _check(x >= 0, file, line, "expecting non-negative, got %d", x); + return x; + } + + template<typename T> inline void + _check0(T x, const char *file, int line) + { + // Valid error numbers are all non-zero; errno is never set to zero by any + // library function. We reset errno here. + if (errno == 0) { + _check(x == 0, file, line, "expecting 0, got %d", x); + } else { + int e = errno; + errno = 0; + _check(x == 0, file, line, "expecting 0, got %d: %s", x, + strerror(e)); + } + } + + template<typename T, typename U> inline void + _checkeq(T l, U r, const char *file, int line) + { + if (l != r) { + stringstream ss; + ss << "expecting " << l << " == " << r; + _check(false, file, line, ss.str().c_str()); + } + } + } -#define check(cond) _check(cond, NULL, __FILE__, __LINE__) +/** + * Similar to assert(), but is not conditionally compiled, so this is safe to + * use as a guard against expected failures (such as checking return codes). + * This is a macro for two reasons: (1) the file and line, and (2) the lazy + * evaluation of msg. + */ +#define check(cond, msg...) _check(cond, __FILE__, __LINE__, ## msg) - /** - * Similar to assert(), but is not conditionally compiled, so this is safe to - * use as a guard against expected failures (such as checking return codes). - * This is a macro for two reasons: (1) the file and line, and (2) the lazy - * evaluation of msg. - */ -#define checkmsg(cond, msg) \ - bool b__ = cond; \ +/** + * Same as check(), but additionally returns the value that was passed in. The + * value is passed by copy, and not reference, since this function is + * frequently wrapped around a call to another function (to check that its + * return value is non-zero or not false). This is suitable for small, + * copyable pieces of data, such as integers, file descriptors, pointers, etc. + */ +#define checkpass(expr, msg...) _checkpass(expr, __FILE__, __LINE__, ## msg) + +/** + * Checks that the value is non-negative. + */ +#define checknneg(expr, msg...) _checknneg(expr, __FILE__, __LINE__, ## msg) + +/** + * Checks that the value is 0. Same as check0(), but throws an error rather + * than return. Also clears the errno on error. The resulting exception + * includes the strerror(). + */ +#define check0x(expr, msg...) _check0(expr, __FILE__, __LINE__, ## msg) + +/** + * Checks that the values are equal. The exception will include both values, + * as formatted by ostream <<. + */ +#define checkeq(l, r, msg...) _checkeq(l, r, __FILE__, __LINE__, ## msg) + +#if 0 +#define checkmsg(cond, msg) \ + bool b__ = cond; \ if (!b__) _check(b__, (msg), __FILE__, __LINE__) -// TODO: half-written -#define checkmsgf(cond, msg, ...) \ - do { \ - bool b__ = cond; \ - if (!b__) { \ - char s__[4096]; \ - snprintf(s, ); \ - _check(b__, s__, __FILE__, __LINE__); \ - } \ +#define checkmsgf(cond, msg...) \ + do { \ + bool b__ = cond; \ + if (!b__) { \ + char s__[4096]; \ + snprintf(s, msg); \ + _check(b__, s__, __FILE__, __LINE__); \ + } \ } while (0) +#endif -#define check0(expr) \ - do { \ - typeof(expr) r__ = expr; \ - if (r__ != 0) { \ - return r__; \ - } \ +/** + * Checks that the value is 0, otherwise returns the value (representing an + * error). + */ +#define check0(expr) \ + do { \ + typeof(expr) r__ = expr; \ + if (r__) { \ + return r__; \ + } \ } while (0) +/** + * Checks that the value is true or non-zero, otherwise dies (calls die()). + */ +#define checkdie(expr, msg...) \ + do { \ + if (!expr) { \ + die(msg); \ + } \ + } while (0) + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |