1 | //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. |
---|
2 | |
---|
3 | //Distributed under the Boost Software License, Version 1.0. (See accompanying |
---|
4 | //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
---|
5 | |
---|
6 | #ifndef UUID_274DA366004E11DCB1DDFE2E56D89593 |
---|
7 | #define UUID_274DA366004E11DCB1DDFE2E56D89593 |
---|
8 | #if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
---|
9 | #pragma GCC system_header |
---|
10 | #endif |
---|
11 | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
---|
12 | #pragma warning(push,1) |
---|
13 | #endif |
---|
14 | |
---|
15 | namespace |
---|
16 | boost |
---|
17 | { |
---|
18 | namespace |
---|
19 | exception_detail |
---|
20 | { |
---|
21 | template <class T> |
---|
22 | class |
---|
23 | refcount_ptr |
---|
24 | { |
---|
25 | public: |
---|
26 | |
---|
27 | refcount_ptr(): |
---|
28 | px_(0) |
---|
29 | { |
---|
30 | } |
---|
31 | |
---|
32 | ~refcount_ptr() |
---|
33 | { |
---|
34 | release(); |
---|
35 | } |
---|
36 | |
---|
37 | refcount_ptr( refcount_ptr const & x ): |
---|
38 | px_(x.px_) |
---|
39 | { |
---|
40 | add_ref(); |
---|
41 | } |
---|
42 | |
---|
43 | refcount_ptr & |
---|
44 | operator=( refcount_ptr const & x ) |
---|
45 | { |
---|
46 | adopt(x.px_); |
---|
47 | return *this; |
---|
48 | } |
---|
49 | |
---|
50 | void |
---|
51 | adopt( T * px ) |
---|
52 | { |
---|
53 | release(); |
---|
54 | px_=px; |
---|
55 | add_ref(); |
---|
56 | } |
---|
57 | |
---|
58 | T * |
---|
59 | get() const |
---|
60 | { |
---|
61 | return px_; |
---|
62 | } |
---|
63 | |
---|
64 | private: |
---|
65 | |
---|
66 | T * px_; |
---|
67 | |
---|
68 | void |
---|
69 | add_ref() |
---|
70 | { |
---|
71 | if( px_ ) |
---|
72 | px_->add_ref(); |
---|
73 | } |
---|
74 | |
---|
75 | void |
---|
76 | release() |
---|
77 | { |
---|
78 | if( px_ && px_->release() ) |
---|
79 | px_=0; |
---|
80 | } |
---|
81 | }; |
---|
82 | } |
---|
83 | |
---|
84 | //////////////////////////////////////////////////////////////////////// |
---|
85 | |
---|
86 | template <class Tag,class T> |
---|
87 | class error_info; |
---|
88 | |
---|
89 | typedef error_info<struct throw_function_,char const *> throw_function; |
---|
90 | typedef error_info<struct throw_file_,char const *> throw_file; |
---|
91 | typedef error_info<struct throw_line_,int> throw_line; |
---|
92 | |
---|
93 | template <> |
---|
94 | class |
---|
95 | error_info<throw_function_,char const *> |
---|
96 | { |
---|
97 | public: |
---|
98 | typedef char const * value_type; |
---|
99 | value_type v_; |
---|
100 | explicit |
---|
101 | error_info( value_type v ): |
---|
102 | v_(v) |
---|
103 | { |
---|
104 | } |
---|
105 | }; |
---|
106 | |
---|
107 | template <> |
---|
108 | class |
---|
109 | error_info<throw_file_,char const *> |
---|
110 | { |
---|
111 | public: |
---|
112 | typedef char const * value_type; |
---|
113 | value_type v_; |
---|
114 | explicit |
---|
115 | error_info( value_type v ): |
---|
116 | v_(v) |
---|
117 | { |
---|
118 | } |
---|
119 | }; |
---|
120 | |
---|
121 | template <> |
---|
122 | class |
---|
123 | error_info<throw_line_,int> |
---|
124 | { |
---|
125 | public: |
---|
126 | typedef int value_type; |
---|
127 | value_type v_; |
---|
128 | explicit |
---|
129 | error_info( value_type v ): |
---|
130 | v_(v) |
---|
131 | { |
---|
132 | } |
---|
133 | }; |
---|
134 | |
---|
135 | class exception; |
---|
136 | |
---|
137 | template <class T> |
---|
138 | class shared_ptr; |
---|
139 | |
---|
140 | namespace |
---|
141 | exception_detail |
---|
142 | { |
---|
143 | class error_info_base; |
---|
144 | struct type_info_; |
---|
145 | |
---|
146 | struct |
---|
147 | error_info_container |
---|
148 | { |
---|
149 | virtual char const * diagnostic_information( char const * ) const = 0; |
---|
150 | virtual shared_ptr<error_info_base> get( type_info_ const & ) const = 0; |
---|
151 | virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0; |
---|
152 | virtual void add_ref() const = 0; |
---|
153 | virtual bool release() const = 0; |
---|
154 | virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0; |
---|
155 | |
---|
156 | protected: |
---|
157 | |
---|
158 | ~error_info_container() throw() |
---|
159 | { |
---|
160 | } |
---|
161 | }; |
---|
162 | |
---|
163 | template <class> |
---|
164 | struct get_info; |
---|
165 | |
---|
166 | template <> |
---|
167 | struct get_info<throw_function>; |
---|
168 | |
---|
169 | template <> |
---|
170 | struct get_info<throw_file>; |
---|
171 | |
---|
172 | template <> |
---|
173 | struct get_info<throw_line>; |
---|
174 | |
---|
175 | char const * get_diagnostic_information( exception const &, char const * ); |
---|
176 | |
---|
177 | void copy_boost_exception( exception *, exception const * ); |
---|
178 | |
---|
179 | template <class E,class Tag,class T> |
---|
180 | E const & set_info( E const &, error_info<Tag,T> const & ); |
---|
181 | |
---|
182 | template <class E> |
---|
183 | E const & set_info( E const &, throw_function const & ); |
---|
184 | |
---|
185 | template <class E> |
---|
186 | E const & set_info( E const &, throw_file const & ); |
---|
187 | |
---|
188 | template <class E> |
---|
189 | E const & set_info( E const &, throw_line const & ); |
---|
190 | } |
---|
191 | |
---|
192 | class |
---|
193 | exception |
---|
194 | { |
---|
195 | protected: |
---|
196 | |
---|
197 | exception(): |
---|
198 | throw_function_(0), |
---|
199 | throw_file_(0), |
---|
200 | throw_line_(-1) |
---|
201 | { |
---|
202 | } |
---|
203 | |
---|
204 | #ifdef __HP_aCC |
---|
205 | //On HP aCC, this protected copy constructor prevents throwing boost::exception. |
---|
206 | //On all other platforms, the same effect is achieved by the pure virtual destructor. |
---|
207 | exception( exception const & x ) throw(): |
---|
208 | data_(x.data_), |
---|
209 | throw_function_(x.throw_function_), |
---|
210 | throw_file_(x.throw_file_), |
---|
211 | throw_line_(x.throw_line_) |
---|
212 | { |
---|
213 | } |
---|
214 | #endif |
---|
215 | |
---|
216 | virtual ~exception() throw() |
---|
217 | #ifndef __HP_aCC |
---|
218 | = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors. |
---|
219 | #endif |
---|
220 | ; |
---|
221 | |
---|
222 | #if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310) |
---|
223 | public: |
---|
224 | #else |
---|
225 | private: |
---|
226 | |
---|
227 | template <class E> |
---|
228 | friend E const & exception_detail::set_info( E const &, throw_function const & ); |
---|
229 | |
---|
230 | template <class E> |
---|
231 | friend E const & exception_detail::set_info( E const &, throw_file const & ); |
---|
232 | |
---|
233 | template <class E> |
---|
234 | friend E const & exception_detail::set_info( E const &, throw_line const & ); |
---|
235 | |
---|
236 | template <class E,class Tag,class T> |
---|
237 | friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & ); |
---|
238 | |
---|
239 | friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); |
---|
240 | |
---|
241 | template <class> |
---|
242 | friend struct exception_detail::get_info; |
---|
243 | friend struct exception_detail::get_info<throw_function>; |
---|
244 | friend struct exception_detail::get_info<throw_file>; |
---|
245 | friend struct exception_detail::get_info<throw_line>; |
---|
246 | friend void exception_detail::copy_boost_exception( exception *, exception const * ); |
---|
247 | #endif |
---|
248 | mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_; |
---|
249 | mutable char const * throw_function_; |
---|
250 | mutable char const * throw_file_; |
---|
251 | mutable int throw_line_; |
---|
252 | }; |
---|
253 | |
---|
254 | inline |
---|
255 | exception:: |
---|
256 | ~exception() throw() |
---|
257 | { |
---|
258 | } |
---|
259 | |
---|
260 | namespace |
---|
261 | exception_detail |
---|
262 | { |
---|
263 | template <class E> |
---|
264 | E const & |
---|
265 | set_info( E const & x, throw_function const & y ) |
---|
266 | { |
---|
267 | x.throw_function_=y.v_; |
---|
268 | return x; |
---|
269 | } |
---|
270 | |
---|
271 | template <class E> |
---|
272 | E const & |
---|
273 | set_info( E const & x, throw_file const & y ) |
---|
274 | { |
---|
275 | x.throw_file_=y.v_; |
---|
276 | return x; |
---|
277 | } |
---|
278 | |
---|
279 | template <class E> |
---|
280 | E const & |
---|
281 | set_info( E const & x, throw_line const & y ) |
---|
282 | { |
---|
283 | x.throw_line_=y.v_; |
---|
284 | return x; |
---|
285 | } |
---|
286 | } |
---|
287 | |
---|
288 | //////////////////////////////////////////////////////////////////////// |
---|
289 | |
---|
290 | namespace |
---|
291 | exception_detail |
---|
292 | { |
---|
293 | template <class T> |
---|
294 | struct |
---|
295 | error_info_injector: |
---|
296 | public T, |
---|
297 | public exception |
---|
298 | { |
---|
299 | explicit |
---|
300 | error_info_injector( T const & x ): |
---|
301 | T(x) |
---|
302 | { |
---|
303 | } |
---|
304 | |
---|
305 | ~error_info_injector() throw() |
---|
306 | { |
---|
307 | } |
---|
308 | }; |
---|
309 | |
---|
310 | struct large_size { char c[256]; }; |
---|
311 | large_size dispatch_boost_exception( exception const * ); |
---|
312 | |
---|
313 | struct small_size { }; |
---|
314 | small_size dispatch_boost_exception( void const * ); |
---|
315 | |
---|
316 | template <class,int> |
---|
317 | struct enable_error_info_helper; |
---|
318 | |
---|
319 | template <class T> |
---|
320 | struct |
---|
321 | enable_error_info_helper<T,sizeof(large_size)> |
---|
322 | { |
---|
323 | typedef T type; |
---|
324 | }; |
---|
325 | |
---|
326 | template <class T> |
---|
327 | struct |
---|
328 | enable_error_info_helper<T,sizeof(small_size)> |
---|
329 | { |
---|
330 | typedef error_info_injector<T> type; |
---|
331 | }; |
---|
332 | |
---|
333 | template <class T> |
---|
334 | struct |
---|
335 | enable_error_info_return_type |
---|
336 | { |
---|
337 | typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception((T*)0))>::type type; |
---|
338 | }; |
---|
339 | } |
---|
340 | |
---|
341 | template <class T> |
---|
342 | inline |
---|
343 | typename |
---|
344 | exception_detail::enable_error_info_return_type<T>::type |
---|
345 | enable_error_info( T const & x ) |
---|
346 | { |
---|
347 | typedef typename exception_detail::enable_error_info_return_type<T>::type rt; |
---|
348 | return rt(x); |
---|
349 | } |
---|
350 | |
---|
351 | //////////////////////////////////////////////////////////////////////// |
---|
352 | |
---|
353 | namespace |
---|
354 | exception_detail |
---|
355 | { |
---|
356 | class |
---|
357 | clone_base |
---|
358 | { |
---|
359 | public: |
---|
360 | |
---|
361 | virtual clone_base const * clone() const = 0; |
---|
362 | virtual void rethrow() const = 0; |
---|
363 | |
---|
364 | virtual |
---|
365 | ~clone_base() throw() |
---|
366 | { |
---|
367 | } |
---|
368 | }; |
---|
369 | |
---|
370 | inline |
---|
371 | void |
---|
372 | copy_boost_exception( exception * a, exception const * b ) |
---|
373 | { |
---|
374 | refcount_ptr<error_info_container> data; |
---|
375 | if( error_info_container * d=b->data_.get() ) |
---|
376 | data = d->clone(); |
---|
377 | a->throw_file_ = b->throw_file_; |
---|
378 | a->throw_line_ = b->throw_line_; |
---|
379 | a->throw_function_ = b->throw_function_; |
---|
380 | a->data_ = data; |
---|
381 | } |
---|
382 | |
---|
383 | inline |
---|
384 | void |
---|
385 | copy_boost_exception( void *, void const * ) |
---|
386 | { |
---|
387 | } |
---|
388 | |
---|
389 | template <class T> |
---|
390 | class |
---|
391 | clone_impl: |
---|
392 | public T, |
---|
393 | public clone_base |
---|
394 | { |
---|
395 | public: |
---|
396 | |
---|
397 | explicit |
---|
398 | clone_impl( T const & x ): |
---|
399 | T(x) |
---|
400 | { |
---|
401 | copy_boost_exception(this,&x); |
---|
402 | } |
---|
403 | |
---|
404 | ~clone_impl() throw() |
---|
405 | { |
---|
406 | } |
---|
407 | |
---|
408 | private: |
---|
409 | |
---|
410 | clone_base const * |
---|
411 | clone() const |
---|
412 | { |
---|
413 | return new clone_impl(*this); |
---|
414 | } |
---|
415 | |
---|
416 | void |
---|
417 | rethrow() const |
---|
418 | { |
---|
419 | throw*this; |
---|
420 | } |
---|
421 | }; |
---|
422 | } |
---|
423 | |
---|
424 | template <class T> |
---|
425 | inline |
---|
426 | exception_detail::clone_impl<T> |
---|
427 | enable_current_exception( T const & x ) |
---|
428 | { |
---|
429 | return exception_detail::clone_impl<T>(x); |
---|
430 | } |
---|
431 | } |
---|
432 | |
---|
433 | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
---|
434 | #pragma warning(pop) |
---|
435 | #endif |
---|
436 | #endif |
---|