Sierra Toolkit Version of the Day
ReportHandler.hpp
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 {
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
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::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::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::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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines