MOAB: Mesh Oriented datABase  (version 5.2.1)
MsqError.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2004 Sandia Corporation and Argonne National
00005     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
00006     with Sandia Corporation, the U.S. Government retains certain
00007     rights in this software.
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2.1 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023   ***************************************************************** */
00024 /*!
00025   \file   MsqError.cpp
00026   \brief  Used to hold the error state and return it to the application.
00027   \author Jason Kraftcheck
00028   \date   2004-09-17
00029 */
00030 
00031 #include "MsqError.hpp"
00032 #include "Mesquite.hpp"
00033 
00034 #include <ostream>
00035 #include <stdio.h>
00036 #include <stdarg.h>
00037 #include <assert.h>
00038 
00039 #include <cstring>
00040 using std::strncpy;
00041 
00042 namespace MBMesquite
00043 {
00044 
00045 const char* MsqError::error_message() const
00046 {
00047     static const char* const error_messages[] = { "No Error",
00048                                                   "<unknown>",
00049                                                   "Out of memory",
00050                                                   "Invalid argument",
00051                                                   "Data not initialized",
00052                                                   "Invalid state",
00053                                                   "File access error",
00054                                                   "File format error",
00055                                                   "Syntax error",
00056                                                   "I/O error",
00057                                                   "Invalid mesh",
00058                                                   "No storage mode for PatchData",
00059                                                   "Not implemented",
00060                                                   "Internal error",
00061                                                   "Interrupted",
00062                                                   "Duplicate tag name",
00063                                                   "Tag not found",
00064                                                   "Unsupported element type",
00065                                                   "Parallel Error - error occurred on at least one processor",
00066                                                   "barruer violated when processing barrier Target Metric",
00067                                                   "Invalid Error Code" };
00068 
00069     /* If this is ever false, it should be caught by a unit test.
00070        Do an assert here so the unit test fails.
00071        This asserts that all error codes have a string in the above list. */
00072     assert( sizeof( error_messages ) == sizeof( char* ) * ( LAST_ERROR_CODE + 1 ) );
00073 
00074     if( !errorMessage.empty() ) return errorMessage.c_str();
00075 
00076     if( errorCode >= 0 && errorCode < LAST_ERROR_CODE ) return error_messages[errorCode];
00077 
00078     return error_messages[LAST_ERROR_CODE];
00079 }
00080 
00081 MsqError::~MsqError() {}
00082 
00083 bool MsqError::Setter::set( const std::string& msg, ErrorCode num )
00084 {
00085     return mErr.set_error( num, msg.c_str() ) && mErr.push( functionName, fileName, lineNumber );
00086 }
00087 
00088 bool MsqError::Setter::set( const char* msg, ErrorCode num )
00089 {
00090     return mErr.set_error( num, msg ) && mErr.push( functionName, fileName, lineNumber );
00091 }
00092 
00093 bool MsqError::Setter::set( ErrorCode num )
00094 {
00095     return mErr.set_error( num ) && mErr.push( functionName, fileName, lineNumber );
00096 }
00097 
00098 bool MsqError::Setter::set( ErrorCode num, const char* format, ... )
00099 {
00100     char buffer[1024];
00101 
00102 #if defined( HAVE_VSNPRINTF )
00103     va_list args;
00104     va_start( args, format );
00105     vsnprintf( buffer, sizeof( buffer ), format, args );
00106     va_end( args );
00107 #elif defined( HAVE__VSNPRINTF )
00108     va_list args;
00109     va_start( args, format );
00110     _vsnprintf( buffer, sizeof( buffer ), format, args );
00111     va_end( args );
00112 #elif defined( HAVE_VSPRINTF )
00113     va_list args;
00114     va_start( args, format );
00115     vsprintf( buffer, format, args );
00116     va_end( args );
00117 #else
00118     strncpy( buffer, format, sizeof( buffer ) );
00119     buffer[sizeof( buffer ) - 1] = '\0';
00120 #endif
00121 
00122     return mErr.set_error( num, buffer ) && mErr.push( functionName, fileName, lineNumber );
00123 }
00124 
00125 bool MsqError::push( const char* function, const char* file, int line )
00126 {
00127     stackTrace.push_back( Trace( function, file, line ) );
00128     return true;
00129 }
00130 
00131 bool MsqError::set_error( ErrorCode num, const char* msg )
00132 {
00133     errorCode = num;
00134     stackTrace.clear();
00135 
00136     if( msg )
00137         errorMessage = msg;
00138     else
00139         // MS VC6 doesn't have string::clear()!
00140         errorMessage.resize( 0 );
00141 
00142     return num != NO_ERROR;
00143 }
00144 
00145 void MsqError::clear()
00146 {
00147     errorCode = NO_ERROR;
00148     // MS VC6 doesn't have string::clear()!
00149     errorMessage.resize( 0 );
00150     stackTrace.clear();
00151 }
00152 
00153 std::ostream& operator<<( std::ostream& str, const MsqError::Trace& tr )
00154 {
00155     return ( str << tr.function << " at " << tr.file << ":" << tr.line );
00156 }
00157 
00158 std::ostream& operator<<( std::ostream& str, const MsqError& err )
00159 {
00160     str << "MESQUITE ERROR " << (int)err.error_code() << " : " << err.error_message() << std::endl;
00161 
00162     MsqError::StackTrace::const_iterator iter      = err.stack().begin();
00163     const MsqError::StackTrace::const_iterator end = err.stack().end();
00164     if( iter != end )
00165     {
00166         str << "  at " << *iter << std::endl;
00167         ++iter;
00168     }
00169     for( ; iter != end; ++iter )
00170         str << "  in " << *iter << std::endl;
00171 
00172     return str;
00173 }
00174 
00175 MsqPrintError::~MsqPrintError()
00176 {
00177     if( error() ) outputStream << *this << std::endl;
00178 }
00179 
00180 }  // namespace MBMesquite
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines