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