1 /* Copyright 2003-2015 Joaquin M Lopez Munoz. 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) 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/multi_index/detail/raw_ptr.hpp> 22 #include <boost/serialization/nvp.hpp> 23 #include <boost/throw_exception.hpp> 24 #include <cstddef> 25 26 namespace pdalboost{ 27 28 namespace multi_index{ 29 30 namespace detail{ 31 32 /* Counterpart of index_saver (check index_saver.hpp for serialization 33 * details.)* multi_index_container is in charge of supplying the info about 34 * the base sequence, and each index can subsequently load itself using the 35 * const interface of index_loader. 36 */ 37 38 template<typename Node,typename FinalNode,typename Allocator> 39 class index_loader:private noncopyable 40 { 41 public: index_loader(const Allocator & al,std::size_t size)42 index_loader(const Allocator& al,std::size_t size): 43 spc(al,size),size_(size),n(0),sorted(false) 44 { 45 } 46 47 template<class Archive> add(Node * node,Archive & ar,const unsigned int)48 void add(Node* node,Archive& ar,const unsigned int) 49 { 50 ar>>serialization::make_nvp("position",*node); 51 entries()[n++]=node; 52 } 53 54 template<class Archive> add_track(Node * node,Archive & ar,const unsigned int)55 void add_track(Node* node,Archive& ar,const unsigned int) 56 { 57 ar>>serialization::make_nvp("position",*node); 58 } 59 60 /* A rearranger is passed two nodes, and is expected to 61 * reposition the second after the first. 62 * If the first node is 0, then the second should be moved 63 * to the beginning of the sequence. 64 */ 65 66 template<typename Rearranger,class Archive> load(Rearranger r,Archive & ar,const unsigned int) const67 void load(Rearranger r,Archive& ar,const unsigned int)const 68 { 69 FinalNode* prev=unchecked_load_node(ar); 70 if(!prev)return; 71 72 if(!sorted){ 73 std::sort(entries(),entries()+size_); 74 sorted=true; 75 } 76 77 check_node(prev); 78 79 for(;;){ 80 for(;;){ 81 FinalNode* node=load_node(ar); 82 if(!node)break; 83 84 if(node==prev)prev=0; 85 r(prev,node); 86 87 prev=node; 88 } 89 prev=load_node(ar); 90 if(!prev)break; 91 } 92 } 93 94 private: entries() const95 Node** entries()const{return raw_ptr<Node**>(spc.data());} 96 97 /* We try to delay sorting as much as possible just in case it 98 * is not necessary, hence this version of load_node. 99 */ 100 101 template<class Archive> unchecked_load_node(Archive & ar) const102 FinalNode* unchecked_load_node(Archive& ar)const 103 { 104 Node* node=0; 105 ar>>serialization::make_nvp("pointer",node); 106 return static_cast<FinalNode*>(node); 107 } 108 109 template<class Archive> load_node(Archive & ar) const110 FinalNode* load_node(Archive& ar)const 111 { 112 Node* node=0; 113 ar>>serialization::make_nvp("pointer",node); 114 check_node(node); 115 return static_cast<FinalNode*>(node); 116 } 117 check_node(Node * node) const118 void check_node(Node* node)const 119 { 120 if(node!=0&&!std::binary_search(entries(),entries()+size_,node)){ 121 throw_exception( 122 archive::archive_exception( 123 archive::archive_exception::other_exception)); 124 } 125 } 126 127 auto_space<Node*,Allocator> spc; 128 std::size_t size_; 129 std::size_t n; 130 mutable bool sorted; 131 }; 132 133 } /* namespace multi_index::detail */ 134 135 } /* namespace multi_index */ 136 137 } /* namespace pdalboost */ 138 139 #endif 140