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