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