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
error_info_name(error_info<Tag,T> const & x)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
to_string(error_info<Tag,T> const & x)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>::
name_value_string() const46     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 
error_info_container_impl()60             error_info_container_impl():
61                 count_(0)
62                 {
63                 }
64 
~error_info_container_impl()65             ~error_info_container_impl() throw()
66                 {
67                 }
68 
69             void
set(shared_ptr<error_info_base> const & x,type_info_ const & typeid_)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>
get(type_info_ const & ti) const78             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 *
diagnostic_information(char const * header) const93             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
add_ref() const122             add_ref() const
123                 {
124                 ++count_;
125                 }
126 
127             bool
release() const128             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>
clone() const140             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 &
set_info(E const & x,error_info<Tag,T> const & v)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 &
setboost::exception_detail::set_info_rv182             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 &
setboost::exception_detail::set_info_rv202             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 &
setboost::exception_detail::set_info_rv217             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 &
setboost::exception_detail::set_info_rv232             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 &
set_info(E const & x,error_info<Tag,T> && v)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
operator <<(E const & x,error_info<Tag,T> const & v)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
operator <<(E const & x,error_info<Tag,T> && v)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
278