#ifndef __error_h__ #define __error_h__ #include #include #include #include #include #include #include "asserts.h" #include "types.h" /** Instance of a single error containing a descriptive error message and the * location in the file that the error took place */ class error_instance { public: error_instance(); error_instance(const error_instance& a_e); error_instance( const std::string a_what, #ifdef __GNUC__ const std::string a_where, #endif const std::string a_file, const uint16 a_line ); void clear(void); void set(void); void set(const error_instance& a_e); void set( const std::string a_what, #ifdef __GNUC__ const std::string a_where, #endif const std::string a_file, const uint16 a_line ); const std::string what(void) const; #ifdef __GNUC__ const std::string where(void) const; #endif const std::string file(void) const; const uint16 line(void) const; error_instance& operator=(const error_instance& a_e); // void dump(std::ostream& a_out, const std::string& a_prefix) const; private: std::string m_what; #ifdef __GNUC__ std::string m_where; #endif std::string m_file; uint16 m_line; }; #ifdef __GNUC__ #define ERROR_INSTANCE(s) \ error_instance((s), __PRETTY_FUNCTION__, __FILE__, __LINE__) #else #define ERROR_INSTANCE(s) \ error_instance((s), __FILE__, __LINE__) #endif /** An error class */ class error : public std::vector { public: typedef std::vector type; error(const int a_errno); error( const int a_errno, const error_instance& a_e, const bool a_internal = false ); error(const error& a_e); void clear(void); void clear_stack(void); void internal(bool a_i); const bool internal(void) const; void num(int a_i); int num(void) const; void push_back(const error_instance& a_e); void push_back(const error& a_e); void push_back(const std::string& a_str); void assign(const error& a_e); error& operator=(const error& a_e); std::ostream& write( std::ostream& a_out, const std::string a_prefix = "" ) const; const std::string str(const std::string a_prefix = "") const; // std::ostream& dump(std::ostream& a_out) const; private: int m_errno; bool m_internal; }; std::ostream& operator<<(std::ostream& a_out, const error& a_e); //----------------------------------------------------------------------------- #define err_unknown INTERNAL_ERROR(0,"An unknown error has occured") #define err_nomem ERROR(ENOMEM,"Out of memory") //----------------------------------------------------------------------------- #define ERROR(e,s) \ error(e,ERROR_INSTANCE((s)), false) #define INTERNAL_ERROR(e,s) \ error(e,ERROR_INSTANCE(s), true) #define TRY(code,es) \ try { \ code; \ } \ catch(error e) { \ e.push_back(ERROR_INSTANCE(es)); \ throw(e); \ } \ catch(...) { \ if (errno == ENOMEM) { \ throw(err_nomem); \ } \ error e = err_unknown; \ \ e.push_back(es); \ throw(e); \ } #define TRY_nomem(code) \ try { \ code; \ } \ catch(error e) { \ throw(e); \ } \ catch(...) { \ if (errno == ENOMEM) { \ throw(err_nomem); \ } \ throw(err_unknown); \ } #define TRY_instead(code,es) \ try { \ code; \ } \ catch(error e) { \ e.clear_stack(); \ e.push_back(ERROR_INSTANCE(es)); \ throw(e); \ } \ catch(...) { \ if (errno == ENOMEM) { \ throw(err_nomem); \ } \ error e = err_unknown; \ \ e.push_back(es); \ throw(e); \ } #define TRY_log(code,es) \ try { \ code; \ } \ catch(error e) { \ e.clear_stack(); \ e.push_back(ERROR_INSTANCE(es)); \ logger.write(e.str()); \ } \ catch(...) { \ if (errno == ENOMEM) { \ throw(err_nomem); \ } \ error e = err_unknown; \ \ e.push_back(es); \ logger.write(e.str()); \ } const char * get_error_str(const int a_err); #endif