PFUNC
1.0
|
00001 #ifndef PFUNC_EXCEPTION_HPP 00002 #define PFUNC_EXCEPTION_HPP 00003 00004 #include <exception> 00005 #include <typeinfo> 00006 #include <stdexcept> 00007 #include <string> 00008 #include <cstdlib> 00009 #include <pfunc/config.h> 00010 00011 #if PFUNC_WINDOWS == 1 00012 #include <Windows.h> 00013 #endif 00014 00020 namespace pfunc { 00021 #if PFUNC_WINDOWS == 1 00022 typedef DWORD error_code_type; 00023 #else 00024 typedef int error_code_type; 00025 #endif 00026 } 00027 00031 #define LINE_TO_STR_HELP(line) #line 00032 00036 #define LINE_TO_STR(line) LINE_TO_STR_HELP(line) 00037 00041 #define FILE_AND_LINE() __FILE__ ":" LINE_TO_STR(__LINE__) 00042 00054 #if PFUNC_USE_EXCEPTIONS == 1 00055 #define PFUNC_CATCH_AND_RETHROW(STRUCT_NAME,FUNC_NAME) \ 00056 catch (const exception& error) { \ 00057 /* Append append the information and throw again */ \ 00058 if (NULL != except) except->destroy (); \ 00059 except = error.clone (); \ 00060 except->add_to_trace \ 00061 (": from " #STRUCT_NAME"::"#FUNC_NAME " at " FILE_AND_LINE()); \ 00062 except->rethrow (); \ 00063 } catch (const std::exception& error) { \ 00064 /* Wrap it up in a exception_generic_impl */ \ 00065 std::string prev_trace (typeid (error).name()); \ 00066 prev_trace += ": from " #STRUCT_NAME"::"#FUNC_NAME " at " FILE_AND_LINE(); \ 00067 if (NULL != except) except->destroy (); \ 00068 except = exception_generic_impl::convert \ 00069 (prev_trace.c_str(), error.what(), \ 00070 static_cast<error_code_type>(PFUNC_ERROR)); \ 00071 except->rethrow (); \ 00072 } catch (...) { \ 00073 throw exception_generic_impl \ 00074 (#STRUCT_NAME"::"#FUNC_NAME " at " FILE_AND_LINE(), \ 00075 "Unknown error", \ 00076 static_cast<error_code_type>(PFUNC_ERROR)); \ 00077 } 00078 00090 #define PFUNC_CATCH_AND_STORE(STRUCT_NAME,FUNC_NAME) \ 00091 catch (const exception& error) { \ 00092 /* Append append the information and throw again */ \ 00093 if (NULL != except) except->destroy (); \ 00094 except = error.clone (); \ 00095 except->add_to_trace \ 00096 (": from " #STRUCT_NAME"::"#FUNC_NAME " at " FILE_AND_LINE()); \ 00097 } catch (const std::exception& error) { \ 00098 /* Wrap it up in a exception_generic_impl */ \ 00099 std::string prev_trace (typeid (error).name()); \ 00100 prev_trace += ": from " #STRUCT_NAME"::"#FUNC_NAME " at " FILE_AND_LINE(); \ 00101 if (NULL != except) except->destroy (); \ 00102 except = exception_generic_impl::convert \ 00103 (prev_trace.c_str(), error.what(), \ 00104 static_cast<error_code_type>(PFUNC_ERROR)); \ 00105 } catch (...) { \ 00106 except = new exception_generic_impl \ 00107 (#STRUCT_NAME"::"#FUNC_NAME " at " FILE_AND_LINE(), \ 00108 "Unknown error", \ 00109 static_cast<error_code_type>(PFUNC_ERROR)); \ 00110 } 00111 00115 #define PFUNC_CHECK_AND_RETHROW() if (NULL != except) except->rethrow(); 00116 00121 #define PFUNC_C_CATCH_AND_RETURN_EXCEPTION_CODE() \ 00122 catch (const pfunc::exception& error) { \ 00123 return error.code(); \ 00124 } 00125 00129 #define PFUNC_CXX_CATCH_AND_RETHROW() \ 00130 catch (const exception& error) { error.rethrow(); } 00131 00135 #define PFUNC_START_TRY_BLOCK() try { 00136 00140 #define PFUNC_CONSTRUCTOR_TRY_BLOCK() try 00141 00145 #define PFUNC_END_TRY_BLOCK() } 00146 00150 #define PFUNC_DEFINE_EXCEPT_PTR() exception* except; 00151 00155 #define PFUNC_EXCEPT_PTR_INIT() , except (NULL) 00156 00160 #define PFUNC_EXCEPT_PTR_CLEAR() \ 00161 if (NULL != except) { \ 00162 except->destroy(); \ 00163 except = NULL; \ 00164 } 00165 00170 #define PFUNC_CAPTURE_RETURN_VALUE(var) error_code_type var = 00171 00172 #else 00173 #define PFUNC_CATCH_AND_RETHROW(STRUCT_NAME,FUNC_NAME) 00174 #define PFUNC_CATCH_AND_STORE(STRUCT_NAME,FUNC_NAME) 00175 #define PFUNC_C_CATCH_AND_RETURN_EXCEPTION_CODE() 00176 #define PFUNC_CHECK_AND_RETHROW() 00177 #define PFUNC_CXX_CATCH_AND_RETHROW() 00178 #define PFUNC_START_TRY_BLOCK() 00179 #define PFUNC_CONSTRUCTOR_TRY_BLOCK() 00180 #define PFUNC_END_TRY_BLOCK() 00181 #define PFUNC_DEFINE_EXCEPT_PTR() 00182 #define PFUNC_EXCEPT_PTR_INIT() 00183 #define PFUNC_EXCEPT_PTR_CLEAR() 00184 #define PFUNC_CAPTURE_RETURN_VALUE(var) 00185 #endif 00186 00187 #if PFUNC_USE_EXCEPTIONS == 1 00188 namespace pfunc { 00189 00194 struct exception : public std::exception { 00196 virtual const char* trace () const throw() = 0; 00197 00199 virtual void add_to_trace (const char*) throw() = 0; 00200 00202 virtual const char* what () const throw() = 0; 00203 00205 virtual error_code_type code () const throw() = 0; 00206 00208 virtual exception* clone () const throw() = 0; 00209 00211 virtual void rethrow () const = 0; 00212 00214 virtual void destroy () throw() = 0; 00215 }; 00216 00220 struct exception_generic_impl : virtual exception { 00221 private: 00222 std::string error_trace; 00223 std::string error_string; 00224 error_code_type error_code; 00226 public: 00234 exception_generic_impl (const char* error_trace, 00235 const char* error_string, 00236 const error_code_type& error_code=0) : 00237 error_trace (error_trace), 00238 error_string (error_string), 00239 error_code (error_code) {} 00240 00246 exception_generic_impl (const exception_generic_impl& other) : 00247 exception (), 00248 error_trace (other.trace()), 00249 error_string (other.what()), 00250 error_code (other.code()) {} 00251 00253 virtual ~exception_generic_impl () throw() {} 00254 00258 const char* trace (void) const throw() { return error_trace.c_str(); } 00259 00265 void add_to_trace (const char* new_trace) throw() { 00266 error_trace += new_trace; 00267 } 00268 00272 const char* what (void) const throw () { return error_string.c_str(); } 00273 00277 error_code_type code (void) const throw() { return error_code; } 00278 00284 exception* clone () const throw() { 00285 exception* clone = 00286 reinterpret_cast<exception*> (malloc (sizeof (exception_generic_impl))); 00287 if (NULL != clone) new (clone) exception_generic_impl(*this); 00288 return clone; 00289 } 00290 00296 void rethrow () const { throw *this; } 00297 00308 static exception* convert (const char* _error_trace, 00309 const char* _error_string, 00310 const error_code_type& _error_code = 0) throw() { 00311 exception* clone = 00312 reinterpret_cast<exception*> (malloc (sizeof (exception_generic_impl))); 00313 if (NULL != clone) 00314 new (clone) exception_generic_impl(_error_trace, 00315 _error_string, 00316 _error_code); 00317 00318 return clone; 00319 } 00320 00325 void destroy () throw() { 00326 this->exception_generic_impl::~exception_generic_impl(); 00327 free (this); 00328 } 00329 }; 00330 } /* namespace pfunc */ 00331 #endif // PFUNC_USE_EXCEPTIONS 00332 #endif // PFUNC_EXCEPTION_HPP