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 | |
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 | |