|
Sierra Toolkit
Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* Copyright 2010 Sandia Corporation. */ 00003 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00004 /* license for use of this work by or on behalf of the U.S. Government. */ 00005 /* Export of this program may require a license from the */ 00006 /* United States Government. */ 00007 /*------------------------------------------------------------------------*/ 00008 00009 #ifndef STK_UTIL_ENVIRONMENT_REPORTHANDLER_HPP 00010 #define STK_UTIL_ENVIRONMENT_REPORTHANDLER_HPP 00011 00012 #include <iosfwd> 00013 #include <string> 00014 #include <sstream> 00015 00016 namespace stk_classic { 00017 00022 00028 typedef void (*REH)(const char *message, int type); 00029 00036 typedef void (*ErrorHandler)(const char* expr, const std::string& location, std::ostringstream& message); 00037 00050 void default_report_handler(const char *message, int type); 00051 00060 REH set_report_handler(REH reh); 00061 00071 void report(const char *message, int type); 00072 00082 std::string source_relative_path(const std::string &path); 00083 00088 void default_assert_handler(const char* expr, 00089 const std::string& location, 00090 std::ostringstream& message); 00091 00096 void default_error_handler(const char* expr, 00097 const std::string& location, 00098 std::ostringstream& message); 00099 00104 void default_invalid_arg_handler(const char* expr, 00105 const std::string& location, 00106 std::ostringstream& message); 00107 00113 ErrorHandler set_assert_handler(ErrorHandler handler); 00114 00120 ErrorHandler set_error_handler(ErrorHandler handler); 00121 00127 ErrorHandler set_invalid_arg_handler(ErrorHandler handler); 00128 00132 void handle_assert(const char* expr, 00133 const std::string& location, 00134 std::ostringstream& message); 00135 00139 void handle_error(const char* expr, 00140 const std::string& location, 00141 std::ostringstream& message); 00142 00146 void handle_invalid_arg(const char* expr, 00147 const std::string& location, 00148 std::ostringstream& message); 00149 00150 00154 00155 } // namespace stk_classic 00156 00161 00169 #define XSTR_TRACE_LINE(s) STR_TRACE_LINE(s) 00170 #define STR_TRACE_LINE(s) #s 00171 00172 #ifdef __PRETTY_FUNCTION__ 00173 00174 #define COUT_TRACE " Function::Line="<<__PRETTY_FUNCTION__<<":"<<__LINE__ 00175 #define STR_TRACE (std::string(__FILE__) + ":" + XSTR_TRACE_LINE(__LINE__) + " in " + std::string(__PRETTY_FUNCTION__)) 00176 00177 #else 00178 00179 #define COUT_TRACE " File::Line="<<__FILE__<<":"<<__LINE__ 00180 #define STR_TRACE (std::string(__FILE__) + ":" + XSTR_TRACE_LINE(__LINE__)) 00181 00182 #endif 00183 00184 #define StackTrace std::string(std::string(" exception thrown from ") + stk_classic::source_relative_path(STR_TRACE)) 00185 00186 // The do-while is necessary to prevent usage of this macro from changing 00187 // program semantics (e.g. dangling-else problem). The obvious implementation: 00188 // if (expr) ; else throw ... 00189 // is not adequate because it causes ambiguous else statements in this context: 00190 // if (something) 00191 // ThrowRequire(foo); 00192 // The compiler does not know whether the else statement that the macro inserts 00193 // applies to the "if (something) " or the "if (expr)". 00194 #define ThrowGenericCond(expr, message, handler) \ 00195 do { \ 00196 if ( !(expr) ) { \ 00197 std::ostringstream stk_util_internal_throw_require_oss; \ 00198 stk_util_internal_throw_require_oss << message; \ 00199 stk_classic::handler( #expr, \ 00200 STR_TRACE, \ 00201 stk_util_internal_throw_require_oss ); \ 00202 } \ 00203 } while (false) 00204 00205 // This generic macro is for unconditional throws. We pass "" as the expr 00206 // string, the handler should be smart enough to realize that this means there 00207 // was not expression checked, AKA, this throw was unconditional. 00208 #define ThrowGeneric(message, handler) \ 00209 do { \ 00210 std::ostringstream stk_util_internal_throw_require_oss; \ 00211 stk_util_internal_throw_require_oss << message; \ 00212 stk_classic::handler( "", \ 00213 STR_TRACE, \ 00214 stk_util_internal_throw_require_oss ); \ 00215 } while (false) 00216 00217 // The macros below define the exceptions that we want to support within 00218 // STK. The intent is that STK developers will never call throw XXX 00219 // directly. This will give us full control over the exceptions being generated 00220 // by STK and how they are handled. These macros are also designed to make 00221 // it as easy as possible for developers to throw exceptions that have good 00222 // error messages and to reduce the volume of coded needed for error handling. 00223 // 00224 // We currently support the following exceptions in STK: 00225 // logic_error <-> ThrowAssert, ThrowAsserMsg, ThrowRequire, ThrowRequireMsg 00226 // runtime_error <-> ThrowErrorMsgIf, ThrowErrorMsg 00227 // invalid_argument <-> ThrowInvalidArgMsgIf, ThrowInvalidArgIf 00228 // 00229 // Please note the logic of the errors is the opposite of the asserts. The 00230 // asserts will throw exceptions if the given expression is false; for the 00231 // error macros, exceptions will be thrown if the given expression is true. 00232 // 00233 // USE: 00234 // All of the following have versions that do not require a message, but 00235 // we strongly encourage developers to use the versions that take the 00236 // message. 00237 // 00238 // ASSERTS: 00239 // ThrowAssertMsg(expr, message); 00240 // If NDEBUG is not defined, throw a logic error if expr evaluates to 00241 // false, adding message to the error message . Use this for expensive 00242 // logic-mistake checks that could impact performance. 00243 // 00244 // ThrowRequireMsg(code, message); 00245 // Always throw a logic error if expr evaluates to false, adding message 00246 // to error message. Use this for inexpensive logic-mistake checks 00247 // that do not impact performance. 00248 // 00249 // ERRORS: 00250 // ThrowErrorMsgIf(expr, message); 00251 // Throw a runtime error if expr evaluates to true, adding message to 00252 // the error message. Use this to generate errors dealing with system 00253 // errors or other errors that do not involve invalid parameters being 00254 // passed to functions. 00255 // 00256 // ThrowInvalidArgMsgIf(expr, message); 00257 // Throw an invalid_argument error if expr evaluates to true, adding 00258 // message to the error message. Use this to generate errors dealing with 00259 // users passing invalid arguments to functions in the API. 00260 // 00261 // EXAMPLES: 00262 // 00263 // 1) Require that i equals j, demonstate use of put-tos in the message arg 00264 // ThrowRequireMsg(i == j, "i(" << i << ") != j(" << j << ")"); 00265 // 00266 // 2) Check method argument foo is not NULL 00267 // ThrowInvalidArgMsgIf(foo != NULL, "Arg foo is NULL"); 00268 00269 #define ThrowRequireMsg(expr,message) ThrowGenericCond(expr, message, handle_assert) 00270 #define ThrowRequire(expr) ThrowRequireMsg(expr, "") 00271 00272 #ifdef NDEBUG 00273 # define ThrowAssert(expr) ((void) (0)) 00274 # define ThrowAssertMsg(expr,message) ((void) (0)) 00275 #else 00276 # define ThrowAssert(expr) ThrowRequire(expr) 00277 # define ThrowAssertMsg(expr,message) ThrowRequireMsg(expr,message) 00278 #endif 00279 00280 #define ThrowErrorMsgIf(expr, message) ThrowGenericCond( !(expr), message, handle_error) 00281 #define ThrowErrorIf(expr) ThrowErrorMsgIf(expr, "") 00282 #define ThrowErrorMsg(message) ThrowGeneric( message, handle_error ) 00283 00284 #define ThrowInvalidArgMsgIf(expr, message) ThrowGenericCond( !(expr), message, handle_invalid_arg) 00285 #define ThrowInvalidArgIf(expr) ThrowInvalidArgMsgIf(expr, "") 00286 00290 00291 #endif // STK_UTIL_ENVIRONMENT_REPORTHANDLER_HPP