1 | /* Copyright 2003-2005 Joaquín M López Muñoz. |
---|
2 | * Distributed under the Boost Software License, Version 1.0. |
---|
3 | * (See accompanying file LICENSE_1_0.txt or copy at |
---|
4 | * http://www.boost.org/LICENSE_1_0.txt) |
---|
5 | * |
---|
6 | * See http://www.boost.org/libs/multi_index for library home page. |
---|
7 | */ |
---|
8 | |
---|
9 | #ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_LOADER_HPP |
---|
10 | #define BOOST_MULTI_INDEX_DETAIL_INDEX_LOADER_HPP |
---|
11 | |
---|
12 | #if defined(_MSC_VER)&&(_MSC_VER>=1200) |
---|
13 | #pragma once |
---|
14 | #endif |
---|
15 | |
---|
16 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
---|
17 | #include <algorithm> |
---|
18 | #include <boost/archive/archive_exception.hpp> |
---|
19 | #include <boost/noncopyable.hpp> |
---|
20 | #include <boost/multi_index/detail/auto_space.hpp> |
---|
21 | #include <boost/serialization/nvp.hpp> |
---|
22 | #include <boost/throw_exception.hpp> |
---|
23 | #include <cstddef> |
---|
24 | |
---|
25 | namespace boost{ |
---|
26 | |
---|
27 | namespace multi_index{ |
---|
28 | |
---|
29 | namespace detail{ |
---|
30 | |
---|
31 | /* Counterpart of index_saver (check index_saver.hpp for serialization |
---|
32 | * details.)* multi_index_container is in charge of supplying the info about |
---|
33 | * the base sequence, and each index can subsequently load itself using the |
---|
34 | * const interface of index_loader. |
---|
35 | */ |
---|
36 | |
---|
37 | template<typename Node,typename FinalNode,typename Allocator> |
---|
38 | class index_loader:private noncopyable |
---|
39 | { |
---|
40 | public: |
---|
41 | index_loader(const Allocator& al,std::size_t size): |
---|
42 | spc(al,size),size_(size),n(0),sorted(false) |
---|
43 | { |
---|
44 | } |
---|
45 | |
---|
46 | template<class Archive> |
---|
47 | void add(Node* node,Archive& ar,const unsigned int) |
---|
48 | { |
---|
49 | ar>>serialization::make_nvp("position",*node); |
---|
50 | entries()[n++]=node; |
---|
51 | } |
---|
52 | |
---|
53 | template<class Archive> |
---|
54 | void add_track(Node* node,Archive& ar,const unsigned int) |
---|
55 | { |
---|
56 | ar>>serialization::make_nvp("position",*node); |
---|
57 | } |
---|
58 | |
---|
59 | /* A rearranger is passed two nodes, and is expected to |
---|
60 | * reposition the second after the first. |
---|
61 | * If the first node is 0, then the second should be moved |
---|
62 | * to the beginning of the sequence. |
---|
63 | */ |
---|
64 | |
---|
65 | template<typename Rearranger,class Archive> |
---|
66 | void load(Rearranger r,Archive& ar,const unsigned int)const |
---|
67 | { |
---|
68 | FinalNode* prev=unchecked_load_node(ar); |
---|
69 | if(!prev)return; |
---|
70 | |
---|
71 | if(!sorted){ |
---|
72 | std::sort(entries(),entries()+size_); |
---|
73 | sorted=true; |
---|
74 | } |
---|
75 | |
---|
76 | check_node(prev); |
---|
77 | |
---|
78 | for(;;){ |
---|
79 | for(;;){ |
---|
80 | FinalNode* node=load_node(ar); |
---|
81 | if(!node)break; |
---|
82 | |
---|
83 | if(node==prev)prev=0; |
---|
84 | r(prev,node); |
---|
85 | |
---|
86 | prev=node; |
---|
87 | } |
---|
88 | prev=load_node(ar); |
---|
89 | if(!prev)break; |
---|
90 | } |
---|
91 | } |
---|
92 | |
---|
93 | private: |
---|
94 | Node** entries()const{return spc.data();} |
---|
95 | |
---|
96 | /* We try to delay sorting as much as possible just in case it |
---|
97 | * is not necessary, hence this version of load_node. |
---|
98 | */ |
---|
99 | |
---|
100 | template<class Archive> |
---|
101 | FinalNode* unchecked_load_node(Archive& ar)const |
---|
102 | { |
---|
103 | Node* node=0; |
---|
104 | ar>>serialization::make_nvp("pointer",node); |
---|
105 | return static_cast<FinalNode*>(node); |
---|
106 | } |
---|
107 | |
---|
108 | template<class Archive> |
---|
109 | FinalNode* load_node(Archive& ar)const |
---|
110 | { |
---|
111 | Node* node=0; |
---|
112 | ar>>serialization::make_nvp("pointer",node); |
---|
113 | check_node(node); |
---|
114 | return static_cast<FinalNode*>(node); |
---|
115 | } |
---|
116 | |
---|
117 | void check_node(Node* node)const |
---|
118 | { |
---|
119 | if(node!=0&&!std::binary_search(entries(),entries()+size_,node)){ |
---|
120 | throw_exception( |
---|
121 | archive::archive_exception( |
---|
122 | archive::archive_exception::other_exception)); |
---|
123 | } |
---|
124 | } |
---|
125 | |
---|
126 | auto_space<Node*,Allocator> spc; |
---|
127 | std::size_t size_; |
---|
128 | std::size_t n; |
---|
129 | mutable bool sorted; |
---|
130 | }; |
---|
131 | |
---|
132 | } /* namespace multi_index::detail */ |
---|
133 | |
---|
134 | } /* namespace multi_index */ |
---|
135 | |
---|
136 | } /* namespace boost */ |
---|
137 | |
---|
138 | #endif |
---|