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>
17namespace boost { namespace exception_detail { using std::shared_ptr; } }
18#else
19namespace boost { template <class T> class shared_ptr; };
20namespace boost { namespace exception_detail { using boost::shared_ptr; } }
21#endif
22
23namespace
24boost
25 {
26 namespace
27 exception_detail
28 {
29 template <class T>
30 class
31 refcount_ptr
32 {
33 public:
34
35 refcount_ptr():
36 px_(0)
37 {
38 }
39
40 ~refcount_ptr()
41 {
42 release();
43 }
44
45 refcount_ptr( refcount_ptr const & x ):
46 px_(x.px_)
47 {
48 add_ref();
49 }
50
51 refcount_ptr &
52 operator=( refcount_ptr const & x )
53 {
54 adopt(x.px_);
55 return *this;
56 }
57
58 void
59 adopt( T * px )
60 {
61 release();
62 px_=px;
63 add_ref();
64 }
65
66 T *
67 get() const
68 {
69 return px_;
70 }
71
72 private:
73
74 T * px_;
75
76 void
77 add_ref()
78 {
79 if( px_ )
80 px_->add_ref();
81 }
82
83 void
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
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
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
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
173 ~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
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.
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::
304 ~exception() throw()
305 {
306 }
307
308 namespace
309 exception_detail
310 {
311 template <class E>
312 E const &
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 &
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 &
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
353 error_info_injector( T const & x ):
354 T(x)
355 {
356 }
357
358 ~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
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
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
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
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 { };
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
478 clone_impl( T const & x ):
479 T(x)
480 {
481 copy_boost_exception(this,&x);
482 }
483
484 ~clone_impl() throw()
485 {
486 }
487
488 private:
489
490 clone_base const *
491 clone() const
492 {
493 return new clone_impl(*this,clone_tag());
494 }
495
496 void
497 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>
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