text: #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
  #define BOOST_ARCHIVE_OSERIALIZER_HPP
  
  // MS compatible compilers support #pragma once
  #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  # pragma once
  #pragma inline_depth(511)
  #pragma inline_recursion(on)
  #endif
  
  #if defined(__MWERKS__)
  #pragma inline_depth(511)
  #endif
  
  /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  // oserializer.hpp: interface for serialization system.
  
  // (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.
  
  #include <cassert>
  #include <cstddef> // NULL
  
  #include <boost/config.hpp>
  #include <boost/static_assert.hpp>
  #include <boost/detail/workaround.hpp>
  
  #include <boost/mpl/eval_if.hpp>
  #include <boost/mpl/equal_to.hpp>
  #include <boost/mpl/greater_equal.hpp>
  #include <boost/mpl/identity.hpp>
  
  #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
      #include <boost/serialization/extended_type_info_typeid.hpp>   
  #endif
  #include <boost/serialization/throw_exception.hpp>
  #include <boost/serialization/smart_cast.hpp>
  #include <boost/serialization/assume_abstract.hpp>
  #include <boost/serialization/static_warning.hpp>
  
  #include <boost/type_traits/is_pointer.hpp>
  #include <boost/type_traits/is_enum.hpp>
  #include <boost/type_traits/is_const.hpp>
  #include <boost/type_traits/is_polymorphic.hpp>
  #include <boost/type_traits/remove_extent.hpp>
  
  #include <boost/serialization/serialization.hpp>
  #include <boost/serialization/version.hpp>
  #include <boost/serialization/level.hpp>
  #include <boost/serialization/tracking.hpp>
  #include <boost/serialization/type_info_implementation.hpp>
  #include <boost/serialization/nvp.hpp>
  #include <boost/serialization/void_cast.hpp>
  #include <boost/serialization/array.hpp>
  #include <boost/serialization/collection_size_type.hpp>
  #include <boost/serialization/singleton.hpp>
  
  #include <boost/archive/archive_exception.hpp>
  #include <boost/archive/detail/basic_oarchive.hpp>
  #include <boost/archive/detail/basic_oserializer.hpp>
  #include <boost/archive/detail/basic_pointer_oserializer.hpp>
  #include <boost/archive/detail/archive_serializer_map.hpp>
  #include <boost/archive/detail/check.hpp>
  
  namespace boost {
  
  namespace serialization {
      class extended_type_info;
  } // namespace serialization
  
  namespace archive {
  
  // an accessor to permit friend access to archives.  Needed because
  // some compilers don't handle friend templates completely
  class save_access {
  public:
      template<class Archive>
      static void end_preamble(Archive & ar){
          ar.end_preamble();
      }
      template<class Archive, class T>
      static void save_primitive(Archive & ar, const  T & t){
          ar.end_preamble();
          ar.save(t);
      }
  };
  
  namespace detail {
  
  #ifdef BOOST_MSVC
  #  pragma warning(push)
  #  pragma warning(disable : 4511 4512)
  #endif
  
  template<class Archive, class T>
  class oserializer : public basic_oserializer
  {
  private:
      // private constructor to inhibit any existence other than the 
      // static one
  public:
      explicit BOOST_DLLEXPORT oserializer() :
          basic_oserializer(
              boost::serialization::singleton<
                  BOOST_DEDUCED_TYPENAME 
                  boost::serialization::type_info_implementation< T >::type
              >::get_const_instance()
          )
      {}
      virtual BOOST_DLLEXPORT void save_object_data(
          basic_oarchive & ar,    
          const void *x
      ) const BOOST_USED;
      virtual bool class_info() const {
          return boost::serialization::implementation_level< T >::value 
              >= boost::serialization::object_class_info;
      }
      virtual bool tracking(const unsigned int /* flags */) const {
          return boost::serialization::tracking_level< T >::value == boost::serialization::track_always
              || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively
                  && serialized_as_pointer());
      }
      virtual version_type version() const {
          return version_type(::boost::serialization::version< T >::value);
      }
      virtual bool is_polymorphic() const {
          return boost::is_polymorphic< T >::value;
      }
      virtual ~oserializer(){}
  };
  
  #ifdef BOOST_MSVC
  #  pragma warning(pop)
  #endif
  
  template<class Archive, class T>
  BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
      basic_oarchive & ar,    
      const void *x
  ) const {
      // make sure call is routed through the highest interface that might
      // be specialized by the user.
      BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
      boost::serialization::serialize_adl(
          boost::serialization::smart_cast_reference<Archive &>(ar),
          * static_cast<T *>(const_cast<void *>(x)),
          version()
      );
  }
  
  #ifdef BOOST_MSVC
  #  pragma warning(push)
  #  pragma warning(disable : 4511 4512)
  #endif
  
  template<class Archive, class T>
  class pointer_oserializer :
      public basic_pointer_oserializer
  {
  private:
      const basic_oserializer & 
      get_basic_serializer() const {
          return boost::serialization::singleton<
              oserializer<Archive, T>
          >::get_const_instance();
      }
      virtual BOOST_DLLEXPORT void save_object_ptr(
          basic_oarchive & ar,
          const void * x
      ) const BOOST_USED;
  public:
      pointer_oserializer();
      ~pointer_oserializer();
  };
  
  #ifdef BOOST_MSVC
  #  pragma warning(pop)
  #endif
  
  template<class Archive, class T>
  BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(
      basic_oarchive & ar,
      const void * x
  ) const {
      assert(NULL != x);
      // make sure call is routed through the highest interface that might
      // be specialized by the user.
      T * t = static_cast<T *>(const_cast<void *>(x));
      const unsigned int file_version = boost::serialization::version< T >::value;
      Archive & ar_impl 
          = boost::serialization::smart_cast_reference<Archive &>(ar);
      boost::serialization::save_construct_data_adl<Archive, T>(
          ar_impl, 
          t, 
          file_version
      );
      ar_impl << boost::serialization::make_nvp(NULL, * t);
  }
  
  template<class Archive, class T>
  pointer_oserializer<Archive, T>::pointer_oserializer() :
      basic_pointer_oserializer(
          boost::serialization::singleton<
              BOOST_DEDUCED_TYPENAME 
              boost::serialization::type_info_implementation< T >::type
          >::get_const_instance()
      )
  {
      // make sure appropriate member function is instantiated
      boost::serialization::singleton<
          oserializer<Archive, T> 
      >::get_mutable_instance().set_bpos(this);
      archive_serializer_map<Archive>::insert(this);
  }
  
  template<class Archive, class T>
  pointer_oserializer<Archive, T>::~pointer_oserializer(){
      archive_serializer_map<Archive>::erase(this);
  }
  
  template<class Archive>
  struct save_non_pointer_type {
      // note this bounces the call right back to the archive
      // with no runtime overhead
      struct save_primitive {
          template<class T>
          static void invoke(Archive & ar, const T & t){
              save_access::save_primitive(ar, t);
          }
      };
      // same as above but passes through serialization
      struct save_only {
          template<class T>
          static void invoke(Archive & ar, const T & t){
              // make sure call is routed through the highest interface that might
              // be specialized by the user.
              boost::serialization::serialize_adl(
                  ar, 
                  const_cast<T &>(t), 
                  ::boost::serialization::version< T >::value
              );
          }
      };
      // adds class information to the archive. This includes
      // serialization level and class version
      struct save_standard {
          template<class T>
          static void invoke(Archive &ar, const T & t){
              ar.save_object(
                  & t, 
                  boost::serialization::singleton<
                      oserializer<Archive, T>
                  >::get_const_instance()
              );
          }
      };
  
      // adds class information to the archive. This includes
      // serialization level and class version
      struct save_conditional {
          template<class T>
          static void invoke(Archive &ar, const T &t){
              //if(0 == (ar.get_flags() & no_tracking))
                  save_standard::invoke(ar, t);
              //else
              //   save_only::invoke(ar, t);
          }
      };
  
  
      template<class T>
      static void invoke(Archive & ar, const T & t){
          typedef 
              BOOST_DEDUCED_TYPENAME mpl::eval_if<
              // if its primitive
                  mpl::equal_to<
                      boost::serialization::implementation_level< T >,
                      mpl::int_<boost::serialization::primitive_type>
                  >,
                  mpl::identity<save_primitive>,
              // else
              BOOST_DEDUCED_TYPENAME mpl::eval_if<
                  // class info / version
                  mpl::greater_equal<
                      boost::serialization::implementation_level< T >,
                      mpl::int_<boost::serialization::object_class_info>
                  >,
                  // do standard save
                  mpl::identity<save_standard>,
              // else
              BOOST_DEDUCED_TYPENAME mpl::eval_if<
                      // no tracking
                  mpl::equal_to<
                      boost::serialization::tracking_level< T >,
                      mpl::int_<boost::serialization::track_never>
                  >,
                  // do a fast save
                  mpl::identity<save_only>,
              // else
                  // do a fast save only tracking is turned off
                  mpl::identity<save_conditional>
              > > >::type typex; 
          check_object_versioning< T >();
          typex::invoke(ar, t);
      }
      template<class T>
      static void invoke(Archive & ar, T & t){
          check_object_level< T >();
          check_object_tracking< T >();
          invoke(ar, const_cast<const T &>(t));
      }
  };
  
  template<class Archive>
  struct save_pointer_type {
      struct abstract
      {
          template<class T>
          static const basic_pointer_oserializer * register_type(Archive & /* ar */){
              // it has? to be polymorphic
              BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
              return NULL;
          }
      };
  
      struct non_abstract
      {
          template<class T>
          static const basic_pointer_oserializer * register_type(Archive & ar){
              return ar.register_type(static_cast<T *>(NULL));
          }
      };
  
      template<class T>
      static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
          // there should never be any need to save an abstract polymorphic 
          // class pointer.  Inhibiting code generation for this
          // permits abstract base classes to be used - note: exception
          // virtual serialize functions used for plug-ins
          typedef 
              BOOST_DEDUCED_TYPENAME mpl::eval_if<
                  boost::serialization::is_abstract< T >,
                  mpl::identity<abstract>,
                  mpl::identity<non_abstract>       
              >::type typex;
          return typex::template register_type< T >(ar);
      }
  
      struct non_polymorphic
      {
          template<class T>
          static void save(
              Archive &ar, 
              T & t
          ){
              const basic_pointer_oserializer & bpos = 
                  boost::serialization::singleton<
                      pointer_oserializer<Archive, T>
                  >::get_const_instance();
              // save the requested pointer type
              ar.save_pointer(& t, & bpos);
          }
      };
  
      struct polymorphic
      {
          template<class T>
          static void save(
              Archive &ar, 
              T & t
          ){
              BOOST_DEDUCED_TYPENAME 
              boost::serialization::type_info_implementation< T >::type const
              & i = boost::serialization::singleton<
                  BOOST_DEDUCED_TYPENAME 
                  boost::serialization::type_info_implementation< T >::type
              >::get_const_instance();
  
              boost::serialization::extended_type_info const * const this_type = & i;
  
              // retrieve the true type of the object pointed to
              // if this assertion fails its an error in this library
              assert(NULL != this_type);
  
              const boost::serialization::extended_type_info * true_type =
                  i.get_derived_extended_type_info(t);
  
              // note:if this exception is thrown, be sure that derived pointer
              // is either registered or exported.
              if(NULL == true_type){
                  boost::serialization::throw_exception(
                      archive_exception(
                          archive_exception::unregistered_class,
                          "derived class not registered or exported"
                      )
                  );
              }
  
              // if its not a pointer to a more derived type
              const void *vp = static_cast<const void *>(&t);
              if(*this_type == *true_type){
                  const basic_pointer_oserializer * bpos = register_type(ar, t);
                  ar.save_pointer(vp, bpos);
                  return;
              }
              // convert pointer to more derived type. if this is thrown
              // it means that the base/derived relationship hasn't be registered
              vp = serialization::void_downcast(
                  *true_type, 
                  *this_type, 
                  static_cast<const void *>(&t)
              );
              if(NULL == vp){
                  boost::serialization::throw_exception(
                      archive_exception(
                          archive_exception::unregistered_cast,
                          true_type->get_debug_info(),
                          this_type->get_debug_info()
                      )
                  );
              }
  
              // since true_type is valid, and this only gets made if the 
              // pointer oserializer object has been created, this should never
              // fail
              const basic_pointer_oserializer * bpos
                  = static_cast<const basic_pointer_oserializer *>(
                      boost::serialization::singleton<
                          archive_serializer_map<Archive>
                      >::get_const_instance().find(*true_type)
                  );
              assert(NULL != bpos);
              if(NULL == bpos)
                  boost::serialization::throw_exception(
                      archive_exception(
                          archive_exception::unregistered_class,
                          bpos->get_debug_info()
                      )
                  );
              ar.save_pointer(vp, bpos);
          }
      };
  
      template<class T>
      static void save(
          Archive & ar, 
          const T & t
      ){
          check_pointer_level< T >();
          check_pointer_tracking< T >();
          typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
              is_polymorphic< T >,
              mpl::identity<polymorphic>,
              mpl::identity<non_polymorphic>
          >::type type;
          type::save(ar, const_cast<T &>(t));
      }
  
      template<class TPtr>
      static void invoke(Archive &ar, const TPtr t){
          register_type(ar, * t);
          if(NULL == t){
              basic_oarchive & boa 
                  = boost::serialization::smart_cast_reference<basic_oarchive &>(ar);
              boa.save_null_pointer();
              save_access::end_preamble(ar);
              return;
          }
          save(ar, * t);
      }
  };
  
  template<class Archive>
  struct save_enum_type
  {
      template<class T>
      static void invoke(Archive &ar, const T &t){
          // convert enum to integers on save
          const int i = static_cast<int>(t);
          ar << boost::serialization::make_nvp(NULL, i);
      }
  };
  
  template<class Archive>
  struct save_array_type
  {
      template<class T>
      static void invoke(Archive &ar, const T &t){
          typedef BOOST_DEDUCED_TYPENAME boost::remove_extent< T >::type value_type;
          
          save_access::end_preamble(ar);
          // consider alignment
          std::size_t c = sizeof(t) / (
              static_cast<const char *>(static_cast<const void *>(&t[1])) 
              - static_cast<const char *>(static_cast<const void *>(&t[0]))
          );
          boost::serialization::collection_size_type count(c);
          ar << BOOST_SERIALIZATION_NVP(count);
          ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count);
      }
  };
  
  } // detail
  
  template<class Archive, class T>
  inline void save(Archive & ar, /*const*/ T &t){
      typedef 
          BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
              mpl::identity<detail::save_pointer_type<Archive> >,
          //else
          BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
              mpl::identity<detail::save_enum_type<Archive> >,
          //else
          BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
              mpl::identity<detail::save_array_type<Archive> >,
          //else
              mpl::identity<detail::save_non_pointer_type<Archive> >
          >
          >
          >::type typex;
      typex::invoke(ar, t);
  }
  
  } // namespace archive
  } // namespace boost
  
  #endif // BOOST_ARCHIVE_OSERIALIZER_HPP
  