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 |
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 |
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>:: |
46 | 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 | |
60 | error_info_container_impl(): |
61 | count_(0) |
62 | { |
63 | } |
64 | |
65 | ~error_info_container_impl() throw() |
66 | { |
67 | } |
68 | |
69 | void |
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> |
78 | 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 * |
93 | diagnostic_information( char const * ) 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 |
122 | add_ref() const |
123 | { |
124 | ++count_; |
125 | } |
126 | |
127 | bool |
128 | 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> |
140 | 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 & |
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 & |
182 | 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 & |
202 | 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 & |
217 | 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 & |
232 | 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 & |
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 |
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 |
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 | |