]>
Commit | Line | Data |
---|---|---|
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 * header ) 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 |