epoc32/include/stdapis/boost/multi_index/detail/index_saver.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
williamr@2
     1
/* Copyright 2003-2005 Joaquín M López Muñoz.
williamr@2
     2
 * Distributed under the Boost Software License, Version 1.0.
williamr@2
     3
 * (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     4
 * http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     5
 *
williamr@2
     6
 * See http://www.boost.org/libs/multi_index for library home page.
williamr@2
     7
 */
williamr@2
     8
williamr@2
     9
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_HPP
williamr@2
    10
#define BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_HPP
williamr@2
    11
williamr@2
    12
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
williamr@2
    13
#pragma once
williamr@2
    14
#endif
williamr@2
    15
williamr@2
    16
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
williamr@2
    17
#include <boost/multi_index/detail/index_matcher.hpp>
williamr@2
    18
#include <boost/noncopyable.hpp>
williamr@2
    19
#include <boost/serialization/nvp.hpp>
williamr@2
    20
#include <cstddef>
williamr@2
    21
williamr@2
    22
namespace boost{
williamr@2
    23
williamr@2
    24
namespace multi_index{
williamr@2
    25
williamr@2
    26
namespace detail{
williamr@2
    27
williamr@2
    28
/* index_saver accepts a base sequence of previously saved elements
williamr@2
    29
 * and saves a possibly reordered subsequence in an efficient manner,
williamr@2
    30
 * serializing only the information needed to rearrange the subsequence
williamr@2
    31
 * based on the original order of the base.
williamr@2
    32
 * multi_index_container is in charge of supplying the info about the
williamr@2
    33
 * base sequence, and each index can subsequently save itself using the
williamr@2
    34
 * const interface of index_saver.
williamr@2
    35
 */
williamr@2
    36
williamr@2
    37
template<typename Node,typename Allocator>
williamr@2
    38
class index_saver:private noncopyable
williamr@2
    39
{
williamr@2
    40
public:
williamr@2
    41
  index_saver(const Allocator& al,std::size_t size):alg(al,size){}
williamr@2
    42
williamr@2
    43
  template<class Archive>
williamr@2
    44
  void add(Node* node,Archive& ar,const unsigned int)
williamr@2
    45
  {
williamr@2
    46
    ar<<serialization::make_nvp("position",*node);
williamr@2
    47
    alg.add(node);
williamr@2
    48
  }
williamr@2
    49
williamr@2
    50
  template<class Archive>
williamr@2
    51
  void add_track(Node* node,Archive& ar,const unsigned int)
williamr@2
    52
  {
williamr@2
    53
    ar<<serialization::make_nvp("position",*node);
williamr@2
    54
  }
williamr@2
    55
williamr@2
    56
  template<typename IndexIterator,class Archive>
williamr@2
    57
  void save(
williamr@2
    58
    IndexIterator first,IndexIterator last,Archive& ar,
williamr@2
    59
    const unsigned int)const
williamr@2
    60
  {
williamr@2
    61
    /* calculate ordered positions */
williamr@2
    62
williamr@2
    63
    alg.execute(first,last);
williamr@2
    64
williamr@2
    65
    /* Given a consecutive subsequence of displaced elements
williamr@2
    66
     * x1,...,xn, the following information is serialized:
williamr@2
    67
     *
williamr@2
    68
     *   p0,p1,...,pn,0
williamr@2
    69
     *
williamr@2
    70
     * where pi is a pointer to xi and p0 is a pointer to the element
williamr@2
    71
     * preceding x1. Crealy, from this information is possible to
williamr@2
    72
     * restore the original order on loading time. If x1 is the first
williamr@2
    73
     * element in the sequence, the following is serialized instead:
williamr@2
    74
     *
williamr@2
    75
     *   p1,p1,...,pn,0
williamr@2
    76
     *
williamr@2
    77
     * For each subsequence of n elements, n+2 pointers are serialized.
williamr@2
    78
     * An optimization policy is applied: consider for instance the
williamr@2
    79
     * sequence
williamr@2
    80
     *
williamr@2
    81
     *   a,B,c,D
williamr@2
    82
     * 
williamr@2
    83
     * where B and D are displaced, but c is in its correct position.
williamr@2
    84
     * Applying the schema described above we would serialize 6 pointers:
williamr@2
    85
     *
williamr@2
    86
     *  p(a),p(B),0
williamr@2
    87
     *  p(c),p(D),0
williamr@2
    88
     * 
williamr@2
    89
     * but this can be reduced to 5 pointers by treating c as a displaced
williamr@2
    90
     * element:
williamr@2
    91
     *
williamr@2
    92
     *  p(a),p(B),p(c),p(D),0
williamr@2
    93
     */
williamr@2
    94
williamr@2
    95
    std::size_t last_saved=3; /* distance to last pointer saved */
williamr@2
    96
    for(IndexIterator it=first,prev=first;it!=last;prev=it++,++last_saved){
williamr@2
    97
      if(!alg.is_ordered(get_node(it))){
williamr@2
    98
        if(last_saved>1)save_node(get_node(prev),ar);
williamr@2
    99
        save_node(get_node(it),ar);
williamr@2
   100
        last_saved=0;
williamr@2
   101
      }
williamr@2
   102
      else if(last_saved==2)save_node(null_node(),ar);
williamr@2
   103
    }
williamr@2
   104
    if(last_saved<=2)save_node(null_node(),ar);
williamr@2
   105
williamr@2
   106
    /* marks the end of the serialization info for [first,last) */
williamr@2
   107
williamr@2
   108
    save_node(null_node(),ar);
williamr@2
   109
  }
williamr@2
   110
williamr@2
   111
private:
williamr@2
   112
  template<typename IndexIterator>
williamr@2
   113
  static Node* get_node(IndexIterator it)
williamr@2
   114
  {
williamr@2
   115
    return it.get_node();
williamr@2
   116
  }
williamr@2
   117
williamr@2
   118
  static Node* null_node(){return 0;}
williamr@2
   119
williamr@2
   120
  template<typename Archive>
williamr@2
   121
  static void save_node(Node* node,Archive& ar)
williamr@2
   122
  {
williamr@2
   123
    ar<<serialization::make_nvp("pointer",node);
williamr@2
   124
  }
williamr@2
   125
williamr@2
   126
  index_matcher::algorithm<Node,Allocator> alg;
williamr@2
   127
};
williamr@2
   128
williamr@2
   129
} /* namespace multi_index::detail */
williamr@2
   130
williamr@2
   131
} /* namespace multi_index */
williamr@2
   132
williamr@2
   133
} /* namespace boost */
williamr@2
   134
williamr@2
   135
#endif