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
15namespace
16boost
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#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
168 ~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
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.
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::
282 ~exception() throw()
283 {
284 }
285
286 namespace
287 exception_detail
288 {
289 template <class E>
290 E const &
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 &
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 &
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
331 error_info_injector( T const & x ):
332 T(x)
333 {
334 }
335
336 ~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
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
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
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
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 { };
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
451 clone_impl( T const & x ):
452 T(x)
453 {
454 copy_boost_exception(this,&x);
455 }
456
457 ~clone_impl() throw()
458 {
459 }
460
461 private:
462
463 clone_base const *
464 clone() const
465 {
466 return new clone_impl(*this,clone_tag());
467 }
468
469 void
470 rethrow() const
471 {
472 throw*this;
473 }
474 };
475 }
476
477 template <class T>
478 inline
479 exception_detail::clone_impl<T>
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