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