info.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.
  2. //Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593
  5. #define UUID_8D22C4CA9CC811DCAA9133D256D89593
  6. #if defined(__GNUC__) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
  7. #pragma GCC system_header
  8. #endif
  9. #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
  10. #pragma warning(push,1)
  11. #endif
  12. #include <boost/exception/exception.hpp>
  13. #include <boost/exception/to_string_stub.hpp>
  14. #include <boost/exception/detail/error_info_impl.hpp>
  15. #include <boost/shared_ptr.hpp>
  16. #include <boost/config.hpp>
  17. #include <map>
  18. namespace
  19. boost
  20. {
  21. template <class Tag,class T>
  22. inline
  23. typename enable_if<has_to_string<T>,std::string>::type
  24. to_string( error_info<Tag,T> const & x )
  25. {
  26. return to_string(x.value());
  27. }
  28. template <class Tag,class T>
  29. inline
  30. error_info<Tag,T>::
  31. error_info( value_type const & value ):
  32. value_(value)
  33. {
  34. }
  35. template <class Tag,class T>
  36. inline
  37. error_info<Tag,T>::
  38. ~error_info() throw()
  39. {
  40. }
  41. template <class Tag,class T>
  42. inline
  43. std::string
  44. error_info<Tag,T>::
  45. tag_typeid_name() const
  46. {
  47. return tag_type_name<Tag>();
  48. }
  49. template <class Tag,class T>
  50. inline
  51. std::string
  52. error_info<Tag,T>::
  53. value_as_string() const
  54. {
  55. return to_string_stub(*this);
  56. }
  57. namespace
  58. exception_detail
  59. {
  60. class
  61. error_info_container_impl:
  62. public error_info_container
  63. {
  64. public:
  65. error_info_container_impl():
  66. count_(0)
  67. {
  68. }
  69. ~error_info_container_impl() throw()
  70. {
  71. }
  72. void
  73. set( shared_ptr<error_info_base> const & x, type_info_ const & typeid_ )
  74. {
  75. BOOST_ASSERT(x);
  76. info_[typeid_] = x;
  77. diagnostic_info_str_.clear();
  78. }
  79. shared_ptr<error_info_base>
  80. get( type_info_ const & ti ) const
  81. {
  82. error_info_map::const_iterator i=info_.find(ti);
  83. if( info_.end()!=i )
  84. {
  85. shared_ptr<error_info_base> const & p = i->second;
  86. #ifndef BOOST_NO_RTTI
  87. BOOST_ASSERT( BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==ti.type_ );
  88. #endif
  89. return p;
  90. }
  91. return shared_ptr<error_info_base>();
  92. }
  93. char const *
  94. diagnostic_information( char const * header ) const
  95. {
  96. if( header )
  97. {
  98. BOOST_ASSERT(*header!=0);
  99. std::ostringstream tmp;
  100. tmp << header;
  101. for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
  102. {
  103. error_info_base const & x = *i->second;
  104. tmp << '[' << x.tag_typeid_name() << "] = " << x.value_as_string() << '\n';
  105. }
  106. tmp.str().swap(diagnostic_info_str_);
  107. }
  108. return diagnostic_info_str_.c_str();
  109. }
  110. private:
  111. friend class boost::exception;
  112. typedef std::map< type_info_, shared_ptr<error_info_base> > error_info_map;
  113. error_info_map info_;
  114. mutable std::string diagnostic_info_str_;
  115. mutable int count_;
  116. error_info_container_impl( error_info_container_impl const & );
  117. error_info_container_impl & operator=( error_info_container const & );
  118. void
  119. add_ref() const
  120. {
  121. ++count_;
  122. }
  123. bool
  124. release() const
  125. {
  126. if( --count_ )
  127. return false;
  128. else
  129. {
  130. delete this;
  131. return true;
  132. }
  133. }
  134. refcount_ptr<error_info_container>
  135. clone() const
  136. {
  137. refcount_ptr<error_info_container> p;
  138. error_info_container_impl * c=new error_info_container_impl;
  139. p.adopt(c);
  140. c->info_ = info_;
  141. return p;
  142. }
  143. };
  144. template <class E,class Tag,class T>
  145. inline
  146. E const &
  147. set_info( E const & x, error_info<Tag,T> const & v )
  148. {
  149. typedef error_info<Tag,T> error_info_tag_t;
  150. shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) );
  151. exception_detail::error_info_container * c=x.data_.get();
  152. if( !c )
  153. x.data_.adopt(c=new exception_detail::error_info_container_impl);
  154. c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t));
  155. return x;
  156. }
  157. template <class T>
  158. struct
  159. derives_boost_exception
  160. {
  161. enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) };
  162. };
  163. }
  164. template <class E,class Tag,class T>
  165. inline
  166. typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type
  167. operator<<( E const & x, error_info<Tag,T> const & v )
  168. {
  169. return exception_detail::set_info(x,v);
  170. }
  171. }
  172. #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
  173. #pragma warning(pop)
  174. #endif
  175. #endif