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
00016
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
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
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 std::string& a_str);
00093 void assign(const error& a_e);
00094
00095 error& operator=(const error& a_e);
00096 std::ostream& write(
00097 std::ostream& a_out,
00098 const std::string a_prefix = ""
00099 ) const;
00100 const std::string str(const std::string a_prefix = "") const;
00101
00102
00103
00104 private:
00105 int m_errno;
00106 bool m_internal;
00107 };
00108
00109 std::ostream& operator<<(std::ostream& a_out, const error& a_e);
00110
00111
00112
00113 #define err_unknown INTERNAL_ERROR(0,"An unknown error has occured")
00114
00115 #define err_nomem ERROR(ENOMEM,"Out of memory")
00116
00117
00118
00119 #define ERROR(e,s) \
00120 error(e,ERROR_INSTANCE((s)), false)
00121
00122 #define INTERNAL_ERROR(e,s) \
00123 error(e,ERROR_INSTANCE(s), true)
00124
00125 #define TRY(code,es) \
00126 try { \
00127 code; \
00128 } \
00129 catch(error e) { \
00130 e.push_back(ERROR_INSTANCE(es)); \
00131 throw(e); \
00132 } \
00133 catch(...) { \
00134 if (errno == ENOMEM) { \
00135 throw(err_nomem); \
00136 } \
00137 error e = err_unknown; \
00138 \
00139 e.push_back(es); \
00140 throw(e); \
00141 }
00142
00143 #define TRY_nomem(code) \
00144 try { \
00145 code; \
00146 } \
00147 catch(error e) { \
00148 throw(e); \
00149 } \
00150 catch(...) { \
00151 if (errno == ENOMEM) { \
00152 throw(err_nomem); \
00153 } \
00154 throw(err_unknown); \
00155 }
00156
00157 #define TRY_instead(code,es) \
00158 try { \
00159 code; \
00160 } \
00161 catch(error e) { \
00162 e.clear_stack(); \
00163 e.push_back(ERROR_INSTANCE(es)); \
00164 throw(e); \
00165 } \
00166 catch(...) { \
00167 if (errno == ENOMEM) { \
00168 throw(err_nomem); \
00169 } \
00170 error e = err_unknown; \
00171 \
00172 e.push_back(es); \
00173 throw(e); \
00174 }
00175
00176 #define TRY_log(code,es) \
00177 try { \
00178 code; \
00179 } \
00180 catch(error e) { \
00181 e.clear_stack(); \
00182 e.push_back(ERROR_INSTANCE(es)); \
00183 logger.write(e.str()); \
00184 } \
00185 catch(...) { \
00186 if (errno == ENOMEM) { \
00187 throw(err_nomem); \
00188 } \
00189 error e = err_unknown; \
00190 \
00191 e.push_back(es); \
00192 logger.write(e.str()); \
00193 }
00194
00195 const char * get_error_str(const int a_err);
00196
00197 #endif