Chris@16
|
1 //Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.
|
Chris@16
|
2
|
Chris@16
|
3 //Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef UUID_0552D49838DD11DD90146B8956D89593
|
Chris@16
|
7 #define UUID_0552D49838DD11DD90146B8956D89593
|
Chris@16
|
8 #if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
|
Chris@16
|
9 #pragma GCC system_header
|
Chris@16
|
10 #endif
|
Chris@16
|
11 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
|
Chris@16
|
12 #pragma warning(push,1)
|
Chris@16
|
13 #endif
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/config.hpp>
|
Chris@16
|
16 #include <boost/exception/get_error_info.hpp>
|
Chris@16
|
17 #include <boost/exception/info.hpp>
|
Chris@16
|
18 #include <boost/utility/enable_if.hpp>
|
Chris@101
|
19 #ifndef BOOST_NO_RTTI
|
Chris@101
|
20 #include <boost/core/demangle.hpp>
|
Chris@101
|
21 #endif
|
Chris@16
|
22 #include <exception>
|
Chris@16
|
23 #include <sstream>
|
Chris@16
|
24 #include <string>
|
Chris@16
|
25
|
Chris@16
|
26 #ifndef BOOST_NO_EXCEPTIONS
|
Chris@16
|
27 #include <boost/exception/current_exception_cast.hpp>
|
Chris@16
|
28 namespace
|
Chris@16
|
29 boost
|
Chris@16
|
30 {
|
Chris@16
|
31 namespace
|
Chris@16
|
32 exception_detail
|
Chris@16
|
33 {
|
Chris@16
|
34 std::string diagnostic_information_impl( boost::exception const *, std::exception const *, bool, bool );
|
Chris@16
|
35 }
|
Chris@16
|
36
|
Chris@16
|
37 inline
|
Chris@16
|
38 std::string
|
Chris@16
|
39 current_exception_diagnostic_information( bool verbose=true)
|
Chris@16
|
40 {
|
Chris@16
|
41 boost::exception const * be=current_exception_cast<boost::exception const>();
|
Chris@16
|
42 std::exception const * se=current_exception_cast<std::exception const>();
|
Chris@16
|
43 if( be || se )
|
Chris@16
|
44 return exception_detail::diagnostic_information_impl(be,se,true,verbose);
|
Chris@16
|
45 else
|
Chris@16
|
46 return "No diagnostic information available.";
|
Chris@16
|
47 }
|
Chris@16
|
48 }
|
Chris@16
|
49 #endif
|
Chris@16
|
50
|
Chris@16
|
51 namespace
|
Chris@16
|
52 boost
|
Chris@16
|
53 {
|
Chris@16
|
54 namespace
|
Chris@16
|
55 exception_detail
|
Chris@16
|
56 {
|
Chris@16
|
57 inline
|
Chris@16
|
58 exception const *
|
Chris@16
|
59 get_boost_exception( exception const * e )
|
Chris@16
|
60 {
|
Chris@16
|
61 return e;
|
Chris@16
|
62 }
|
Chris@16
|
63
|
Chris@16
|
64 inline
|
Chris@16
|
65 exception const *
|
Chris@16
|
66 get_boost_exception( ... )
|
Chris@16
|
67 {
|
Chris@16
|
68 return 0;
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 inline
|
Chris@16
|
72 std::exception const *
|
Chris@16
|
73 get_std_exception( std::exception const * e )
|
Chris@16
|
74 {
|
Chris@16
|
75 return e;
|
Chris@16
|
76 }
|
Chris@16
|
77
|
Chris@16
|
78 inline
|
Chris@16
|
79 std::exception const *
|
Chris@16
|
80 get_std_exception( ... )
|
Chris@16
|
81 {
|
Chris@16
|
82 return 0;
|
Chris@16
|
83 }
|
Chris@16
|
84
|
Chris@16
|
85 inline
|
Chris@16
|
86 char const *
|
Chris@16
|
87 get_diagnostic_information( exception const & x, char const * header )
|
Chris@16
|
88 {
|
Chris@16
|
89 #ifndef BOOST_NO_EXCEPTIONS
|
Chris@16
|
90 try
|
Chris@16
|
91 {
|
Chris@16
|
92 #endif
|
Chris@16
|
93 error_info_container * c=x.data_.get();
|
Chris@16
|
94 if( !c )
|
Chris@16
|
95 x.data_.adopt(c=new exception_detail::error_info_container_impl);
|
Chris@16
|
96 char const * di=c->diagnostic_information(header);
|
Chris@16
|
97 BOOST_ASSERT(di!=0);
|
Chris@16
|
98 return di;
|
Chris@16
|
99 #ifndef BOOST_NO_EXCEPTIONS
|
Chris@16
|
100 }
|
Chris@16
|
101 catch(...)
|
Chris@16
|
102 {
|
Chris@16
|
103 return 0;
|
Chris@16
|
104 }
|
Chris@16
|
105 #endif
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 inline
|
Chris@16
|
109 std::string
|
Chris@16
|
110 diagnostic_information_impl( boost::exception const * be, std::exception const * se, bool with_what, bool verbose )
|
Chris@16
|
111 {
|
Chris@16
|
112 if( !be && !se )
|
Chris@16
|
113 return "Unknown exception.";
|
Chris@16
|
114 #ifndef BOOST_NO_RTTI
|
Chris@16
|
115 if( !be )
|
Chris@16
|
116 be=dynamic_cast<boost::exception const *>(se);
|
Chris@16
|
117 if( !se )
|
Chris@16
|
118 se=dynamic_cast<std::exception const *>(be);
|
Chris@16
|
119 #endif
|
Chris@16
|
120 char const * wh=0;
|
Chris@16
|
121 if( with_what && se )
|
Chris@16
|
122 {
|
Chris@16
|
123 wh=se->what();
|
Chris@16
|
124 if( be && exception_detail::get_diagnostic_information(*be,0)==wh )
|
Chris@16
|
125 return wh;
|
Chris@16
|
126 }
|
Chris@16
|
127 std::ostringstream tmp;
|
Chris@16
|
128 if( be && verbose )
|
Chris@16
|
129 {
|
Chris@16
|
130 char const * const * f=get_error_info<throw_file>(*be);
|
Chris@16
|
131 int const * l=get_error_info<throw_line>(*be);
|
Chris@16
|
132 char const * const * fn=get_error_info<throw_function>(*be);
|
Chris@16
|
133 if( !f && !l && !fn )
|
Chris@16
|
134 tmp << "Throw location unknown (consider using BOOST_THROW_EXCEPTION)\n";
|
Chris@16
|
135 else
|
Chris@16
|
136 {
|
Chris@16
|
137 if( f )
|
Chris@16
|
138 {
|
Chris@16
|
139 tmp << *f;
|
Chris@16
|
140 if( int const * l=get_error_info<throw_line>(*be) )
|
Chris@16
|
141 tmp << '(' << *l << "): ";
|
Chris@16
|
142 }
|
Chris@16
|
143 tmp << "Throw in function ";
|
Chris@16
|
144 if( char const * const * fn=get_error_info<throw_function>(*be) )
|
Chris@16
|
145 tmp << *fn;
|
Chris@16
|
146 else
|
Chris@16
|
147 tmp << "(unknown)";
|
Chris@16
|
148 tmp << '\n';
|
Chris@16
|
149 }
|
Chris@16
|
150 }
|
Chris@16
|
151 #ifndef BOOST_NO_RTTI
|
Chris@16
|
152 if ( verbose )
|
Chris@16
|
153 tmp << std::string("Dynamic exception type: ") <<
|
Chris@101
|
154 core::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n';
|
Chris@16
|
155 #endif
|
Chris@16
|
156 if( with_what && se && verbose )
|
Chris@16
|
157 tmp << "std::exception::what: " << wh << '\n';
|
Chris@16
|
158 if( be )
|
Chris@16
|
159 if( char const * s=exception_detail::get_diagnostic_information(*be,tmp.str().c_str()) )
|
Chris@16
|
160 if( *s )
|
Chris@16
|
161 return std::string(s);
|
Chris@16
|
162 return tmp.str();
|
Chris@16
|
163 }
|
Chris@16
|
164 }
|
Chris@16
|
165
|
Chris@16
|
166 template <class T>
|
Chris@16
|
167 std::string
|
Chris@16
|
168 diagnostic_information( T const & e, bool verbose=true )
|
Chris@16
|
169 {
|
Chris@16
|
170 return exception_detail::diagnostic_information_impl(exception_detail::get_boost_exception(&e),exception_detail::get_std_exception(&e),true,verbose);
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@16
|
173 inline
|
Chris@16
|
174 char const *
|
Chris@16
|
175 diagnostic_information_what( exception const & e, bool verbose=true ) throw()
|
Chris@16
|
176 {
|
Chris@16
|
177 char const * w=0;
|
Chris@16
|
178 #ifndef BOOST_NO_EXCEPTIONS
|
Chris@16
|
179 try
|
Chris@16
|
180 {
|
Chris@16
|
181 #endif
|
Chris@16
|
182 (void) exception_detail::diagnostic_information_impl(&e,0,false,verbose);
|
Chris@16
|
183 if( char const * di=exception_detail::get_diagnostic_information(e,0) )
|
Chris@16
|
184 return di;
|
Chris@16
|
185 else
|
Chris@16
|
186 return "Failed to produce boost::diagnostic_information_what()";
|
Chris@16
|
187 #ifndef BOOST_NO_EXCEPTIONS
|
Chris@16
|
188 }
|
Chris@16
|
189 catch(
|
Chris@16
|
190 ... )
|
Chris@16
|
191 {
|
Chris@16
|
192 }
|
Chris@16
|
193 #endif
|
Chris@16
|
194 return w;
|
Chris@16
|
195 }
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
|
Chris@16
|
199 #pragma warning(pop)
|
Chris@16
|
200 #endif
|
Chris@16
|
201 #endif
|