You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
135 lines
3.7 KiB
135 lines
3.7 KiB
/* Copyright 2003-2008 Joaquin M Lopez Munoz. |
|
* Distributed under the Boost Software License, Version 1.0. |
|
* (See accompanying file LICENSE_1_0.txt or copy at |
|
* http://www.boost.org/LICENSE_1_0.txt) |
|
* |
|
* See http://www.boost.org/libs/multi_index for library home page. |
|
*/ |
|
|
|
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_HPP |
|
#define BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_HPP |
|
|
|
#if defined(_MSC_VER)&&(_MSC_VER>=1200) |
|
#pragma once |
|
#endif |
|
|
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
|
#include <boost/multi_index/detail/index_matcher.hpp> |
|
#include <boost/noncopyable.hpp> |
|
#include <boost/serialization/nvp.hpp> |
|
#include <cstddef> |
|
|
|
namespace boost{ |
|
|
|
namespace multi_index{ |
|
|
|
namespace detail{ |
|
|
|
/* index_saver accepts a base sequence of previously saved elements |
|
* and saves a possibly reordered subsequence in an efficient manner, |
|
* serializing only the information needed to rearrange the subsequence |
|
* based on the original order of the base. |
|
* multi_index_container is in charge of supplying the info about the |
|
* base sequence, and each index can subsequently save itself using the |
|
* const interface of index_saver. |
|
*/ |
|
|
|
template<typename Node,typename Allocator> |
|
class index_saver:private noncopyable |
|
{ |
|
public: |
|
index_saver(const Allocator& al,std::size_t size):alg(al,size){} |
|
|
|
template<class Archive> |
|
void add(Node* node,Archive& ar,const unsigned int) |
|
{ |
|
ar<<serialization::make_nvp("position",*node); |
|
alg.add(node); |
|
} |
|
|
|
template<class Archive> |
|
void add_track(Node* node,Archive& ar,const unsigned int) |
|
{ |
|
ar<<serialization::make_nvp("position",*node); |
|
} |
|
|
|
template<typename IndexIterator,class Archive> |
|
void save( |
|
IndexIterator first,IndexIterator last,Archive& ar, |
|
const unsigned int)const |
|
{ |
|
/* calculate ordered positions */ |
|
|
|
alg.execute(first,last); |
|
|
|
/* Given a consecutive subsequence of displaced elements |
|
* x1,...,xn, the following information is serialized: |
|
* |
|
* p0,p1,...,pn,0 |
|
* |
|
* where pi is a pointer to xi and p0 is a pointer to the element |
|
* preceding x1. Crealy, from this information is possible to |
|
* restore the original order on loading time. If x1 is the first |
|
* element in the sequence, the following is serialized instead: |
|
* |
|
* p1,p1,...,pn,0 |
|
* |
|
* For each subsequence of n elements, n+2 pointers are serialized. |
|
* An optimization policy is applied: consider for instance the |
|
* sequence |
|
* |
|
* a,B,c,D |
|
* |
|
* where B and D are displaced, but c is in its correct position. |
|
* Applying the schema described above we would serialize 6 pointers: |
|
* |
|
* p(a),p(B),0 |
|
* p(c),p(D),0 |
|
* |
|
* but this can be reduced to 5 pointers by treating c as a displaced |
|
* element: |
|
* |
|
* p(a),p(B),p(c),p(D),0 |
|
*/ |
|
|
|
std::size_t last_saved=3; /* distance to last pointer saved */ |
|
for(IndexIterator it=first,prev=first;it!=last;prev=it++,++last_saved){ |
|
if(!alg.is_ordered(get_node(it))){ |
|
if(last_saved>1)save_node(get_node(prev),ar); |
|
save_node(get_node(it),ar); |
|
last_saved=0; |
|
} |
|
else if(last_saved==2)save_node(null_node(),ar); |
|
} |
|
if(last_saved<=2)save_node(null_node(),ar); |
|
|
|
/* marks the end of the serialization info for [first,last) */ |
|
|
|
save_node(null_node(),ar); |
|
} |
|
|
|
private: |
|
template<typename IndexIterator> |
|
static Node* get_node(IndexIterator it) |
|
{ |
|
return it.get_node(); |
|
} |
|
|
|
static Node* null_node(){return 0;} |
|
|
|
template<typename Archive> |
|
static void save_node(Node* node,Archive& ar) |
|
{ |
|
ar<<serialization::make_nvp("pointer",node); |
|
} |
|
|
|
index_matcher::algorithm<Node,Allocator> alg; |
|
}; |
|
|
|
} /* namespace multi_index::detail */ |
|
|
|
} /* namespace multi_index */ |
|
|
|
} /* namespace boost */ |
|
|
|
#endif
|
|
|