1 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2 // extended_type_info.cpp: implementation for portable version of type_info
3
4 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5 // Use, modification and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8
9 // See http://www.boost.org for updates, documentation, and revision history.
10
11 #if (defined _MSC_VER) && (_MSC_VER == 1200)
12 # pragma warning (disable : 4786) // too long name, harmless warning
13 #endif
14
15 #include <algorithm>
16 #include <set>
17 #include <utility>
18 #include <boost/assert.hpp>
19 #include <cstddef> // NULL
20
21 #include <cstring>
22 #if defined(BOOST_NO_STDC_NAMESPACE)
23 namespace std{ using ::strcmp; }
24 #endif
25
26 #include <boost/config.hpp> // msvc needs this to suppress warning
27
28 #include <boost/core/no_exceptions_support.hpp>
29
30 // it marks our code with proper attributes as being exported when
31 // we're compiling it while marking it import when just the headers
32 // is being included.
33 #define BOOST_SERIALIZATION_SOURCE
34 #include <boost/serialization/config.hpp>
35 #include <boost/serialization/singleton.hpp>
36 #include <boost/serialization/force_include.hpp>
37 #include <boost/serialization/extended_type_info.hpp>
38
39 #ifdef BOOST_MSVC
40 # pragma warning(push)
41 # pragma warning(disable : 4511 4512)
42 #endif
43
44 namespace boost {
45 namespace serialization {
46 namespace detail {
47
48 struct key_compare
49 {
50 bool
operator ()boost::serialization::detail::key_compare51 operator()(
52 const extended_type_info * lhs,
53 const extended_type_info * rhs
54 ) const {
55 // performance shortcut
56 if(lhs == rhs)
57 return false;
58 const char * l = lhs->get_key();
59 BOOST_ASSERT(NULL != l);
60 const char * r = rhs->get_key();
61 BOOST_ASSERT(NULL != r);
62 // performance shortcut
63 // shortcut to exploit string pooling
64 if(l == r)
65 return false;
66 // for exported types, use the string key so that
67 // multiple instances in different translation units
68 // can be matched up
69 return std::strcmp(l, r) < 0;
70 }
71 };
72
73 typedef std::multiset<const extended_type_info *, key_compare> ktmap;
74
75 #ifdef BOOST_MSVC
76 # pragma warning(push)
77 # pragma warning(disable : 4511 4512)
78 #endif
79
80 class extended_type_info_arg : public extended_type_info
81 {
82 bool
is_less_than(const extended_type_info &) const83 is_less_than(const extended_type_info & /*rhs*/) const BOOST_OVERRIDE {
84 BOOST_ASSERT(false);
85 return false;
86 }
87 bool
is_equal(const extended_type_info &) const88 is_equal(const extended_type_info & /*rhs*/) const BOOST_OVERRIDE {
89 BOOST_ASSERT(false);
90 return false;
91 }
get_debug_info() const92 const char * get_debug_info() const BOOST_OVERRIDE {
93 return get_key();
94 }
construct(unsigned int,...) const95 void * construct(unsigned int /*count*/, ...) const BOOST_OVERRIDE {
96 BOOST_ASSERT(false);
97 return NULL;
98 }
destroy(void const * const) const99 void destroy(void const * const /*p*/) const BOOST_OVERRIDE {
100 BOOST_ASSERT(false);
101 }
102 public:
extended_type_info_arg(const char * key)103 extended_type_info_arg(const char * key) :
104 extended_type_info(0, key)
105 {}
106
~extended_type_info_arg()107 ~extended_type_info_arg() BOOST_OVERRIDE {}
108 };
109
110 #ifdef BOOST_MSVC
111 # pragma warning(pop)
112 #endif
113
114 } // namespace detail
115
116 BOOST_SERIALIZATION_DECL void
key_register() const117 extended_type_info::key_register() const{
118 if(NULL == get_key())
119 return;
120 singleton<detail::ktmap>::get_mutable_instance().insert(this);
121 }
122
123 BOOST_SERIALIZATION_DECL void
key_unregister() const124 extended_type_info::key_unregister() const{
125 if(NULL == get_key())
126 return;
127 // note: it's been discovered that at least one platform is not guaranteed
128 // to destroy singletons reverse order of construction. So we can't
129 // use a runtime assert here. Leave this in a reminder not to do this!
130 // BOOST_ASSERT(! singleton<detail::ktmap>::is_destroyed());
131 if(! singleton<detail::ktmap>::is_destroyed()){
132 detail::ktmap & x = singleton<detail::ktmap>::get_mutable_instance();
133 detail::ktmap::iterator start = x.lower_bound(this);
134 detail::ktmap::iterator end = x.upper_bound(this);
135 // remove entry in map which corresponds to this type
136 for(;start != end; ++start){
137 if(this == *start){
138 x.erase(start);
139 break;
140 }
141 }
142 }
143 }
144
145 BOOST_SERIALIZATION_DECL const extended_type_info *
find(const char * key)146 extended_type_info::find(const char *key) {
147 BOOST_ASSERT(NULL != key);
148 const detail::ktmap & k = singleton<detail::ktmap>::get_const_instance();
149 const detail::extended_type_info_arg eti_key(key);
150 const detail::ktmap::const_iterator it = k.find(& eti_key);
151 if(k.end() == it)
152 return NULL;
153 return *(it);
154 }
155
156 BOOST_SERIALIZATION_DECL
extended_type_info(const unsigned int type_info_key,const char * key)157 extended_type_info::extended_type_info(
158 const unsigned int type_info_key,
159 const char * key
160 ) :
161 m_type_info_key(type_info_key),
162 m_key(key)
163 {
164 }
165
166 BOOST_SERIALIZATION_DECL
~extended_type_info()167 extended_type_info::~extended_type_info(){
168 }
169
170 BOOST_SERIALIZATION_DECL bool
operator <(const extended_type_info & rhs) const171 extended_type_info::operator<(const extended_type_info &rhs) const {
172 // short cut for a common cases
173 if(this == & rhs)
174 return false;
175 if(m_type_info_key == rhs.m_type_info_key){
176 return is_less_than(rhs);
177 }
178 if(m_type_info_key < rhs.m_type_info_key)
179 return true;
180 return false;
181 }
182
183 BOOST_SERIALIZATION_DECL bool
operator ==(const extended_type_info & rhs) const184 extended_type_info::operator==(const extended_type_info &rhs) const {
185 // short cut for a common cases
186 if(this == & rhs)
187 return true;
188 if(m_type_info_key != rhs.m_type_info_key){
189 return false;
190 }
191 return is_equal(rhs);
192 }
193
194 } // namespace serialization
195 } // namespace boost
196