Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.

libs/serialization/src/void_cast.cpp

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// void_cast.cpp: implementation of run-time casting of void pointers

// (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)
// <gennadiy.rozental@tfn.com>

//  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 <cassert>
#include <cstddef> // NULL

// STL
#include <vector>
#include <functional>
#include <algorithm>
#include <cassert>

// BOOST
#define BOOST_SERIALIZATION_SOURCE
#include <boost/serialization/singleton.hpp>

#define BOOST_SERIALIZATION_SOURCE
#include <boost/serialization/extended_type_info.hpp>
#include <boost/serialization/void_cast.hpp>

namespace boost { 
namespace serialization {
namespace void_cast_detail {

typedef std::vector<const void_caster *> set_type;
typedef boost::serialization::singleton<set_type> void_caster_registry;

inline bool
void_caster::operator==(void_caster const & rhs) const{
    if(m_derived != rhs.m_derived)
        return false;
    if(m_base != rhs.m_base)
        return false;
    return true;
}

// implementation of void caster base class
BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
void_caster::void_caster(
    extended_type_info const & derived,
    extended_type_info const & base 
) :
    m_derived(derived),
    m_base(base)
{}

BOOST_SERIALIZATION_DECL(void)
void_caster::static_register() const {
    void_caster_registry::get_mutable_instance().push_back(this);
    // to do - add new void_caster_derived entries
    // which can be generated by adding this new primitive
    /*
    while(){
        if(!extend_down(this)
        && !extend_up(this))
            break;
    }
    */
}

BOOST_SERIALIZATION_DECL(void)
void_caster::static_unregister() const {
    if(! void_caster_registry::is_destroyed()){
        void_cast_detail::set_type & st 
            = void_caster_registry::get_mutable_instance();
        void_cast_detail::set_type::iterator it;
        it = std::find(st.begin(), st.end(), this);
        assert(st.end() != it);
        st.erase(it);
        // to do - remove all void_caster_derived entries
        // which depend upon this primitive
        /*
        while(){
            if(!truncate_down(this)
            && !truncate_up(this))
                break;
        }
        */
    }
}

#if 0
// implementation of shortcut void caster
class void_caster_derived : public void_caster
{
    std::ptrdiff_t difference;
    virtual void const *
    upcast(void const * const t) const{
        return static_cast<const char *> ( t ) + difference;
    }
    virtual void const *
    downcast(void const * const t) const{
        return static_cast<const char *> ( t ) - difference;
    }
public:
    void_caster_derived(
        extended_type_info const & derived,
        extended_type_info const & base,
        std::ptrdiff_t difference
    ) :
        void_caster(derived, base),
        difference( difference )
    {
        this->static_register();
    }
    ~void_caster_derived(){
        this->static_unregister();
    }
};
#endif

// just used as a search key
class void_caster_argument : public void_caster
{
    virtual void const *
    upcast(void const * const t) const {
        assert(false);
        return NULL;
    }
    virtual void const *
    downcast( void const * const t) const {
        assert(false);
        return NULL;
    }
public:
    void_caster_argument(
        extended_type_info const & derived,
        extended_type_info const & base
    ) :
        void_caster(derived, base)
    {}
    ~void_caster_argument(){};
};

struct match {
    void_cast_detail::void_caster_argument const * const m_ca;

    match(void_cast_detail::void_caster_argument const * const ca) :
        m_ca(ca)
    {}
    bool operator()(const void_cast_detail::void_caster * vc){
        return * vc == * m_ca;
    };
};

} // namespace void_cast_detail

// Given a void *, assume that it really points to an instance of one type
// and alter it so that it would point to an instance of a related type.
// Return the altered pointer. If there exists no sequence of casts that
// can transform from_type to to_type, return a NULL.  
BOOST_SERIALIZATION_DECL(void const *)  
void_upcast(
    extended_type_info const & derived,
    extended_type_info const & base,
    void const * const t
){
    // same types - trivial case
    if (derived == base)
        return t;

    // check to see if base/derived pair is found in the registry
    const void_cast_detail::set_type & s
        = void_cast_detail::void_caster_registry::get_const_instance();
    void_cast_detail::set_type::const_iterator it;
    void_cast_detail::void_caster_argument ca(derived, base);

    it = std::find_if(
        s.begin(), 
        s.end(),
        void_cast_detail::match(& ca)
    );
    
    // if so
    if (s.end() != it)
        // we're done
        return (*it)->upcast(t);

    // try to find a chain that gives us what we want
    for(it = s.begin(); it != s.end(); ++it){
        // if the current candidate doesn't cast to the desired target type
        if((*it)->m_base == base){
            // if the current candidate casts from the desired source type
            if ((*it)->m_derived == derived){
                // we have a base/derived match - we're done
                // cast to the intermediate type
                return (*it)->upcast(t);
            }
            const void * t_new;
            t_new = void_upcast(derived, (*it)->m_derived, t);
            if(NULL != t_new)
                return (*it)->upcast(t_new);
        }
    }
    return NULL;
}

BOOST_SERIALIZATION_DECL(void const *)  
void_downcast(
    extended_type_info const & derived,
    extended_type_info const & base,
    void const * const t
){
    // same types - trivial case
    if (derived == base)
        return t;

    // check to see if base/derived pair is found in the registry
    const void_cast_detail::set_type & s
        = void_cast_detail::void_caster_registry::get_const_instance();
    void_cast_detail::set_type::const_iterator it;
    void_cast_detail::void_caster_argument ca(derived, base);

    it = std::find_if(
        s.begin(), 
        s.end(),
        void_cast_detail::match(& ca)
    );
        
    // if so
    if (s.end() != it)
        // we're done
        return(*it)->downcast(t);

    // try to find a chain that gives us what we want
    for(it = s.begin(); it != s.end(); ++it){
        // if the current candidate doesn't cast to the desired target type
        if ((*it)->m_derived == derived){
            // if the current candidate casts from the desired source type
            if ((*it)->m_base == base){
                // we have a base/derived match - we're done
                // cast to the intermediate type
                return (*it)->downcast(t);
            }
            const void * t_new;
            t_new = void_downcast((*it)->m_base, base, t);
            if(NULL != t_new)
                return (*it)->downcast(t_new);
        }
    }
    return NULL;
}

} // namespace serialization
} // namespace boost

// EOF