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 | #if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
9 | #pragma GCC system_header |
10 | #endif |
11 | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
12 | #pragma warning(push,1) |
13 | #endif |
14 | |
15 | #include <boost/exception/exception.hpp> |
16 | #include <boost/exception/to_string_stub.hpp> |
17 | #include <boost/exception/detail/error_info_impl.hpp> |
18 | #include <boost/shared_ptr.hpp> |
19 | #include <boost/config.hpp> |
20 | #include <map> |
21 | |
22 | namespace |
23 | boost |
24 | { |
25 | template <class Tag,class T> |
26 | inline |
27 | std::string |
28 | error_info_name( error_info<Tag,T> const & x ) |
29 | { |
30 | return tag_type_name<Tag>(); |
31 | } |
32 | |
33 | template <class Tag,class T> |
34 | inline |
35 | std::string |
36 | to_string( error_info<Tag,T> const & x ) |
37 | { |
38 | return '[' + error_info_name(x) + "] = " + to_string_stub(x.value()) + '\n'; |
39 | } |
40 | |
41 | template <class Tag,class T> |
42 | inline |
43 | error_info<Tag,T>:: |
44 | error_info( value_type const & value ): |
45 | value_(value) |
46 | { |
47 | } |
48 | |
49 | template <class Tag,class T> |
50 | inline |
51 | error_info<Tag,T>:: |
52 | ~error_info() throw() |
53 | { |
54 | } |
55 | |
56 | template <class Tag,class T> |
57 | inline |
58 | std::string |
59 | error_info<Tag,T>:: |
60 | name_value_string() const |
61 | { |
62 | return to_string_stub(*this); |
63 | } |
64 | |
65 | namespace |
66 | exception_detail |
67 | { |
68 | class |
69 | error_info_container_impl: |
70 | public error_info_container |
71 | { |
72 | public: |
73 | |
74 | error_info_container_impl(): |
75 | count_(0) |
76 | { |
77 | } |
78 | |
79 | ~error_info_container_impl() throw() |
80 | { |
81 | } |
82 | |
83 | void |
84 | set( shared_ptr<error_info_base> const & x, type_info_ const & typeid_ ) |
85 | { |
86 | BOOST_ASSERT(x); |
87 | info_[typeid_] = x; |
88 | diagnostic_info_str_.clear(); |
89 | } |
90 | |
91 | shared_ptr<error_info_base> |
92 | get( type_info_ const & ti ) const |
93 | { |
94 | error_info_map::const_iterator i=info_.find(x: ti); |
95 | if( info_.end()!=i ) |
96 | { |
97 | shared_ptr<error_info_base> const & p = i->second; |
98 | #ifndef BOOST_NO_RTTI |
99 | BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ ); |
100 | #endif |
101 | return p; |
102 | } |
103 | return shared_ptr<error_info_base>(); |
104 | } |
105 | |
106 | char const * |
107 | diagnostic_information( char const * ) const |
108 | { |
109 | if( header ) |
110 | { |
111 | std::ostringstream tmp; |
112 | tmp << header; |
113 | for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i ) |
114 | { |
115 | error_info_base const & x = *i->second; |
116 | tmp << x.name_value_string(); |
117 | } |
118 | tmp.str().swap(s&: diagnostic_info_str_); |
119 | } |
120 | return diagnostic_info_str_.c_str(); |
121 | } |
122 | |
123 | private: |
124 | |
125 | friend class boost::exception; |
126 | |
127 | typedef std::map< type_info_, shared_ptr<error_info_base> > error_info_map; |
128 | error_info_map info_; |
129 | mutable std::string diagnostic_info_str_; |
130 | mutable int count_; |
131 | |
132 | error_info_container_impl( error_info_container_impl const & ); |
133 | error_info_container_impl & operator=( error_info_container const & ); |
134 | |
135 | void |
136 | add_ref() const |
137 | { |
138 | ++count_; |
139 | } |
140 | |
141 | bool |
142 | release() const |
143 | { |
144 | if( --count_ ) |
145 | return false; |
146 | else |
147 | { |
148 | delete this; |
149 | return true; |
150 | } |
151 | } |
152 | |
153 | refcount_ptr<error_info_container> |
154 | clone() const |
155 | { |
156 | refcount_ptr<error_info_container> p; |
157 | error_info_container_impl * c=new error_info_container_impl; |
158 | p.adopt(px: c); |
159 | c->info_ = info_; |
160 | return p; |
161 | } |
162 | }; |
163 | |
164 | template <class E,class Tag,class T> |
165 | inline |
166 | E const & |
167 | set_info( E const & x, error_info<Tag,T> const & v ) |
168 | { |
169 | typedef error_info<Tag,T> error_info_tag_t; |
170 | shared_ptr<error_info_tag_t> p( new error_info_tag_t(v) ); |
171 | exception_detail::error_info_container * c=x.data_.get(); |
172 | if( !c ) |
173 | x.data_.adopt(c=new exception_detail::error_info_container_impl); |
174 | c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); |
175 | return x; |
176 | } |
177 | |
178 | template <class T> |
179 | struct |
180 | derives_boost_exception |
181 | { |
182 | enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) }; |
183 | }; |
184 | } |
185 | |
186 | template <class E,class Tag,class T> |
187 | inline |
188 | typename enable_if<exception_detail::derives_boost_exception<E>,E const &>::type |
189 | operator<<( E const & x, error_info<Tag,T> const & v ) |
190 | { |
191 | return exception_detail::set_info(x,v); |
192 | } |
193 | } |
194 | |
195 | #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) |
196 | #pragma warning(pop) |
197 | #endif |
198 | #endif |
199 | |