1 #ifndef __error_h__ 2 #define __error_h__ 3 4 #include <iostream> 5 #include <string> 6 #include <algorithm> 7 #include <exception> 8 #include <vector> 9 10 #include <cerrno> 11 12 #include "asserts.h" 13 #include "types.h" 14 15 /** Instance of a single error containing a descriptive error message and the 16 * location in the file that the error took place */ 17 class error_instance 18 { 19 public: 20 error_instance(); 21 error_instance(const error_instance& a_e); 22 error_instance( 23 const std::string a_what, 24 #ifdef __GNUC__ 25 const std::string a_where, 26 #endif 27 const std::string a_file, 28 const uint16 a_line 29 ); 30 31 void clear(void); 32 void set(void); 33 void set(const error_instance& a_e); 34 void set( 35 const std::string a_what, 36 #ifdef __GNUC__ 37 const std::string a_where, 38 #endif 39 const std::string a_file, 40 const uint16 a_line 41 ); 42 43 const std::string what(void) const; 44 #ifdef __GNUC__ 45 const std::string where(void) const; 46 #endif 47 const std::string file(void) const; 48 const uint16 line(void) const; 49 50 error_instance& operator=(const error_instance& a_e); 51 52 // void dump(std::ostream& a_out, const std::string& a_prefix) const; 53 54 private: 55 std::string m_what; 56 #ifdef __GNUC__ 57 std::string m_where; 58 #endif 59 std::string m_file; 60 uint16 m_line; 61 }; 62 63 #ifdef __GNUC__ 64 #define ERROR_INSTANCE(s) \ 65 error_instance((s), __PRETTY_FUNCTION__, __FILE__, __LINE__) 66 #else 67 #define ERROR_INSTANCE(s) \ 68 error_instance((s), __FILE__, __LINE__) 69 #endif 70 71 /** An error class */ 72 class error : public std::vector<error_instance> 73 { 74 public: 75 typedef std::vector<error_instance> type; 76 77 error(const int a_errno); 78 error( 79 const int a_errno, 80 const error_instance& a_e, 81 const bool a_internal = false 82 ); 83 error(const error& a_e); 84 85 void clear(void); 86 void clear_stack(void); 87 void internal(bool a_i); 88 const bool internal(void) const; 89 void num(int a_i); 90 int num(void) const; 91 void push_back(const error_instance& a_e); 92 void push_back(const error& a_e); 93 void push_back(const std::string& a_str); 94 void assign(const error& a_e); 95 96 error& operator=(const error& a_e); 97 std::ostream& write( 98 std::ostream& a_out, 99 const std::string a_prefix = "" 100 ) const; 101 const std::string str(const std::string a_prefix = "") const; 102 103 // std::ostream& dump(std::ostream& a_out) const; 104 105 private: 106 int m_errno; 107 bool m_internal; 108 }; 109 110 std::ostream& operator<<(std::ostream& a_out, const error& a_e); 111 112 //----------------------------------------------------------------------------- 113 114 #define err_unknown INTERNAL_ERROR(0,"An unknown error has occured") 115 116 #define err_nomem ERROR(ENOMEM,"Out of memory") 117 118 //----------------------------------------------------------------------------- 119 120 #define ERROR(e,s) \ 121 error(e,ERROR_INSTANCE((s)), false) 122 123 #define INTERNAL_ERROR(e,s) \ 124 error(e,ERROR_INSTANCE(s), true) 125 126 #define TRY(code,es) \ 127 try { \ 128 code; \ 129 } \ 130 catch(error e) { \ 131 e.push_back(ERROR_INSTANCE(es)); \ 132 throw(e); \ 133 } \ 134 catch(...) { \ 135 if (errno == ENOMEM) { \ 136 throw(err_nomem); \ 137 } \ 138 error e = err_unknown; \ 139 \ 140 e.push_back(es); \ 141 throw(e); \ 142 } 143 144 #define TRY_nomem(code) \ 145 try { \ 146 code; \ 147 } \ 148 catch(error e) { \ 149 throw(e); \ 150 } \ 151 catch(...) { \ 152 if (errno == ENOMEM) { \ 153 throw(err_nomem); \ 154 } \ 155 throw(err_unknown); \ 156 } 157 158 #define TRY_instead(code,es) \ 159 try { \ 160 code; \ 161 } \ 162 catch(error e) { \ 163 e.clear_stack(); \ 164 e.push_back(ERROR_INSTANCE(es)); \ 165 throw(e); \ 166 } \ 167 catch(...) { \ 168 if (errno == ENOMEM) { \ 169 throw(err_nomem); \ 170 } \ 171 error e = err_unknown; \ 172 \ 173 e.push_back(es); \ 174 throw(e); \ 175 } 176 177 #define TRY_log(code,es) \ 178 try { \ 179 code; \ 180 } \ 181 catch(error e) { \ 182 e.clear_stack(); \ 183 e.push_back(ERROR_INSTANCE(es)); \ 184 logger.write(e.str()); \ 185 } \ 186 catch(...) { \ 187 if (errno == ENOMEM) { \ 188 throw(err_nomem); \ 189 } \ 190 error e = err_unknown; \ 191 \ 192 e.push_back(es); \ 193 logger.write(e.str()); \ 194 } 195 196 const char * get_error_str(const int a_err); 197 198 #endif 199