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
|