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