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 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
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