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