blob: 727161d0f929eee60c6290f6e8f42ce3e9907495 [file] [log] [blame]
Jeff Thompsonf7d49942013-08-01 16:47:40 -07001//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 defined(__GNUC__) && !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
16ndnboost
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 protected:
211
212 exception():
213 throw_function_(0),
214 throw_file_(0),
215 throw_line_(-1)
216 {
217 }
218
219#ifdef __HP_aCC
220 //On HP aCC, this protected copy constructor prevents throwing ndnboost::exception.
221 //On all other platforms, the same effect is achieved by the pure virtual destructor.
222 exception( exception const & x ) throw():
223 data_(x.data_),
224 throw_function_(x.throw_function_),
225 throw_file_(x.throw_file_),
226 throw_line_(x.throw_line_)
227 {
228 }
229#endif
230
231 virtual ~exception() throw()
232#ifndef __HP_aCC
233 = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors.
234#endif
235 ;
236
237#if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310)
238 public:
239#else
240 private:
241
242 template <class E>
243 friend E const & exception_detail::set_info( E const &, throw_function const & );
244
245 template <class E>
246 friend E const & exception_detail::set_info( E const &, throw_file const & );
247
248 template <class E>
249 friend E const & exception_detail::set_info( E const &, throw_line const & );
250
251 template <class E,class Tag,class T>
252 friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & );
253
254 friend char const * exception_detail::get_diagnostic_information( exception const &, char const * );
255
256 template <class>
257 friend struct exception_detail::get_info;
258 friend struct exception_detail::get_info<throw_function>;
259 friend struct exception_detail::get_info<throw_file>;
260 friend struct exception_detail::get_info<throw_line>;
261 friend void exception_detail::copy_boost_exception( exception *, exception const * );
262#endif
263 mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
264 mutable char const * throw_function_;
265 mutable char const * throw_file_;
266 mutable int throw_line_;
267 };
268#if defined(__GNUC__)
269# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
270# pragma GCC visibility pop
271# endif
272#endif
273
274 inline
275 exception::
276 ~exception() throw()
277 {
278 }
279
280 namespace
281 exception_detail
282 {
283 template <class E>
284 E const &
285 set_info( E const & x, throw_function const & y )
286 {
287 x.throw_function_=y.v_;
288 return x;
289 }
290
291 template <class E>
292 E const &
293 set_info( E const & x, throw_file const & y )
294 {
295 x.throw_file_=y.v_;
296 return x;
297 }
298
299 template <class E>
300 E const &
301 set_info( E const & x, throw_line const & y )
302 {
303 x.throw_line_=y.v_;
304 return x;
305 }
306 }
307
308 ////////////////////////////////////////////////////////////////////////
309
310 namespace
311 exception_detail
312 {
313#if defined(__GNUC__)
314# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
315# pragma GCC visibility push (default)
316# endif
317#endif
318 template <class T>
319 struct
320 error_info_injector:
321 public T,
322 public exception
323 {
324 explicit
325 error_info_injector( T const & x ):
326 T(x)
327 {
328 }
329
330 ~error_info_injector() throw()
331 {
332 }
333 };
334#if defined(__GNUC__)
335# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
336# pragma GCC visibility pop
337# endif
338#endif
339
340 struct large_size { char c[256]; };
341 large_size dispatch_boost_exception( exception const * );
342
343 struct small_size { };
344 small_size dispatch_boost_exception( void const * );
345
346 template <class,int>
347 struct enable_error_info_helper;
348
349 template <class T>
350 struct
351 enable_error_info_helper<T,sizeof(large_size)>
352 {
353 typedef T type;
354 };
355
356 template <class T>
357 struct
358 enable_error_info_helper<T,sizeof(small_size)>
359 {
360 typedef error_info_injector<T> type;
361 };
362
363 template <class T>
364 struct
365 enable_error_info_return_type
366 {
367 typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception(static_cast<T *>(0)))>::type type;
368 };
369 }
370
371 template <class T>
372 inline
373 typename
374 exception_detail::enable_error_info_return_type<T>::type
375 enable_error_info( T const & x )
376 {
377 typedef typename exception_detail::enable_error_info_return_type<T>::type rt;
378 return rt(x);
379 }
380
381 ////////////////////////////////////////////////////////////////////////
382
383 namespace
384 exception_detail
385 {
386#if defined(__GNUC__)
387# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
388# pragma GCC visibility push (default)
389# endif
390#endif
391 class
392 clone_base
393 {
394 public:
395
396 virtual clone_base const * clone() const = 0;
397 virtual void rethrow() const = 0;
398
399 virtual
400 ~clone_base() throw()
401 {
402 }
403 };
404#if defined(__GNUC__)
405# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
406# pragma GCC visibility pop
407# endif
408#endif
409
410 inline
411 void
412 copy_boost_exception( exception * a, exception const * b )
413 {
414 refcount_ptr<error_info_container> data;
415 if( error_info_container * d=b->data_.get() )
416 data = d->clone();
417 a->throw_file_ = b->throw_file_;
418 a->throw_line_ = b->throw_line_;
419 a->throw_function_ = b->throw_function_;
420 a->data_ = data;
421 }
422
423 inline
424 void
425 copy_boost_exception( void *, void const * )
426 {
427 }
428
429 template <class T>
430 class
431 clone_impl:
432 public T,
433 public virtual clone_base
434 {
435 struct clone_tag { };
436 clone_impl( clone_impl const & x, clone_tag ):
437 T(x)
438 {
439 copy_boost_exception(this,&x);
440 }
441
442 public:
443
444 explicit
445 clone_impl( T const & x ):
446 T(x)
447 {
448 copy_boost_exception(this,&x);
449 }
450
451 ~clone_impl() throw()
452 {
453 }
454
455 private:
456
457 clone_base const *
458 clone() const
459 {
460 return new clone_impl(*this,clone_tag());
461 }
462
463 void
464 rethrow() const
465 {
466 throw*this;
467 }
468 };
469 }
470
471 template <class T>
472 inline
473 exception_detail::clone_impl<T>
474 enable_current_exception( T const & x )
475 {
476 return exception_detail::clone_impl<T>(x);
477 }
478 }
479
480#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
481#pragma warning(pop)
482#endif
483#endif