rvm 1.08
|
00001 #ifndef __error_h__ 00002 #define __error_h__ 00003 00004 #include <iostream> 00005 #include <string> 00006 #include <algorithm> 00007 #include <exception> 00008 #include <vector> 00009 00010 #include <cerrno> 00011 00012 #include "asserts.h" 00013 #include "types.h" 00014 00015 /** Instance of a single error containing a descriptive error message and the 00016 * location in the file that the error took place */ 00017 class error_instance 00018 { 00019 public: 00020 error_instance(); 00021 error_instance(const error_instance& a_e); 00022 error_instance( 00023 const std::string a_what, 00024 #ifdef __GNUC__ 00025 const std::string a_where, 00026 #endif 00027 const std::string a_file, 00028 const uint16 a_line 00029 ); 00030 00031 void clear(void); 00032 void set(void); 00033 void set(const error_instance& a_e); 00034 void set( 00035 const std::string a_what, 00036 #ifdef __GNUC__ 00037 const std::string a_where, 00038 #endif 00039 const std::string a_file, 00040 const uint16 a_line 00041 ); 00042 00043 const std::string what(void) const; 00044 #ifdef __GNUC__ 00045 const std::string where(void) const; 00046 #endif 00047 const std::string file(void) const; 00048 const uint16 line(void) const; 00049 00050 error_instance& operator=(const error_instance& a_e); 00051 00052 // void dump(std::ostream& a_out, const std::string& a_prefix) const; 00053 00054 private: 00055 std::string m_what; 00056 #ifdef __GNUC__ 00057 std::string m_where; 00058 #endif 00059 std::string m_file; 00060 uint16 m_line; 00061 }; 00062 00063 #ifdef __GNUC__ 00064 #define ERROR_INSTANCE(s) \ 00065 error_instance((s), __PRETTY_FUNCTION__, __FILE__, __LINE__) 00066 #else 00067 #define ERROR_INSTANCE(s) \ 00068 error_instance((s), __FILE__, __LINE__) 00069 #endif 00070 00071 /** An error class */ 00072 class error : public std::vector<error_instance> 00073 { 00074 public: 00075 typedef std::vector<error_instance> type; 00076 00077 error(const int a_errno); 00078 error( 00079 const int a_errno, 00080 const error_instance& a_e, 00081 const bool a_internal = false 00082 ); 00083 error(const error& a_e); 00084 00085 void clear(void); 00086 void clear_stack(void); 00087 void internal(bool a_i); 00088 const bool internal(void) const; 00089 void num(int a_i); 00090 int num(void) const; 00091 void push_back(const error_instance& a_e); 00092 void push_back(const error& a_e); 00093 void push_back(const std::string& a_str); 00094 void assign(const error& a_e); 00095 00096 error& operator=(const error& a_e); 00097 std::ostream& write( 00098 std::ostream& a_out, 00099 const std::string a_prefix = "" 00100 ) const; 00101 const std::string str(const std::string a_prefix = "") const; 00102 00103 // std::ostream& dump(std::ostream& a_out) const; 00104 00105 private: 00106 int m_errno; 00107 bool m_internal; 00108 }; 00109 00110 std::ostream& operator<<(std::ostream& a_out, const error& a_e); 00111 00112 //----------------------------------------------------------------------------- 00113 00114 #define err_unknown INTERNAL_ERROR(0,"An unknown error has occured") 00115 00116 #define err_nomem ERROR(ENOMEM,"Out of memory") 00117 00118 //----------------------------------------------------------------------------- 00119 00120 #define ERROR(e,s) \ 00121 error(e,ERROR_INSTANCE((s)), false) 00122 00123 #define INTERNAL_ERROR(e,s) \ 00124 error(e,ERROR_INSTANCE(s), true) 00125 00126 #define TRY(code,es) \ 00127 try { \ 00128 code; \ 00129 } \ 00130 catch(error e) { \ 00131 e.push_back(ERROR_INSTANCE(es)); \ 00132 throw(e); \ 00133 } \ 00134 catch(...) { \ 00135 if (errno == ENOMEM) { \ 00136 throw(err_nomem); \ 00137 } \ 00138 error e = err_unknown; \ 00139 \ 00140 e.push_back(es); \ 00141 throw(e); \ 00142 } 00143 00144 #define TRY_nomem(code) \ 00145 try { \ 00146 code; \ 00147 } \ 00148 catch(error e) { \ 00149 throw(e); \ 00150 } \ 00151 catch(...) { \ 00152 if (errno == ENOMEM) { \ 00153 throw(err_nomem); \ 00154 } \ 00155 throw(err_unknown); \ 00156 } 00157 00158 #define TRY_instead(code,es) \ 00159 try { \ 00160 code; \ 00161 } \ 00162 catch(error e) { \ 00163 e.clear_stack(); \ 00164 e.push_back(ERROR_INSTANCE(es)); \ 00165 throw(e); \ 00166 } \ 00167 catch(...) { \ 00168 if (errno == ENOMEM) { \ 00169 throw(err_nomem); \ 00170 } \ 00171 error e = err_unknown; \ 00172 \ 00173 e.push_back(es); \ 00174 throw(e); \ 00175 } 00176 00177 #define TRY_log(code,es) \ 00178 try { \ 00179 code; \ 00180 } \ 00181 catch(error e) { \ 00182 e.clear_stack(); \ 00183 e.push_back(ERROR_INSTANCE(es)); \ 00184 logger.write(e.str()); \ 00185 } \ 00186 catch(...) { \ 00187 if (errno == ENOMEM) { \ 00188 throw(err_nomem); \ 00189 } \ 00190 error e = err_unknown; \ 00191 \ 00192 e.push_back(es); \ 00193 logger.write(e.str()); \ 00194 } 00195 00196 const char * get_error_str(const int a_err); 00197 00198 #endif