|
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 namespace |
|
10 boost |
|
11 { |
|
12 namespace |
|
13 exception_detail |
|
14 { |
|
15 template <class T> |
|
16 class |
|
17 refcount_ptr |
|
18 { |
|
19 public: |
|
20 |
|
21 refcount_ptr(): |
|
22 px_(0) |
|
23 { |
|
24 } |
|
25 |
|
26 ~refcount_ptr() |
|
27 { |
|
28 release(); |
|
29 } |
|
30 |
|
31 refcount_ptr( refcount_ptr const & x ): |
|
32 px_(x.px_) |
|
33 { |
|
34 add_ref(); |
|
35 } |
|
36 |
|
37 refcount_ptr & |
|
38 operator=( refcount_ptr const & x ) |
|
39 { |
|
40 adopt(x.px_); |
|
41 return *this; |
|
42 } |
|
43 |
|
44 void |
|
45 adopt( T * px ) |
|
46 { |
|
47 release(); |
|
48 px_=px; |
|
49 add_ref(); |
|
50 } |
|
51 |
|
52 T * |
|
53 get() const |
|
54 { |
|
55 return px_; |
|
56 } |
|
57 |
|
58 private: |
|
59 |
|
60 T * px_; |
|
61 |
|
62 void |
|
63 add_ref() |
|
64 { |
|
65 if( px_ ) |
|
66 px_->add_ref(); |
|
67 } |
|
68 |
|
69 void |
|
70 release() |
|
71 { |
|
72 if( px_ ) |
|
73 px_->release(); |
|
74 } |
|
75 }; |
|
76 } |
|
77 |
|
78 //////////////////////////////////////////////////////////////////////// |
|
79 |
|
80 template <class Tag,class T> |
|
81 class error_info; |
|
82 |
|
83 typedef error_info<struct tag_throw_function,char const *> throw_function; |
|
84 typedef error_info<struct tag_throw_file,char const *> throw_file; |
|
85 typedef error_info<struct tag_throw_line,int> throw_line; |
|
86 |
|
87 template <> |
|
88 class |
|
89 error_info<tag_throw_function,char const *> |
|
90 { |
|
91 public: |
|
92 typedef char const * value_type; |
|
93 value_type v_; |
|
94 explicit |
|
95 error_info( value_type v ): |
|
96 v_(v) |
|
97 { |
|
98 } |
|
99 }; |
|
100 |
|
101 template <> |
|
102 class |
|
103 error_info<tag_throw_file,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<tag_throw_line,int> |
|
118 { |
|
119 public: |
|
120 typedef int value_type; |
|
121 value_type v_; |
|
122 explicit |
|
123 error_info( value_type v ): |
|
124 v_(v) |
|
125 { |
|
126 } |
|
127 }; |
|
128 |
|
129 template <class E,class Tag,class T> |
|
130 E const & operator<<( E const &, error_info<Tag,T> const & ); |
|
131 |
|
132 class exception; |
|
133 |
|
134 template <class> |
|
135 class shared_ptr; |
|
136 |
|
137 namespace |
|
138 exception_detail |
|
139 { |
|
140 class error_info_base; |
|
141 struct type_info_; |
|
142 |
|
143 struct |
|
144 error_info_container |
|
145 { |
|
146 virtual char const * diagnostic_information() const = 0; |
|
147 virtual shared_ptr<error_info_base const> get( type_info_ const & ) const = 0; |
|
148 virtual void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0; |
|
149 virtual void add_ref() const = 0; |
|
150 virtual void release() const = 0; |
|
151 |
|
152 protected: |
|
153 |
|
154 virtual |
|
155 ~error_info_container() throw() |
|
156 { |
|
157 } |
|
158 }; |
|
159 |
|
160 template <class> |
|
161 struct get_info; |
|
162 |
|
163 template <> |
|
164 struct get_info<throw_function>; |
|
165 |
|
166 template <> |
|
167 struct get_info<throw_file>; |
|
168 |
|
169 template <> |
|
170 struct get_info<throw_line>; |
|
171 |
|
172 char const * get_diagnostic_information( exception const & ); |
|
173 } |
|
174 |
|
175 class |
|
176 exception |
|
177 { |
|
178 protected: |
|
179 |
|
180 exception(): |
|
181 throw_function_(0), |
|
182 throw_file_(0), |
|
183 throw_line_(-1) |
|
184 { |
|
185 } |
|
186 |
|
187 #ifdef __HP_aCC |
|
188 //On HP aCC, this protected copy constructor prevents throwing boost::exception. |
|
189 //On all other platforms, the same effect is achieved by the pure virtual destructor. |
|
190 exception( exception const & x ) throw(): |
|
191 data_(x.data_), |
|
192 throw_function_(x.throw_function_), |
|
193 throw_file_(x.throw_file_), |
|
194 throw_line_(x.throw_line_) |
|
195 { |
|
196 } |
|
197 #endif |
|
198 |
|
199 virtual ~exception() throw() |
|
200 #ifndef __HP_aCC |
|
201 = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors. |
|
202 #endif |
|
203 ; |
|
204 |
|
205 private: |
|
206 |
|
207 template <class E> |
|
208 friend |
|
209 E const & |
|
210 operator<<( E const & x, throw_function const & y ) |
|
211 { |
|
212 x.throw_function_=y.v_; |
|
213 return x; |
|
214 } |
|
215 |
|
216 template <class E> |
|
217 friend |
|
218 E const & |
|
219 operator<<( E const & x, throw_file const & y ) |
|
220 { |
|
221 x.throw_file_=y.v_; |
|
222 return x; |
|
223 } |
|
224 |
|
225 template <class E> |
|
226 friend |
|
227 E const & |
|
228 operator<<( E const & x, throw_line const & y ) |
|
229 { |
|
230 x.throw_line_=y.v_; |
|
231 return x; |
|
232 } |
|
233 |
|
234 friend char const * exception_detail::get_diagnostic_information( exception const & ); |
|
235 |
|
236 template <class E,class Tag,class T> |
|
237 friend E const & operator<<( E const &, error_info<Tag,T> const & ); |
|
238 |
|
239 template <class> |
|
240 friend struct exception_detail::get_info; |
|
241 friend struct exception_detail::get_info<throw_function>; |
|
242 friend struct exception_detail::get_info<throw_file>; |
|
243 friend struct exception_detail::get_info<throw_line>; |
|
244 |
|
245 mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_; |
|
246 mutable char const * throw_function_; |
|
247 mutable char const * throw_file_; |
|
248 mutable int throw_line_; |
|
249 }; |
|
250 |
|
251 inline |
|
252 exception:: |
|
253 ~exception() throw() |
|
254 { |
|
255 } |
|
256 |
|
257 //////////////////////////////////////////////////////////////////////// |
|
258 |
|
259 namespace |
|
260 exception_detail |
|
261 { |
|
262 template <class T> |
|
263 struct |
|
264 error_info_injector: |
|
265 public T, |
|
266 public exception |
|
267 { |
|
268 explicit |
|
269 error_info_injector( T const & x ): |
|
270 T(x) |
|
271 { |
|
272 } |
|
273 |
|
274 ~error_info_injector() throw() |
|
275 { |
|
276 } |
|
277 }; |
|
278 |
|
279 struct large_size { char c[256]; }; |
|
280 large_size dispatch( exception * ); |
|
281 |
|
282 struct small_size { }; |
|
283 small_size dispatch( void * ); |
|
284 |
|
285 template <class,int> |
|
286 struct enable_error_info_helper; |
|
287 |
|
288 template <class T> |
|
289 struct |
|
290 enable_error_info_helper<T,sizeof(large_size)> |
|
291 { |
|
292 typedef T type; |
|
293 }; |
|
294 |
|
295 template <class T> |
|
296 struct |
|
297 enable_error_info_helper<T,sizeof(small_size)> |
|
298 { |
|
299 typedef error_info_injector<T> type; |
|
300 }; |
|
301 |
|
302 template <class T> |
|
303 struct |
|
304 enable_error_info_return_type |
|
305 { |
|
306 typedef typename enable_error_info_helper<T,sizeof(dispatch((T*)0))>::type type; |
|
307 }; |
|
308 } |
|
309 |
|
310 template <class T> |
|
311 inline |
|
312 typename |
|
313 exception_detail::enable_error_info_return_type<T>::type |
|
314 enable_error_info( T const & x ) |
|
315 { |
|
316 typedef typename exception_detail::enable_error_info_return_type<T>::type rt; |
|
317 return rt(x); |
|
318 } |
|
319 |
|
320 //////////////////////////////////////////////////////////////////////// |
|
321 |
|
322 namespace |
|
323 exception_detail |
|
324 { |
|
325 class |
|
326 clone_base |
|
327 { |
|
328 public: |
|
329 |
|
330 virtual clone_base const * clone() const = 0; |
|
331 virtual void rethrow() const = 0; |
|
332 |
|
333 virtual |
|
334 ~clone_base() throw() |
|
335 { |
|
336 } |
|
337 }; |
|
338 |
|
339 inline |
|
340 void |
|
341 copy_boost_exception( exception * a, exception const * b ) |
|
342 { |
|
343 *a = *b; |
|
344 } |
|
345 |
|
346 inline |
|
347 void |
|
348 copy_boost_exception( void *, void const * ) |
|
349 { |
|
350 } |
|
351 |
|
352 template <class T> |
|
353 class |
|
354 clone_impl: |
|
355 public T, |
|
356 public clone_base |
|
357 { |
|
358 public: |
|
359 |
|
360 explicit |
|
361 clone_impl( T const & x ): |
|
362 T(x) |
|
363 { |
|
364 copy_boost_exception(this,&x); |
|
365 } |
|
366 |
|
367 ~clone_impl() throw() |
|
368 { |
|
369 } |
|
370 |
|
371 private: |
|
372 |
|
373 clone_base const * |
|
374 clone() const |
|
375 { |
|
376 return new clone_impl(*this); |
|
377 } |
|
378 |
|
379 void |
|
380 rethrow() const |
|
381 { |
|
382 throw*this; |
|
383 } |
|
384 }; |
|
385 } |
|
386 |
|
387 template <class T> |
|
388 inline |
|
389 exception_detail::clone_impl<T> |
|
390 enable_current_exception( T const & x ) |
|
391 { |
|
392 return exception_detail::clone_impl<T>(x); |
|
393 } |
|
394 } |
|
395 |
|
396 #endif |