1 /* ***************************************************************** 2 MESQUITE -- The Mesh Quality Improvement Toolkit 3 4 Copyright 2004 Sandia Corporation and Argonne National 5 Laboratory. Under the terms of Contract DE-AC04-94AL85000 6 with Sandia Corporation, the U.S. Government retains certain 7 rights in this software. 8 9 This library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Lesser General Public 11 License as published by the Free Software Foundation; either 12 version 2.1 of the License, or (at your option) any later version. 13 14 This library is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public License 20 (lgpl.txt) along with this library; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 23 ***************************************************************** */ 24 25 #ifndef MSQ_ERROR_HPP 26 #define MSQ_ERROR_HPP 27 28 #include "Mesquite.hpp" 29 30 #include <iosfwd> 31 #include <list> 32 #include <string> 33 34 namespace MBMesquite 35 { 36 37 /**\defgroup error Mesquite internal error handling 38 */ 39 /*@{*/ 40 41 #ifndef MSQ_FUNCTION 42 # define MSQ_FUNCTION "" 43 #endif 44 45 46 /**\brief Mesquite's Error Checking macro. 47 * 48 * Check the status of an MsqError. Returns true as pushes the current 49 * file/line onto the stack trace if the error flag is true. Returns 50 * false otherwise. 51 */ 52 #define MSQ_CHKERR(err) (err.error() && err.push(MSQ_FUNCTION,__FILE__,__LINE__)) 53 54 /**\brief If passed error is true, return from a void function. 55 * 56 * Shorthand for if (MSQ_CHKERR(err)) return 57 */ 58 #define MSQ_ERRRTN(err) if (MSQ_CHKERR(err)) return 59 60 /**\brief Return zero/NULL on error. 61 */ 62 #define MSQ_ERRZERO(err) if (MSQ_CHKERR(err)) return 0 63 64 /**\brief Return false on error. 65 */ 66 #define MSQ_ERRFALSE(err) if (MSQ_CHKERR(err)) return false 67 68 /**\brief Macro to set error - use err.clear() to clear. 69 * 70 * Set the error object to the specified error code and optional error message, 71 * and push the current file/line onto the stack trace. 72 * Examples: 73 * - MSQ_SETERR( err )( MsqError::INVALID_ARG ); 74 * - MSQ_SETERR( err )( "foo cannot be zero", MsqError::INVALID_ARG ); 75 * - MSQ_SETERR( err )( MsqError::INVALID_ARG, "foo = %d", foo ); 76 */ 77 #define MSQ_SETERR(err) \ 78 MBMesquite::MsqError::setter(err, MSQ_FUNCTION,__FILE__,__LINE__).set 79 80 /** 81 *\class MsqError 82 *\brief Used to hold the error state and return it to the application. 83 *\author Jason Kraftcheck 84 *\date 2004-09-17 85 * 86 * Used to hold error state and related information. 87 * Internal Mesquite code should access this object via 88 * the MSQ_SETERR() and MSQ_CHKERR() macros. 89 * 90 * For applications, the cast-to-bool operator and << operator 91 * are provided for convenient, if simple access to this data. 92 * E.g.: if (err) cout << err << endl; 93 * 94 * There are two options for an application to gain more detailed 95 * access to the error data. The application may either access 96 * the data stored in this class via the provided methods or 97 * subclass MsqError, overriding set_error() and push() 98 * to handle the error data as it is generated. 99 */ 100 class MsqError { 101 public: 102 103 /* NOTE: If you add an error to this list, make sure 104 a) you add it *before* LAST_ERROR_CODE 105 b) you add the corresponding string in MsqError.cpp 106 */ 107 /** \brief Error codes 108 */ 109 enum ErrorCode { 110 NO_ERROR = 0,/**< no error */ 111 UNKNOWN_ERROR, /**< unknown error occured */ 112 OUT_OF_MEMORY, /**< unable to allocate the necessary memory */ 113 INVALID_ARG , /**< invalid function argument passed */ 114 NOT_INITIALIZED, /**< object not initialized */ 115 INVALID_STATE, /**< object is in an invalid state */ 116 FILE_ACCESS, /**< File cannot be opened/created. */ 117 FILE_FORMAT, /**< Wrong file type */ 118 PARSE_ERROR, /**< Error parsing input (or input file) */ 119 IO_ERROR, /**< An I/O error occured (e.g. read from file failed.) */ 120 INVALID_MESH, /**< The mesh is invalid */ 121 NO_PD_STORAGE_MODE, /**< no storage mode chosen within PatchData */ 122 NOT_IMPLEMENTED, /**< requested functionality is not (yet) implemented */ 123 INTERNAL_ERROR, /**< A bug in Mesquite */ 124 INTERRUPTED, /**< Application or user interrupted operation */ 125 TAG_ALREADY_EXISTS, /**< Attempt to create tag that already exists */ 126 TAG_NOT_FOUND, /**< Specified tag does not exist */ 127 UNSUPPORTED_ELEMENT, /**< the element type is not supported. */ 128 PARALLEL_ERROR, /**< an error occurred in parallel > */ 129 BARRIER_VIOLATED, /**< barruer violated when processing barrier Target Metric */ 130 LAST_ERROR_CODE 131 }; 132 133 //! \brief resets error object to non-active state (no error). 134 MESQUITE_EXPORT void clear(); 135 136 //! \brief Check if an error has occured error() const137 inline bool error() const { return NO_ERROR != errorCode; } 138 //! \brief Check if an error has occured operator bool() const139 inline operator bool() const { return NO_ERROR != errorCode; } 140 141 //! \brief Initialize to cleared state. MsqError()142 MESQUITE_EXPORT MsqError() : errorCode(NO_ERROR) { } 143 144 //! Destructor - empty but must declar virtual destrucor if virtual functions. 145 MESQUITE_EXPORT virtual ~MsqError(); 146 147 /* ************************************************************ * 148 * Low-level access to error data 149 * ************************************************************ */ 150 151 //! Get error code error_code() const152 inline ErrorCode error_code() const { return errorCode; } 153 154 //!\class Trace 155 //!\brief One line of stack trace data 156 struct MESQUITE_EXPORT Trace { 157 std::string function; 158 std::string file; 159 int line; 160 TraceMBMesquite::MsqError::Trace161 Trace( const char* fun, const char* fil, int lin ) 162 : function(fun), file(fil), line(lin) {} 163 }; 164 165 //! Get error message 166 MESQUITE_EXPORT const char* error_message() const; 167 168 //! Container type used to store stack trace. 169 //! Return type for stack() 170 typedef std::list<Trace> StackTrace; 171 172 //! Get stack trace stack() const173 inline const StackTrace& stack() const { return stackTrace; } 174 175 176 /* ************************************************************ * 177 * Set error data 178 * ************************************************************ */ 179 180 //! Add to back-trace of call stack. Called by MSQ_CHKERR. 181 //! Must always return true. 182 MESQUITE_EXPORT virtual bool push( const char* function, const char* file, int line ); 183 184 //! Initialize the error object with the passed data. 185 MESQUITE_EXPORT virtual bool set_error( ErrorCode num, const char* msg = 0 ); 186 187 //!\class setter 188 //! Used for implementing pre-processor macros for internal use 189 //! in Mesquite. 190 class MESQUITE_EXPORT Setter { 191 public: Setter(MsqError & err,const char * function,const char * file,int line)192 Setter(MsqError& err, const char* function, const char* file, int line) 193 : mErr(err), functionName(function), fileName(file), lineNumber(line) {} 194 195 bool set( ErrorCode num ); 196 bool set( const char* message, ErrorCode num ); 197 bool set( const std::string& message, ErrorCode num ); 198 bool set( ErrorCode num, const char* format, ... ) 199 #ifdef __GNUC__ 200 __attribute__ ((format (printf, 3, 4))) 201 #endif 202 ; // ending semicolon for set( ErrorCode num, const char* format, ... ) 203 private: 204 MsqError& mErr; 205 const char* functionName; 206 const char* fileName; 207 int lineNumber; 208 }; 209 setter(MsqError & err,const char * function,const char * file,int line)210 static inline Setter setter( MsqError& err, const char* function, const char* file, int line ) 211 { return Setter( err, function, file, line ); } 212 213 private: 214 215 ErrorCode errorCode; 216 std::string errorMessage; 217 StackTrace stackTrace; 218 }; 219 220 221 //! Print message and stack trace 222 MESQUITE_EXPORT std::ostream& operator<<( std::ostream&, const MsqError& ); 223 //! Print MsqError::Trace 224 MESQUITE_EXPORT std::ostream& operator<<( std::ostream&, const MsqError::Trace& ); 225 226 /** 227 *\class MsqPrintError 228 *\brief Utility class for printing error data - used in Mesquite tests. 229 *\author Jason Kraftcheck 230 *\date 2004-10-11 231 * 232 * A subclass of MsqError. Behaves the same as MsqError, except that 233 * it will automatically print itself to the specified ostream upon 234 * destruction if an error occured. For objections of this type 235 * declared on the stack (not new'd), this means that the error will 236 * be printed when the function returns (if an error occured.) 237 */ 238 class MsqPrintError : public MsqError 239 { 240 public: 241 //!\brief Initialize with ostream to print error data to. MsqPrintError(std::ostream & stream)242 MESQUITE_EXPORT MsqPrintError( std::ostream& stream ) 243 : outputStream(stream) {} 244 245 //!\brief On destruction, conditionally prints error data. 246 MESQUITE_EXPORT virtual ~MsqPrintError( ); 247 248 private: 249 250 std::ostream& outputStream; 251 }; 252 253 /*@}*/ 254 255 } // namespace 256 257 258 #endif 259 260 261