1 //Copyright (c) 2006-2010 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 BOOST_EXCEPTION_8D22C4CA9CC811DCAA9133D256D89593 7 #define BOOST_EXCEPTION_8D22C4CA9CC811DCAA9133D256D89593 8 9 #include <boost/config.hpp> 10 #include <boost/exception/exception.hpp> 11 #include <boost/exception/to_string_stub.hpp> 12 #include <boost/exception/detail/error_info_impl.hpp> 13 #include <boost/exception/detail/shared_ptr.hpp> 14 #include <map> 15 16 #ifndef BOOST_EXCEPTION_ENABLE_WARNINGS 17 #if __GNUC__*100+__GNUC_MINOR__>301 18 #pragma GCC system_header 19 #endif 20 #ifdef __clang__ 21 #pragma clang system_header 22 #endif 23 #ifdef _MSC_VER 24 #pragma warning(push,1) 25 #endif 26 #endif 27 28 namespace 29 boost 30 { 31 template <class Tag,class T> 32 inline 33 std::string error_info_name(error_info<Tag,T> const & x)34 error_info_name( error_info<Tag,T> const & x ) 35 { 36 return tag_type_name<Tag>(); 37 } 38 39 template <class Tag,class T> 40 inline 41 std::string to_string(error_info<Tag,T> const & x)42 to_string( error_info<Tag,T> const & x ) 43 { 44 return '[' + error_info_name(x) + "] = " + to_string_stub(x.value()) + '\n'; 45 } 46 47 template <class Tag,class T> 48 inline 49 std::string 50 error_info<Tag,T>:: name_value_string() const51 name_value_string() const 52 { 53 return to_string_stub(*this); 54 } 55 56 namespace 57 exception_detail 58 { 59 class 60 error_info_container_impl BOOST_FINAL: 61 public error_info_container 62 { 63 public: 64 error_info_container_impl()65 error_info_container_impl(): 66 count_(0) 67 { 68 } 69 ~error_info_container_impl()70 ~error_info_container_impl() BOOST_NOEXCEPT_OR_NOTHROW 71 { 72 } 73 74 void set(shared_ptr<error_info_base> const & x,type_info_ const & typeid_)75 set( shared_ptr<error_info_base> const & x, type_info_ const & typeid_ ) 76 { 77 BOOST_ASSERT(x); 78 info_[typeid_] = x; 79 diagnostic_info_str_.clear(); 80 } 81 82 shared_ptr<error_info_base> get(type_info_ const & ti) const83 get( type_info_ const & ti ) const 84 { 85 error_info_map::const_iterator i=info_.find(ti); 86 if( info_.end()!=i ) 87 { 88 shared_ptr<error_info_base> const & p = i->second; 89 #ifndef BOOST_NO_RTTI 90 BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ ); 91 #endif 92 return p; 93 } 94 return shared_ptr<error_info_base>(); 95 } 96 97 char const * diagnostic_information(char const * header) const98 diagnostic_information( char const * header ) const 99 { 100 if( header ) 101 { 102 std::ostringstream tmp; 103 tmp << header; 104 for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i ) 105 { 106 error_info_base const & x = *i->second; 107 tmp << x.name_value_string(); 108 } 109 tmp.str().swap(diagnostic_info_str_); 110 } 111 return diagnostic_info_str_.c_str(); 112 } 113 114 private: 115 116 friend class boost::exception; 117 118 typedef std::map< type_info_, shared_ptr<error_info_base> > error_info_map; 119 error_info_map info_; 120 mutable std::string diagnostic_info_str_; 121 mutable int count_; 122 123 error_info_container_impl( error_info_container_impl const & ); 124 error_info_container_impl & operator=( error_info_container const & ); 125 126 void add_ref() const127 add_ref() const 128 { 129 ++count_; 130 } 131 132 bool release() const133 release() const 134 { 135 if( --count_ ) 136 return false; 137 else 138 { 139 delete this; 140 return true; 141 } 142 } 143 144 refcount_ptr<error_info_container> clone() const145 clone() const 146 { 147 refcount_ptr<error_info_container> p; 148 error_info_container_impl * c=new error_info_container_impl; 149 p.adopt(c); 150 for( error_info_map::const_iterator i=info_.begin(),e=info_.end(); i!=e; ++i ) 151 { 152 shared_ptr<error_info_base> cp(i->second->clone()); 153 c->info_.insert(std::make_pair(i->first,cp)); 154 } 155 return p; 156 } 157 }; 158 159 template <class E,class Tag,class T> 160 inline 161 E const & set_info(E const & x,error_info<Tag,T> const & v)162 set_info( E const & x, error_info<Tag,T> const & v ) 163 { 164 typedef error_info<Tag,T> error_info_tag_t; 165 shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) ); 166 exception_detail::error_info_container * c=x.data_.get(); 167 if( !c ) 168 x.data_.adopt(c=new exception_detail::error_info_container_impl); 169 c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); 170 return x; 171 } 172 173 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 174 template <class E,class Tag,class T> 175 E const & set_info( E const &, error_info<Tag,T> && ); 176 template <class T> 177 struct set_info_rv; 178 template <class Tag,class T> 179 struct 180 set_info_rv<error_info<Tag,T> > 181 { 182 template <class E,class Tag1,class T1> 183 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 184 template <class E> 185 static 186 E const & setboost::exception_detail::set_info_rv187 set( E const & x, error_info<Tag,T> && v ) 188 { 189 typedef error_info<Tag,T> error_info_tag_t; 190 shared_ptr<error_info_tag_t> p( new error_info_tag_t(std::move(v)) ); 191 exception_detail::error_info_container * c=x.data_.get(); 192 if( !c ) 193 x.data_.adopt(c=new exception_detail::error_info_container_impl); 194 c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); 195 return x; 196 } 197 }; 198 template <> 199 struct 200 set_info_rv<throw_function> 201 { 202 template <class E,class Tag1,class T1> 203 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 204 template <class E> 205 static 206 E const & setboost::exception_detail::set_info_rv207 set( E const & x, throw_function && y ) 208 { 209 x.throw_function_=y.v_; 210 return x; 211 } 212 }; 213 template <> 214 struct 215 set_info_rv<throw_file> 216 { 217 template <class E,class Tag1,class T1> 218 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 219 template <class E> 220 static 221 E const & setboost::exception_detail::set_info_rv222 set( E const & x, throw_file && y ) 223 { 224 x.throw_file_=y.v_; 225 return x; 226 } 227 }; 228 template <> 229 struct 230 set_info_rv<throw_line> 231 { 232 template <class E,class Tag1,class T1> 233 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 234 template <class E> 235 static 236 E const & setboost::exception_detail::set_info_rv237 set( E const & x, throw_line && y ) 238 { 239 x.throw_line_=y.v_; 240 return x; 241 } 242 }; 243 template <class E,class Tag,class T> 244 inline 245 E const & set_info(E const & x,error_info<Tag,T> && v)246 set_info( E const & x, error_info<Tag,T> && v ) 247 { 248 return set_info_rv<error_info<Tag,T> >::template set<E>(x,std::move(v)); 249 } 250 #endif 251 252 template <class T> 253 struct 254 derives_boost_exception 255 { 256 enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) }; 257 }; 258 } 259 260 template <class E,class Tag,class T> 261 inline 262 typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type operator <<(E const & x,error_info<Tag,T> const & v)263 operator<<( E const & x, error_info<Tag,T> const & v ) 264 { 265 return exception_detail::set_info(x,v); 266 } 267 268 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 269 template <class E,class Tag,class T> 270 inline 271 typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type operator <<(E const & x,error_info<Tag,T> && v)272 operator<<( E const & x, error_info<Tag,T> && v ) 273 { 274 return exception_detail::set_info(x,std::move(v)); 275 } 276 #endif 277 } 278 279 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 280 #pragma warning(pop) 281 #endif 282 #endif 283