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