Line data Source code
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 defined(__GNUC__) && __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
34 : error_info_name( error_info<Tag,T> const & )
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 :
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
60 : error_info_container_impl BOOST_FINAL:
61 : public error_info_container
62 : {
63 : public:
64 :
65 0 : error_info_container_impl():
66 0 : count_(0)
67 0 : {
68 0 : }
69 :
70 0 : ~error_info_container_impl() BOOST_NOEXCEPT_OR_NOTHROW
71 0 : {
72 0 : }
73 :
74 : void
75 0 : set( shared_ptr<error_info_base> const & x, type_info_ const & typeid_ )
76 : {
77 0 : BOOST_ASSERT(x);
78 0 : info_[typeid_] = x;
79 0 : diagnostic_info_str_.clear();
80 0 : }
81 :
82 : shared_ptr<error_info_base>
83 0 : get( type_info_ const & ti ) const
84 : {
85 0 : error_info_map::const_iterator i=info_.find(ti);
86 0 : if( info_.end()!=i )
87 : {
88 0 : shared_ptr<error_info_base> const & p = i->second;
89 0 : return p;
90 : }
91 0 : return shared_ptr<error_info_base>();
92 0 : }
93 :
94 : char const *
95 0 : diagnostic_information( char const * header ) const
96 : {
97 0 : if( header )
98 : {
99 0 : std::ostringstream tmp;
100 0 : tmp << header;
101 0 : for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
102 : {
103 0 : error_info_base const & x = *i->second;
104 0 : tmp << x.name_value_string();
105 0 : }
106 0 : tmp.str().swap(diagnostic_info_str_);
107 0 : }
108 0 : return diagnostic_info_str_.c_str();
109 0 : }
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
124 0 : add_ref() const
125 : {
126 0 : ++count_;
127 0 : }
128 :
129 : bool
130 0 : release() const
131 : {
132 0 : if( --count_ )
133 0 : return false;
134 : else
135 : {
136 0 : delete this;
137 0 : return true;
138 : }
139 0 : }
140 :
141 : refcount_ptr<error_info_container>
142 0 : clone() const
143 : {
144 0 : refcount_ptr<error_info_container> p;
145 0 : error_info_container_impl * c=new error_info_container_impl;
146 0 : p.adopt(c);
147 0 : for( error_info_map::const_iterator i=info_.begin(),e=info_.end(); i!=e; ++i )
148 : {
149 0 : shared_ptr<error_info_base> cp(i->second->clone());
150 0 : c->info_.insert(std::make_pair(i->first,cp));
151 0 : }
152 0 : return p;
153 0 : }
154 : };
155 :
156 : template <class E,class Tag,class T>
157 : inline
158 : E const &
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 &
184 : 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 &
204 : 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 &
219 : 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 &
234 : 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 &
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
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
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
|