epoc32/include/stdapis/boost/multi_index/detail/index_saver.hpp
branchSymbian2
changeset 2 2fe1408b6811
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/epoc32/include/stdapis/boost/multi_index/detail/index_saver.hpp	Tue Mar 16 16:12:26 2010 +0000
     1.3 @@ -0,0 +1,135 @@
     1.4 +/* Copyright 2003-2005 Joaquín M López Muñoz.
     1.5 + * Distributed under the Boost Software License, Version 1.0.
     1.6 + * (See accompanying file LICENSE_1_0.txt or copy at
     1.7 + * http://www.boost.org/LICENSE_1_0.txt)
     1.8 + *
     1.9 + * See http://www.boost.org/libs/multi_index for library home page.
    1.10 + */
    1.11 +
    1.12 +#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_HPP
    1.13 +#define BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_HPP
    1.14 +
    1.15 +#if defined(_MSC_VER)&&(_MSC_VER>=1200)
    1.16 +#pragma once
    1.17 +#endif
    1.18 +
    1.19 +#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    1.20 +#include <boost/multi_index/detail/index_matcher.hpp>
    1.21 +#include <boost/noncopyable.hpp>
    1.22 +#include <boost/serialization/nvp.hpp>
    1.23 +#include <cstddef>
    1.24 +
    1.25 +namespace boost{
    1.26 +
    1.27 +namespace multi_index{
    1.28 +
    1.29 +namespace detail{
    1.30 +
    1.31 +/* index_saver accepts a base sequence of previously saved elements
    1.32 + * and saves a possibly reordered subsequence in an efficient manner,
    1.33 + * serializing only the information needed to rearrange the subsequence
    1.34 + * based on the original order of the base.
    1.35 + * multi_index_container is in charge of supplying the info about the
    1.36 + * base sequence, and each index can subsequently save itself using the
    1.37 + * const interface of index_saver.
    1.38 + */
    1.39 +
    1.40 +template<typename Node,typename Allocator>
    1.41 +class index_saver:private noncopyable
    1.42 +{
    1.43 +public:
    1.44 +  index_saver(const Allocator& al,std::size_t size):alg(al,size){}
    1.45 +
    1.46 +  template<class Archive>
    1.47 +  void add(Node* node,Archive& ar,const unsigned int)
    1.48 +  {
    1.49 +    ar<<serialization::make_nvp("position",*node);
    1.50 +    alg.add(node);
    1.51 +  }
    1.52 +
    1.53 +  template<class Archive>
    1.54 +  void add_track(Node* node,Archive& ar,const unsigned int)
    1.55 +  {
    1.56 +    ar<<serialization::make_nvp("position",*node);
    1.57 +  }
    1.58 +
    1.59 +  template<typename IndexIterator,class Archive>
    1.60 +  void save(
    1.61 +    IndexIterator first,IndexIterator last,Archive& ar,
    1.62 +    const unsigned int)const
    1.63 +  {
    1.64 +    /* calculate ordered positions */
    1.65 +
    1.66 +    alg.execute(first,last);
    1.67 +
    1.68 +    /* Given a consecutive subsequence of displaced elements
    1.69 +     * x1,...,xn, the following information is serialized:
    1.70 +     *
    1.71 +     *   p0,p1,...,pn,0
    1.72 +     *
    1.73 +     * where pi is a pointer to xi and p0 is a pointer to the element
    1.74 +     * preceding x1. Crealy, from this information is possible to
    1.75 +     * restore the original order on loading time. If x1 is the first
    1.76 +     * element in the sequence, the following is serialized instead:
    1.77 +     *
    1.78 +     *   p1,p1,...,pn,0
    1.79 +     *
    1.80 +     * For each subsequence of n elements, n+2 pointers are serialized.
    1.81 +     * An optimization policy is applied: consider for instance the
    1.82 +     * sequence
    1.83 +     *
    1.84 +     *   a,B,c,D
    1.85 +     * 
    1.86 +     * where B and D are displaced, but c is in its correct position.
    1.87 +     * Applying the schema described above we would serialize 6 pointers:
    1.88 +     *
    1.89 +     *  p(a),p(B),0
    1.90 +     *  p(c),p(D),0
    1.91 +     * 
    1.92 +     * but this can be reduced to 5 pointers by treating c as a displaced
    1.93 +     * element:
    1.94 +     *
    1.95 +     *  p(a),p(B),p(c),p(D),0
    1.96 +     */
    1.97 +
    1.98 +    std::size_t last_saved=3; /* distance to last pointer saved */
    1.99 +    for(IndexIterator it=first,prev=first;it!=last;prev=it++,++last_saved){
   1.100 +      if(!alg.is_ordered(get_node(it))){
   1.101 +        if(last_saved>1)save_node(get_node(prev),ar);
   1.102 +        save_node(get_node(it),ar);
   1.103 +        last_saved=0;
   1.104 +      }
   1.105 +      else if(last_saved==2)save_node(null_node(),ar);
   1.106 +    }
   1.107 +    if(last_saved<=2)save_node(null_node(),ar);
   1.108 +
   1.109 +    /* marks the end of the serialization info for [first,last) */
   1.110 +
   1.111 +    save_node(null_node(),ar);
   1.112 +  }
   1.113 +
   1.114 +private:
   1.115 +  template<typename IndexIterator>
   1.116 +  static Node* get_node(IndexIterator it)
   1.117 +  {
   1.118 +    return it.get_node();
   1.119 +  }
   1.120 +
   1.121 +  static Node* null_node(){return 0;}
   1.122 +
   1.123 +  template<typename Archive>
   1.124 +  static void save_node(Node* node,Archive& ar)
   1.125 +  {
   1.126 +    ar<<serialization::make_nvp("pointer",node);
   1.127 +  }
   1.128 +
   1.129 +  index_matcher::algorithm<Node,Allocator> alg;
   1.130 +};
   1.131 +
   1.132 +} /* namespace multi_index::detail */
   1.133 +
   1.134 +} /* namespace multi_index */
   1.135 +
   1.136 +} /* namespace boost */
   1.137 +
   1.138 +#endif