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