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