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 (__GNUC__*100+__GNUC_MINOR__>301) && !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 #ifdef BOOST_EXCEPTION_MINI_BOOST
16 #include  <memory>
17 namespace boost { namespace exception_detail { using std::shared_ptr; } }
18 #else
19 namespace boost { template <class T> class shared_ptr; };
20 namespace boost { namespace exception_detail { using boost::shared_ptr; } }
21 #endif
22 
23 namespace
24 boost
25     {
26     namespace
27     exception_detail
28         {
29         template <class T>
30         class
31         refcount_ptr
32             {
33             public:
34 
refcount_ptr()35             refcount_ptr():
36                 px_(0)
37                 {
38                 }
39 
~refcount_ptr()40             ~refcount_ptr()
41                 {
42                 release();
43                 }
44 
refcount_ptr(refcount_ptr const & x)45             refcount_ptr( refcount_ptr const & x ):
46                 px_(x.px_)
47                 {
48                 add_ref();
49                 }
50 
51             refcount_ptr &
operator =(refcount_ptr const & x)52             operator=( refcount_ptr const & x )
53                 {
54                 adopt(x.px_);
55                 return *this;
56                 }
57 
58             void
adopt(T * px)59             adopt( T * px )
60                 {
61                 release();
62                 px_=px;
63                 add_ref();
64                 }
65 
66             T *
get() const67             get() const
68                 {
69                 return px_;
70                 }
71 
72             private:
73 
74             T * px_;
75 
76             void
add_ref()77             add_ref()
78                 {
79                 if( px_ )
80                     px_->add_ref();
81                 }
82 
83             void
release()84             release()
85                 {
86                 if( px_ && px_->release() )
87                     px_=0;
88                 }
89             };
90         }
91 
92     ////////////////////////////////////////////////////////////////////////
93 
94     template <class Tag,class T>
95     class error_info;
96 
97     typedef error_info<struct throw_function_,char const *> throw_function;
98     typedef error_info<struct throw_file_,char const *> throw_file;
99     typedef error_info<struct throw_line_,int> throw_line;
100 
101     template <>
102     class
103     error_info<throw_function_,char const *>
104         {
105         public:
106         typedef char const * value_type;
107         value_type v_;
108         explicit
error_info(value_type v)109         error_info( value_type v ):
110             v_(v)
111             {
112             }
113         };
114 
115     template <>
116     class
117     error_info<throw_file_,char const *>
118         {
119         public:
120         typedef char const * value_type;
121         value_type v_;
122         explicit
error_info(value_type v)123         error_info( value_type v ):
124             v_(v)
125             {
126             }
127         };
128 
129     template <>
130     class
131     error_info<throw_line_,int>
132         {
133         public:
134         typedef int value_type;
135         value_type v_;
136         explicit
error_info(value_type v)137         error_info( value_type v ):
138             v_(v)
139             {
140             }
141         };
142 
143 #if defined(__GNUC__)
144 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
145 #  pragma GCC visibility push (default)
146 # endif
147 #endif
148     class exception;
149 #if defined(__GNUC__)
150 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
151 #  pragma GCC visibility pop
152 # endif
153 #endif
154 
155     namespace
156     exception_detail
157         {
158         class error_info_base;
159         struct type_info_;
160 
161         struct
162         error_info_container
163             {
164             virtual char const * diagnostic_information( char const * ) const = 0;
165             virtual shared_ptr<error_info_base> get( type_info_ const & ) const = 0;
166             virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0;
167             virtual void add_ref() const = 0;
168             virtual bool release() const = 0;
169             virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0;
170 
171             protected:
172 
~error_info_containerboost::exception_detail::error_info_container173             ~error_info_container() throw()
174                 {
175                 }
176             };
177 
178         template <class>
179         struct get_info;
180 
181         template <>
182         struct get_info<throw_function>;
183 
184         template <>
185         struct get_info<throw_file>;
186 
187         template <>
188         struct get_info<throw_line>;
189 
190         template <class>
191         struct set_info_rv;
192 
193         template <>
194         struct set_info_rv<throw_function>;
195 
196         template <>
197         struct set_info_rv<throw_file>;
198 
199         template <>
200         struct set_info_rv<throw_line>;
201 
202         char const * get_diagnostic_information( exception const &, char const * );
203 
204         void copy_boost_exception( exception *, exception const * );
205 
206         template <class E,class Tag,class T>
207         E const & set_info( E const &, error_info<Tag,T> const & );
208 
209         template <class E>
210         E const & set_info( E const &, throw_function const & );
211 
212         template <class E>
213         E const & set_info( E const &, throw_file const & );
214 
215         template <class E>
216         E const & set_info( E const &, throw_line const & );
217         }
218 
219 #if defined(__GNUC__)
220 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
221 #  pragma GCC visibility push (default)
222 # endif
223 #endif
224     class
225     exception
226         {
227         //<N3757>
228         public:
229         template <class Tag> void set( typename Tag::type const & );
230         template <class Tag> typename Tag::type const * get() const;
231         //</N3757>
232 
233         protected:
234 
exception()235         exception():
236             throw_function_(0),
237             throw_file_(0),
238             throw_line_(-1)
239             {
240             }
241 
242 #ifdef __HP_aCC
243         //On HP aCC, this protected copy constructor prevents throwing boost::exception.
244         //On all other platforms, the same effect is achieved by the pure virtual destructor.
exception(exception const & x)245         exception( exception const & x ) throw():
246             data_(x.data_),
247             throw_function_(x.throw_function_),
248             throw_file_(x.throw_file_),
249             throw_line_(x.throw_line_)
250             {
251             }
252 #endif
253 
254         virtual ~exception() throw()
255 #ifndef __HP_aCC
256             = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors.
257 #endif
258             ;
259 
260 #if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310)
261         public:
262 #else
263         private:
264 
265         template <class E>
266         friend E const & exception_detail::set_info( E const &, throw_function const & );
267 
268         template <class E>
269         friend E const & exception_detail::set_info( E const &, throw_file const & );
270 
271         template <class E>
272         friend E const & exception_detail::set_info( E const &, throw_line const & );
273 
274         template <class E,class Tag,class T>
275         friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & );
276 
277         friend char const * exception_detail::get_diagnostic_information( exception const &, char const * );
278 
279         template <class>
280         friend struct exception_detail::get_info;
281         friend struct exception_detail::get_info<throw_function>;
282         friend struct exception_detail::get_info<throw_file>;
283         friend struct exception_detail::get_info<throw_line>;
284         template <class>
285         friend struct exception_detail::set_info_rv;
286         friend struct exception_detail::set_info_rv<throw_function>;
287         friend struct exception_detail::set_info_rv<throw_file>;
288         friend struct exception_detail::set_info_rv<throw_line>;
289         friend void exception_detail::copy_boost_exception( exception *, exception const * );
290 #endif
291         mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
292         mutable char const * throw_function_;
293         mutable char const * throw_file_;
294         mutable int throw_line_;
295         };
296 #if defined(__GNUC__)
297 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
298 #  pragma GCC visibility pop
299 # endif
300 #endif
301 
302     inline
303     exception::
~exception()304     ~exception() throw()
305         {
306         }
307 
308     namespace
309     exception_detail
310         {
311         template <class E>
312         E const &
set_info(E const & x,throw_function const & y)313         set_info( E const & x, throw_function const & y )
314             {
315             x.throw_function_=y.v_;
316             return x;
317             }
318 
319         template <class E>
320         E const &
set_info(E const & x,throw_file const & y)321         set_info( E const & x, throw_file const & y )
322             {
323             x.throw_file_=y.v_;
324             return x;
325             }
326 
327         template <class E>
328         E const &
set_info(E const & x,throw_line const & y)329         set_info( E const & x, throw_line const & y )
330             {
331             x.throw_line_=y.v_;
332             return x;
333             }
334         }
335 
336     ////////////////////////////////////////////////////////////////////////
337 
338     namespace
339     exception_detail
340         {
341 #if defined(__GNUC__)
342 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
343 #  pragma GCC visibility push (default)
344 # endif
345 #endif
346         template <class T>
347         struct
348         error_info_injector:
349             public T,
350             public exception
351             {
352             explicit
error_info_injectorboost::exception_detail::error_info_injector353             error_info_injector( T const & x ):
354                 T(x)
355                 {
356                 }
357 
~error_info_injectorboost::exception_detail::error_info_injector358             ~error_info_injector() throw()
359                 {
360                 }
361             };
362 #if defined(__GNUC__)
363 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
364 #  pragma GCC visibility pop
365 # endif
366 #endif
367 
368         struct large_size { char c[256]; };
369         large_size dispatch_boost_exception( exception const * );
370 
371         struct small_size { };
372         small_size dispatch_boost_exception( void const * );
373 
374         template <class,int>
375         struct enable_error_info_helper;
376 
377         template <class T>
378         struct
379         enable_error_info_helper<T,sizeof(large_size)>
380             {
381             typedef T type;
382             };
383 
384         template <class T>
385         struct
386         enable_error_info_helper<T,sizeof(small_size)>
387             {
388             typedef error_info_injector<T> type;
389             };
390 
391         template <class T>
392         struct
393         enable_error_info_return_type
394             {
395             typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception(static_cast<T *>(0)))>::type type;
396             };
397         }
398 
399     template <class T>
400     inline
401     typename
402     exception_detail::enable_error_info_return_type<T>::type
enable_error_info(T const & x)403     enable_error_info( T const & x )
404         {
405         typedef typename exception_detail::enable_error_info_return_type<T>::type rt;
406         return rt(x);
407         }
408 
409     ////////////////////////////////////////////////////////////////////////
410 
411     namespace
412     exception_detail
413         {
414 #if defined(__GNUC__)
415 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
416 #  pragma GCC visibility push (default)
417 # endif
418 #endif
419         class
420         clone_base
421             {
422             public:
423 
424             virtual clone_base const * clone() const = 0;
425             virtual void rethrow() const = 0;
426 
427             virtual
~clone_base()428             ~clone_base() throw()
429                 {
430                 }
431             };
432 #if defined(__GNUC__)
433 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
434 #  pragma GCC visibility pop
435 # endif
436 #endif
437 
438         inline
439         void
copy_boost_exception(exception * a,exception const * b)440         copy_boost_exception( exception * a, exception const * b )
441             {
442             refcount_ptr<error_info_container> data;
443             if( error_info_container * d=b->data_.get() )
444                 data = d->clone();
445             a->throw_file_ = b->throw_file_;
446             a->throw_line_ = b->throw_line_;
447             a->throw_function_ = b->throw_function_;
448             a->data_ = data;
449             }
450 
451         inline
452         void
copy_boost_exception(void *,void const *)453         copy_boost_exception( void *, void const * )
454             {
455             }
456 
457 #if defined(__GNUC__)
458 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
459 #  pragma GCC visibility push (default)
460 # endif
461 #endif
462         template <class T>
463         class
464         clone_impl:
465             public T,
466             public virtual clone_base
467             {
468             struct clone_tag { };
clone_impl(clone_impl const & x,clone_tag)469             clone_impl( clone_impl const & x, clone_tag ):
470                 T(x)
471                 {
472                 copy_boost_exception(this,&x);
473                 }
474 
475             public:
476 
477             explicit
clone_impl(T const & x)478             clone_impl( T const & x ):
479                 T(x)
480                 {
481                 copy_boost_exception(this,&x);
482                 }
483 
~clone_impl()484             ~clone_impl() throw()
485                 {
486                 }
487 
488             private:
489 
490             clone_base const *
clone() const491             clone() const
492                 {
493                 return new clone_impl(*this,clone_tag());
494                 }
495 
496             void
rethrow() const497             rethrow() const
498                 {
499                 throw*this;
500                 }
501             };
502         }
503 #if defined(__GNUC__)
504 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
505 #  pragma GCC visibility pop
506 # endif
507 #endif
508 
509     template <class T>
510     inline
511     exception_detail::clone_impl<T>
enable_current_exception(T const & x)512     enable_current_exception( T const & x )
513         {
514         return exception_detail::clone_impl<T>(x);
515         }
516     }
517 
518 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
519 #pragma warning(pop)
520 #endif
521 #endif
522