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