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 return p; 90 } 91 return shared_ptr<error_info_base>(); 92 } 93 94 char const * diagnostic_information(char const * header) const95 diagnostic_information( char const * header ) const 96 { 97 if( header ) 98 { 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.name_value_string(); 105 } 106 tmp.str().swap(diagnostic_info_str_); 107 } 108 return diagnostic_info_str_.c_str(); 109 } 110 111 private: 112 113 friend class boost::exception; 114 115 typedef std::map< type_info_, shared_ptr<error_info_base> > error_info_map; 116 error_info_map info_; 117 mutable std::string diagnostic_info_str_; 118 mutable int count_; 119 120 error_info_container_impl( error_info_container_impl const & ); 121 error_info_container_impl & operator=( error_info_container const & ); 122 123 void add_ref() const124 add_ref() const 125 { 126 ++count_; 127 } 128 129 bool release() const130 release() const 131 { 132 if( --count_ ) 133 return false; 134 else 135 { 136 delete this; 137 return true; 138 } 139 } 140 141 refcount_ptr<error_info_container> clone() const142 clone() const 143 { 144 refcount_ptr<error_info_container> p; 145 error_info_container_impl * c=new error_info_container_impl; 146 p.adopt(c); 147 for( error_info_map::const_iterator i=info_.begin(),e=info_.end(); i!=e; ++i ) 148 { 149 shared_ptr<error_info_base> cp(i->second->clone()); 150 c->info_.insert(std::make_pair(i->first,cp)); 151 } 152 return p; 153 } 154 }; 155 156 template <class E,class Tag,class T> 157 inline 158 E const & set_info(E const & x,error_info<Tag,T> const & v)159 set_info( E const & x, error_info<Tag,T> const & v ) 160 { 161 typedef error_info<Tag,T> error_info_tag_t; 162 shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) ); 163 exception_detail::error_info_container * c=x.data_.get(); 164 if( !c ) 165 x.data_.adopt(c=new exception_detail::error_info_container_impl); 166 c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); 167 return x; 168 } 169 170 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 171 template <class E,class Tag,class T> 172 E const & set_info( E const &, error_info<Tag,T> && ); 173 template <class T> 174 struct set_info_rv; 175 template <class Tag,class T> 176 struct 177 set_info_rv<error_info<Tag,T> > 178 { 179 template <class E,class Tag1,class T1> 180 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 181 template <class E> 182 static 183 E const & setboost::exception_detail::set_info_rv184 set( E const & x, error_info<Tag,T> && v ) 185 { 186 typedef error_info<Tag,T> error_info_tag_t; 187 shared_ptr<error_info_tag_t> p( new error_info_tag_t(std::move(v)) ); 188 exception_detail::error_info_container * c=x.data_.get(); 189 if( !c ) 190 x.data_.adopt(c=new exception_detail::error_info_container_impl); 191 c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); 192 return x; 193 } 194 }; 195 template <> 196 struct 197 set_info_rv<throw_function> 198 { 199 template <class E,class Tag1,class T1> 200 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 201 template <class E> 202 static 203 E const & setboost::exception_detail::set_info_rv204 set( E const & x, throw_function && y ) 205 { 206 x.throw_function_=y.v_; 207 return x; 208 } 209 }; 210 template <> 211 struct 212 set_info_rv<throw_file> 213 { 214 template <class E,class Tag1,class T1> 215 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 216 template <class E> 217 static 218 E const & setboost::exception_detail::set_info_rv219 set( E const & x, throw_file && y ) 220 { 221 x.throw_file_=y.v_; 222 return x; 223 } 224 }; 225 template <> 226 struct 227 set_info_rv<throw_line> 228 { 229 template <class E,class Tag1,class T1> 230 friend E const & set_info( E const &, error_info<Tag1,T1> && ); 231 template <class E> 232 static 233 E const & setboost::exception_detail::set_info_rv234 set( E const & x, throw_line && y ) 235 { 236 x.throw_line_=y.v_; 237 return x; 238 } 239 }; 240 template <class E,class Tag,class T> 241 inline 242 E const & set_info(E const & x,error_info<Tag,T> && v)243 set_info( E const & x, error_info<Tag,T> && v ) 244 { 245 return set_info_rv<error_info<Tag,T> >::template set<E>(x,std::move(v)); 246 } 247 #endif 248 249 template <class T> 250 struct 251 derives_boost_exception 252 { 253 enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) }; 254 }; 255 } 256 257 template <class E,class Tag,class T> 258 inline 259 typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type operator <<(E const & x,error_info<Tag,T> const & v)260 operator<<( E const & x, error_info<Tag,T> const & v ) 261 { 262 return exception_detail::set_info(x,v); 263 } 264 265 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 266 template <class E,class Tag,class T> 267 inline 268 typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type operator <<(E const & x,error_info<Tag,T> && v)269 operator<<( E const & x, error_info<Tag,T> && v ) 270 { 271 return exception_detail::set_info(x,std::move(v)); 272 } 273 #endif 274 } 275 276 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 277 #pragma warning(pop) 278 #endif 279 #endif 280