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 refcount_ptr()35 refcount_ptr(): 36 px_(0) 37 { 38 } 39 ~refcount_ptr()40 ~refcount_ptr() 41 { 42 release(); 43 } 44 refcount_ptr(refcount_ptr const & x)45 refcount_ptr( refcount_ptr const & x ): 46 px_(x.px_) 47 { 48 add_ref(); 49 } 50 51 refcount_ptr & operator =(refcount_ptr const & x)52 operator=( refcount_ptr const & x ) 53 { 54 adopt(x.px_); 55 return *this; 56 } 57 58 void adopt(T * px)59 adopt( T * px ) 60 { 61 release(); 62 px_=px; 63 add_ref(); 64 } 65 66 T * get() const67 get() const 68 { 69 return px_; 70 } 71 72 private: 73 74 T * px_; 75 76 void add_ref()77 add_ref() 78 { 79 if( px_ ) 80 px_->add_ref(); 81 } 82 83 void release()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 error_info(value_type v)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 error_info(value_type v)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 error_info(value_type v)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 ~error_info_containerboost::exception_detail::error_info_container173 ~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 exception()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. exception(exception const & x)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:: ~exception()304 ~exception() throw() 305 { 306 } 307 308 namespace 309 exception_detail 310 { 311 template <class E> 312 E const & set_info(E const & x,throw_function const & y)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 & set_info(E const & x,throw_file const & y)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 & set_info(E const & x,throw_line const & y)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 error_info_injectorboost::exception_detail::error_info_injector353 error_info_injector( T const & x ): 354 T(x) 355 { 356 } 357 ~error_info_injectorboost::exception_detail::error_info_injector358 ~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 enable_error_info(T const & x)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 ~clone_base()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 copy_boost_exception(exception * a,exception const * b)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 copy_boost_exception(void *,void const *)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 { }; clone_impl(clone_impl const & x,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 clone_impl(T const & x)478 clone_impl( T const & x ): 479 T(x) 480 { 481 copy_boost_exception(this,&x); 482 } 483 ~clone_impl()484 ~clone_impl() throw() 485 { 486 } 487 488 private: 489 490 clone_base const * clone() const491 clone() const 492 { 493 return new clone_impl(*this,clone_tag()); 494 } 495 496 void rethrow() const497 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> enable_current_exception(T const & x)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