diagnostic_information.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
  2. //Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef UUID_0552D49838DD11DD90146B8956D89593
  5. #define UUID_0552D49838DD11DD90146B8956D89593
  6. #include <boost/config.hpp>
  7. #include <boost/exception/get_error_info.hpp>
  8. #include <boost/exception/detail/exception_ptr_base.hpp>
  9. #include <boost/utility/enable_if.hpp>
  10. #include <exception>
  11. #include <sstream>
  12. #include <string>
  13. namespace
  14. boost
  15. {
  16. namespace
  17. exception_detail
  18. {
  19. template <class T>
  20. struct
  21. enable_boost_exception_overload
  22. {
  23. struct yes { char q[100]; };
  24. typedef char no;
  25. static yes check(exception const *);
  26. static no check(...);
  27. enum e { value=sizeof(check((T*)0))==sizeof(yes) };
  28. };
  29. template <class T>
  30. struct
  31. enable_std_exception_overload
  32. {
  33. struct yes { char q[100]; };
  34. typedef char no;
  35. static yes check(std::exception const *);
  36. static no check(...);
  37. enum e { value = !enable_boost_exception_overload<T>::value && sizeof(check((T*)0))==sizeof(yes) };
  38. };
  39. inline
  40. char const *
  41. get_diagnostic_information( exception const & x )
  42. {
  43. if( error_info_container * c=x.data_.get() )
  44. #ifndef BOOST_NO_EXCEPTIONS
  45. try
  46. {
  47. #endif
  48. return c->diagnostic_information();
  49. #ifndef BOOST_NO_EXCEPTIONS
  50. }
  51. catch(...)
  52. {
  53. }
  54. #endif
  55. return 0;
  56. }
  57. inline
  58. std::string
  59. diagnostic_information_impl( boost::exception const * be, std::exception const * se )
  60. {
  61. BOOST_ASSERT(be||se);
  62. #ifndef BOOST_NO_RTTI
  63. if( !se )
  64. se = dynamic_cast<std::exception const *>(be);
  65. if( !be )
  66. be = dynamic_cast<boost::exception const *>(se);
  67. #endif
  68. std::ostringstream tmp;
  69. if( be )
  70. {
  71. if( char const * const * f=get_error_info<throw_file>(*be) )
  72. {
  73. tmp << *f;
  74. if( int const * l=get_error_info<throw_line>(*be) )
  75. tmp << '(' << *l << "): ";
  76. }
  77. tmp << "Throw in function ";
  78. if( char const * const * fn=get_error_info<throw_function>(*be) )
  79. tmp << *fn;
  80. else
  81. tmp << "(unknown)";
  82. tmp << '\n';
  83. }
  84. #ifndef BOOST_NO_RTTI
  85. tmp << std::string("Dynamic exception type: ") <<
  86. (be?BOOST_EXCEPTION_DYNAMIC_TYPEID(*be):BOOST_EXCEPTION_DYNAMIC_TYPEID(*se)).name() << '\n';
  87. #endif
  88. if( se )
  89. tmp << "std::exception::what: " << se->what() << '\n';
  90. if( be )
  91. if( char const * s=exception_detail::get_diagnostic_information(*be) )
  92. if( *s )
  93. tmp << s;
  94. return tmp.str();
  95. }
  96. }
  97. template <class T>
  98. inline
  99. typename enable_if<exception_detail::enable_boost_exception_overload<T>,std::string>::type
  100. diagnostic_information( T const & e )
  101. {
  102. return exception_detail::diagnostic_information_impl(&e,0);
  103. }
  104. template <class T>
  105. inline
  106. typename enable_if<exception_detail::enable_std_exception_overload<T>,std::string>::type
  107. diagnostic_information( T const & e )
  108. {
  109. return exception_detail::diagnostic_information_impl(0,&e);
  110. }
  111. }
  112. #ifndef BOOST_NO_EXCEPTIONS
  113. #include <boost/exception/current_exception_cast.hpp>
  114. namespace
  115. boost
  116. {
  117. inline
  118. std::string
  119. current_exception_diagnostic_information()
  120. {
  121. boost::exception const * be=current_exception_cast<boost::exception const>();
  122. std::exception const * se=current_exception_cast<std::exception const>();
  123. if( be || se )
  124. return exception_detail::diagnostic_information_impl(be,se);
  125. else
  126. return "No diagnostic information available.";
  127. }
  128. inline
  129. std::string
  130. diagnostic_information( exception_detail::exception_ptr_base const & p )
  131. {
  132. if( !p._empty() )
  133. try
  134. {
  135. p._rethrow();
  136. }
  137. catch(
  138. ... )
  139. {
  140. return current_exception_diagnostic_information();
  141. }
  142. return "<empty>";
  143. }
  144. }
  145. #endif
  146. #endif