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