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 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 0 : error_info<Tag,T>::
46 : name_value_string() const
47 : {
48 0 : 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 0 : error_info_container_impl():
61 0 : count_(0)
62 : {
63 : }
64 :
65 0 : ~error_info_container_impl() BOOST_NOEXCEPT_OR_NOTHROW
66 0 : {
67 0 : }
68 :
69 : void
70 0 : set( shared_ptr<error_info_base> const & x, type_info_ const & typeid_ )
71 : {
72 0 : BOOST_ASSERT(x);
73 0 : info_[typeid_] = x;
74 0 : diagnostic_info_str_.clear();
75 0 : }
76 :
77 : shared_ptr<error_info_base>
78 0 : get( type_info_ const & ti ) const
79 : {
80 0 : error_info_map::const_iterator i=info_.find(ti);
81 0 : if( info_.end()!=i )
82 : {
83 0 : shared_ptr<error_info_base> const & p = i->second;
84 : #ifndef BOOST_NO_RTTI
85 0 : BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ );
86 : #endif
87 0 : return p;
88 : }
89 0 : return shared_ptr<error_info_base>();
90 : }
91 :
92 : char const *
93 0 : diagnostic_information( char const * header ) const
94 : {
95 0 : if( header )
96 : {
97 0 : std::ostringstream tmp;
98 0 : tmp << header;
99 0 : for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
100 : {
101 0 : error_info_base const & x = *i->second;
102 0 : tmp << x.name_value_string();
103 : }
104 0 : tmp.str().swap(diagnostic_info_str_);
105 : }
106 0 : 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 0 : add_ref() const
123 : {
124 0 : ++count_;
125 0 : }
126 :
127 : bool
128 0 : release() const
129 : {
130 0 : if( --count_ )
131 : return false;
132 : else
133 : {
134 0 : delete this;
135 0 : return true;
136 : }
137 : }
138 :
139 : refcount_ptr<error_info_container>
140 0 : clone() const
141 : {
142 0 : refcount_ptr<error_info_container> p;
143 0 : error_info_container_impl * c=new error_info_container_impl;
144 0 : p.adopt(c);
145 0 : for( error_info_map::const_iterator i=info_.begin(),e=info_.end(); i!=e; ++i )
146 : {
147 0 : shared_ptr<error_info_base> cp(i->second->clone());
148 0 : c->info_.insert(std::make_pair(i->first,cp));
149 : }
150 0 : 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 0 : set( E const & x, throw_function && y )
203 : {
204 0 : 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 0 : set( E const & x, throw_file && y )
218 : {
219 0 : 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 0 : set( E const & x, throw_line && y )
233 : {
234 0 : x.throw_line_=y.v_;
235 : return x;
236 : }
237 : };
238 : template <class E,class Tag,class T>
239 : inline
240 : E const &
241 0 : set_info( E const & x, error_info<Tag,T> && v )
242 : {
243 0 : 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 0 : operator<<( E const & x, error_info<Tag,T> && v )
268 : {
269 0 : 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
|