]> git.lyx.org Git - features.git/blob - boost/boost/exception/detail/exception_ptr.hpp
boost: update to 1.42.0
[features.git] / boost / boost / exception / detail / exception_ptr.hpp
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_618474C2DE1511DEB74A388C56D89593
7 #define UUID_618474C2DE1511DEB74A388C56D89593
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 #include <boost/config.hpp>
16 #ifdef BOOST_NO_EXCEPTIONS
17 #error This header requires exception handling to be enabled.
18 #endif
19 #include <boost/exception/exception.hpp>
20 #include <boost/exception/info.hpp>
21 #include <boost/exception/diagnostic_information.hpp>
22 #include <boost/exception/detail/type_info.hpp>
23 #include <boost/shared_ptr.hpp>
24 #include <stdexcept>
25 #include <new>
26 #include <ios>
27
28 namespace
29 boost
30     {
31 #ifndef BOOST_NO_RTTI
32     typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type;
33
34     inline
35     std::string
36     to_string( original_exception_type const & x )
37         {
38         return x.value()->name();
39         }
40 #endif
41
42     class exception_ptr;
43     exception_ptr current_exception();
44     void rethrow_exception( exception_ptr const & );
45
46     class
47     exception_ptr
48         {
49         typedef bool exception_ptr::*unspecified_bool_type;
50         friend exception_ptr current_exception();
51         friend void rethrow_exception( exception_ptr const & );
52
53         shared_ptr<exception_detail::clone_base const> c_;
54         bool bad_alloc_;
55
56         struct
57         bad_alloc_tag
58             {
59             };
60
61         explicit
62         exception_ptr( bad_alloc_tag ):
63             bad_alloc_(true)
64             {
65             }
66
67         explicit
68         exception_ptr( shared_ptr<exception_detail::clone_base const> const & c ):
69             c_(c),
70             bad_alloc_(false)
71             {
72             BOOST_ASSERT(c);
73             }
74
75         void
76         rethrow() const
77             {
78             BOOST_ASSERT(*this);
79             if( bad_alloc_ )
80                 throw enable_current_exception(std::bad_alloc());
81             else
82                 c_->rethrow();
83             }
84
85         bool
86         empty() const
87             {
88             return !bad_alloc_ && !c_;
89             }
90
91         public:
92
93         exception_ptr():
94             bad_alloc_(false)
95             {
96             }
97
98         ~exception_ptr() throw()
99             {
100             }
101
102         operator unspecified_bool_type() const
103             {
104             return empty() ? 0 : &exception_ptr::bad_alloc_;
105             }
106
107         friend
108         bool
109         operator==( exception_ptr const & a, exception_ptr const & b )
110             {
111             return a.c_==b.c_ && a.bad_alloc_==b.bad_alloc_;
112             }
113
114         friend
115         bool
116         operator!=( exception_ptr const & a, exception_ptr const & b )
117             {
118             return !(a==b);
119             }
120         };
121
122     class
123     unknown_exception:
124         public exception,
125         public std::exception,
126         public exception_detail::clone_base
127         {
128         public:
129
130         unknown_exception()
131             {
132             }
133
134         explicit
135         unknown_exception( std::exception const & e )
136             {
137             add_original_type(e);
138             }
139
140         explicit
141         unknown_exception( boost::exception const & e ):
142             boost::exception(e)
143             {
144             add_original_type(e);
145             }
146
147         ~unknown_exception() throw()
148             {
149             }
150
151         private:
152
153         exception_detail::clone_base const *
154         clone() const
155             {
156             return new unknown_exception(*this);
157             }
158
159         void
160         rethrow() const
161             {
162             throw*this;
163             }
164
165         template <class E>
166         void
167         add_original_type( E const & e )
168             {
169 #ifndef BOOST_NO_RTTI
170             (*this) << original_exception_type(&typeid(e));
171 #endif
172             }
173         };
174
175     namespace
176     exception_detail
177         {
178         template <class T>
179         class
180         current_exception_std_exception_wrapper:
181             public T,
182             public boost::exception,
183             public clone_base
184             {
185             public:
186
187             explicit
188             current_exception_std_exception_wrapper( T const & e1 ):
189                 T(e1)
190                 {
191                 add_original_type(e1);
192                 }
193
194             current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ):
195                 T(e1),
196                 boost::exception(e2)
197                 {
198                 add_original_type(e1);
199                 }
200
201             ~current_exception_std_exception_wrapper() throw()
202                 {
203                 }
204
205             private:
206
207             clone_base const *
208             clone() const
209                 {
210                 return new current_exception_std_exception_wrapper(*this);
211                 }
212
213             void
214             rethrow() const
215                 {
216                 throw *this;
217                 }
218
219             template <class E>
220             void
221             add_original_type( E const & e )
222                 {
223 #ifndef BOOST_NO_RTTI
224                 (*this) << original_exception_type(&typeid(e));
225 #endif
226                 }
227             };
228
229 #ifdef BOOST_NO_RTTI
230         template <class T>
231         exception const *
232         get_boost_exception( T const * )
233             {
234             try
235                 {
236                 throw;
237                 }
238             catch(
239             exception & x )
240                 {
241                 return &x;
242                 }
243             catch(...)
244                 {
245                 return 0;
246                 }
247             }
248 #else
249         template <class T>
250         exception const *
251         get_boost_exception( T const * x )
252             {
253             return dynamic_cast<exception const *>(x);
254             }
255 #endif
256
257         template <class T>
258         inline
259         shared_ptr<clone_base const>
260         current_exception_std_exception( T const & e1 )
261             {
262             if( boost::exception const * e2 = get_boost_exception(&e1) )
263                 return shared_ptr<current_exception_std_exception_wrapper<T> const>(new current_exception_std_exception_wrapper<T>(e1,*e2));
264             else
265                 return shared_ptr<current_exception_std_exception_wrapper<T> const>(new current_exception_std_exception_wrapper<T>(e1));
266             }
267
268         inline
269         shared_ptr<clone_base const>
270         current_exception_unknown_exception()
271             {
272             return shared_ptr<unknown_exception const>(new unknown_exception());
273             }
274
275         inline
276         shared_ptr<clone_base const>
277         current_exception_unknown_boost_exception( boost::exception const & e )
278             {
279             return shared_ptr<unknown_exception const>(new unknown_exception(e));
280             }
281
282         inline
283         shared_ptr<clone_base const>
284         current_exception_unknown_std_exception( std::exception const & e )
285             {
286             if( boost::exception const * be = get_boost_exception(&e) )
287                 return current_exception_unknown_boost_exception(*be);
288             else
289                 return shared_ptr<unknown_exception const>(new unknown_exception(e));
290             }
291
292         inline
293         shared_ptr<clone_base const>
294         current_exception_impl()
295             {
296             try
297                 {
298                 throw;
299                 }
300             catch(
301             exception_detail::clone_base & e )
302                 {
303                 return shared_ptr<exception_detail::clone_base const>(e.clone());
304                 }
305             catch(
306             std::domain_error & e )
307                 {
308                 return exception_detail::current_exception_std_exception(e);
309                 }
310             catch(
311             std::invalid_argument & e )
312                 {
313                 return exception_detail::current_exception_std_exception(e);
314                 }
315             catch(
316             std::length_error & e )
317                 {
318                 return exception_detail::current_exception_std_exception(e);
319                 }
320             catch(
321             std::out_of_range & e )
322                 {
323                 return exception_detail::current_exception_std_exception(e);
324                 }
325             catch(
326             std::logic_error & e )
327                 {
328                 return exception_detail::current_exception_std_exception(e);
329                 }
330             catch(
331             std::range_error & e )
332                 {
333                 return exception_detail::current_exception_std_exception(e);
334                 }
335             catch(
336             std::overflow_error & e )
337                 {
338                 return exception_detail::current_exception_std_exception(e);
339                 }
340             catch(
341             std::underflow_error & e )
342                 {
343                 return exception_detail::current_exception_std_exception(e);
344                 }
345             catch(
346             std::ios_base::failure & e )
347                 {
348                 return exception_detail::current_exception_std_exception(e);
349                 }
350             catch(
351             std::runtime_error & e )
352                 {
353                 return exception_detail::current_exception_std_exception(e);
354                 }
355             catch(
356             std::bad_alloc & e )
357                 {
358                 return exception_detail::current_exception_std_exception(e);
359                 }
360 #ifndef BOOST_NO_TYPEID
361             catch(
362             std::bad_cast & e )
363                 {
364                 return exception_detail::current_exception_std_exception(e);
365                 }
366             catch(
367             std::bad_typeid & e )
368                 {
369                 return exception_detail::current_exception_std_exception(e);
370                 }
371 #endif
372             catch(
373             std::bad_exception & e )
374                 {
375                 return exception_detail::current_exception_std_exception(e);
376                 }
377             catch(
378             std::exception & e )
379                 {
380                 return exception_detail::current_exception_unknown_std_exception(e);
381                 }
382             catch(
383             boost::exception & e )
384                 {
385                 return exception_detail::current_exception_unknown_boost_exception(e);
386                 }
387             catch(
388             ... )
389                 {
390                 return exception_detail::current_exception_unknown_exception();
391                 }
392             }
393         }
394
395     inline
396     exception_ptr
397     current_exception()
398         {
399         try
400             {
401             return exception_ptr(exception_detail::current_exception_impl());
402             }
403         catch(
404         std::bad_alloc & )
405             {
406             }
407         catch(
408         ... )
409             {
410             try
411                 {
412                 return exception_ptr(exception_detail::current_exception_std_exception(std::bad_exception()));
413                 }
414             catch(
415             std::bad_alloc & )
416                 {
417                 }
418             catch(
419             ... )
420                 {
421                 BOOST_ASSERT(0);
422                 }
423             }
424         return exception_ptr(exception_ptr::bad_alloc_tag());
425         }
426
427     template <class T>
428     inline
429     exception_ptr
430     copy_exception( T const & e )
431         {
432         try
433             {
434             throw enable_current_exception(e);
435             }
436         catch(
437         ... )
438             {
439             return current_exception();
440             }
441         }
442
443     inline
444     void
445     rethrow_exception( exception_ptr const & p )
446         {
447         p.rethrow();
448         }
449
450     inline
451     std::string
452     diagnostic_information( exception_ptr const & p )
453         {
454         if( p )
455             try
456                 {
457                 rethrow_exception(p);
458                 }
459             catch(
460             ... )
461                 {
462                 return current_exception_diagnostic_information();
463                 }
464         return "<empty>";
465         }
466
467     inline
468     std::string
469     to_string( exception_ptr const & p )
470         {
471         std::string s='\n'+diagnostic_information(p);
472         std::string padding("  ");
473         std::string r;
474         bool f=false;
475         for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i )
476             {
477             if( f )
478                 r+=padding;
479             char c=*i;
480             r+=c;
481             f=(c=='\n');
482             }
483         return r;
484         }
485     }
486
487 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
488 #pragma warning(pop)
489 #endif
490 #endif