libs/serialization/src/extended_type_info.cpp
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// extended_type_info.cpp: implementation for portable version of type_info
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#if (defined _MSC_VER) && (_MSC_VER == 1200)
# pragma warning (disable : 4786) // too long name, harmless warning
#endif
#include <algorithm>
#include <set>
#include <utility>
#include <cassert>
#include <cstddef> // NULL
#include <boost/config.hpp> // msvc needs this to suppress warning
#include <cstring>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{ using ::strcmp; }
#endif
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/serialization/singleton.hpp>
#include <boost/serialization/force_include.hpp>
#define BOOST_SERIALIZATION_SOURCE
#include <boost/serialization/extended_type_info.hpp>
namespace boost {
namespace serialization {
namespace detail {
struct key_compare
{
bool
operator()(
const extended_type_info * lhs,
const extended_type_info * rhs
) const {
const char * l = lhs->get_key();
assert(NULL != l);
const char * r = rhs->get_key();
assert(NULL != r);
// performance shortcut
// shortcut to exploit string pooling
if(l == r)
return false;
// for exported types, use the string key so that
// multiple instances in different translation units
// can be matched up
return std::strcmp(l, r) < 0;
}
};
typedef std::multiset<const extended_type_info *, key_compare> ktmap;
class extended_type_info_arg : public extended_type_info
{
public:
extended_type_info_arg(const char * key) :
extended_type_info(NULL)
{
m_key = key;
}
~extended_type_info_arg(){
m_key = NULL;
}
};
} // namespace detail
BOOST_SERIALIZATION_DECL(void)
extended_type_info::key_register(const char *key) {
assert(NULL != key);
m_key = key;
singleton<detail::ktmap>::get_mutable_instance().insert(this);
}
BOOST_SERIALIZATION_DECL(void)
extended_type_info::key_unregister() {
assert(NULL != m_key);
if(! singleton<detail::ktmap>::is_destroyed()){
detail::ktmap & x = singleton<detail::ktmap>::get_mutable_instance();
detail::ktmap::iterator start = x.lower_bound(this);
detail::ktmap::iterator end = x.upper_bound(this);
assert(start != end);
// remove entry in map which corresponds to this type
do{
if(this == *start)
x.erase(start++);
else
++start;
}while(start != end);
}
m_key = NULL;
}
BOOST_SERIALIZATION_DECL(const extended_type_info *)
extended_type_info::find(const char *key) {
assert(NULL != key);
const detail::ktmap & k = singleton<detail::ktmap>::get_const_instance();
const detail::extended_type_info_arg eti_key(key);
const detail::ktmap::const_iterator it = k.find(& eti_key);
if(k.end() == it)
return NULL;
return *(it);
}
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
extended_type_info::extended_type_info(
const unsigned int type_info_key
) :
m_type_info_key(type_info_key),
m_key(NULL)
{
// make sure that the ktmap is instantiated before
// the first key is added to it.
singleton<detail::ktmap>::get_const_instance();
}
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
extended_type_info::~extended_type_info(){
if(NULL == m_key)
return;
key_unregister();
}
BOOST_SERIALIZATION_DECL(bool)
extended_type_info::operator<(const extended_type_info &rhs) const {
if(m_type_info_key == rhs.m_type_info_key){
return is_less_than(rhs);
}
if(m_type_info_key < rhs.m_type_info_key)
return true;
return false;
}
BOOST_SERIALIZATION_DECL(bool)
extended_type_info::operator==(const extended_type_info &rhs) const {
// short cut for a common cases
if(this == & rhs)
return true;
if(m_type_info_key != rhs.m_type_info_key){
return false;
}
return is_equal(rhs);
};
} // namespace serialization
} // namespace boost