1 // Boost.Geometry Index
2 //
3 // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
4 //
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
10 #define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
11 
12 //#include <boost/serialization/serialization.hpp>
13 #include <boost/serialization/split_member.hpp>
14 #include <boost/serialization/version.hpp>
15 //#include <boost/serialization/nvp.hpp>
16 
17 // TODO
18 // how about using the unsigned type capable of storing Max in compile-time versions?
19 
20 // TODO
21 // - add wrappers for Point and Box and implement serialize for those wrappers instead of
22 //   raw geometries
23 //   PROBLEM: after implementing this, how Values would be set?
24 // - store the name of the parameters to know how to load and detect errors
25 // - in the header, once store info about the Indexable and Bounds types (geometry type, point CS, Dim, etc.)
26 //   each geometry save without this info
27 
28 // TODO - move to index/detail/serialization.hpp
29 namespace boost { namespace geometry { namespace index { namespace detail {
30 
31 // TODO - use boost::move?
32 template<typename T>
33 class serialization_storage
34 {
35 public:
36     template <typename Archive>
serialization_storage(Archive & ar,unsigned int version)37     serialization_storage(Archive & ar, unsigned int version)
38     {
39         boost::serialization::load_construct_data_adl(ar, this->address(), version);
40     }
~serialization_storage()41     ~serialization_storage()
42     {
43         this->address()->~T();
44     }
address()45     T * address()
46     {
47         return static_cast<T*>(m_storage.address());
48     }
49 private:
50     boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> m_storage;
51 };
52 
53 // TODO - save and load item_version? see: collections_load_imp and collections_save_imp
54 // this should be done once for the whole container
55 // versions of all used types should be stored
56 
57 template <typename T, typename Archive> inline
serialization_load(const char * name,Archive & ar)58 T serialization_load(const char * name, Archive & ar)
59 {
60     namespace bs = boost::serialization;
61     serialization_storage<T> storage(ar, bs::version<T>::value);        // load_construct_data
62     ar >> boost::serialization::make_nvp(name, *storage.address());   // serialize
63     //ar >> *storage.address();                                           // serialize
64     return *storage.address();
65 }
66 
67 template <typename T, typename Archive> inline
serialization_save(T const & t,const char * name,Archive & ar)68 void serialization_save(T const& t, const char * name, Archive & ar)
69 {
70     namespace bs = boost::serialization;
71     bs::save_construct_data_adl(ar, boost::addressof(t), bs::version<T>::value);  // save_construct_data
72     ar << boost::serialization::make_nvp(name, t);                                // serialize
73     //ar << t;                                                                      // serialize
74 }
75 
76 }}}}
77 
78 // TODO - move to index/serialization/rtree.hpp
79 namespace boost { namespace serialization {
80 
81 // boost::geometry::index::linear
82 
83 template<class Archive, size_t Max, size_t Min>
save_construct_data(Archive & ar,const boost::geometry::index::linear<Max,Min> * params,unsigned int)84 void save_construct_data(Archive & ar, const boost::geometry::index::linear<Max, Min> * params, unsigned int )
85 {
86     size_t max = params->get_max_elements(), min = params->get_min_elements();
87     ar << boost::serialization::make_nvp("max", max);
88     ar << boost::serialization::make_nvp("min", min);
89 }
90 template<class Archive, size_t Max, size_t Min>
load_construct_data(Archive & ar,boost::geometry::index::linear<Max,Min> * params,unsigned int)91 void load_construct_data(Archive & ar, boost::geometry::index::linear<Max, Min> * params, unsigned int )
92 {
93     size_t max, min;
94     ar >> boost::serialization::make_nvp("max", max);
95     ar >> boost::serialization::make_nvp("min", min);
96     if ( max != params->get_max_elements() || min != params->get_min_elements() )
97         // TODO change exception type
98         BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
99     // the constructor musn't be called for this type
100     //::new(params)boost::geometry::index::linear<Max, Min>();
101 }
serialize(Archive &,boost::geometry::index::linear<Max,Min> &,unsigned int)102 template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::linear<Max, Min> &, unsigned int) {}
103 
104 // boost::geometry::index::quadratic
105 
106 template<class Archive, size_t Max, size_t Min>
save_construct_data(Archive & ar,const boost::geometry::index::quadratic<Max,Min> * params,unsigned int)107 void save_construct_data(Archive & ar, const boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
108 {
109     size_t max = params->get_max_elements(), min = params->get_min_elements();
110     ar << boost::serialization::make_nvp("max", max);
111     ar << boost::serialization::make_nvp("min", min);
112 }
113 template<class Archive, size_t Max, size_t Min>
load_construct_data(Archive & ar,boost::geometry::index::quadratic<Max,Min> * params,unsigned int)114 void load_construct_data(Archive & ar, boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
115 {
116     size_t max, min;
117     ar >> boost::serialization::make_nvp("max", max);
118     ar >> boost::serialization::make_nvp("min", min);
119     if ( max != params->get_max_elements() || min != params->get_min_elements() )
120         // TODO change exception type
121         BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
122     // the constructor musn't be called for this type
123     //::new(params)boost::geometry::index::quadratic<Max, Min>();
124 }
serialize(Archive &,boost::geometry::index::quadratic<Max,Min> &,unsigned int)125 template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::quadratic<Max, Min> &, unsigned int) {}
126 
127 // boost::geometry::index::rstar
128 
129 template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
save_construct_data(Archive & ar,const boost::geometry::index::rstar<Max,Min,RE,OCT> * params,unsigned int)130 void save_construct_data(Archive & ar, const boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
131 {
132     size_t max = params->get_max_elements()
133          , min = params->get_min_elements()
134          , re = params->get_reinserted_elements()
135          , oct = params->get_overlap_cost_threshold();
136     ar << boost::serialization::make_nvp("max", max);
137     ar << boost::serialization::make_nvp("min", min);
138     ar << boost::serialization::make_nvp("re", re);
139     ar << boost::serialization::make_nvp("oct", oct);
140 }
141 template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
load_construct_data(Archive & ar,boost::geometry::index::rstar<Max,Min,RE,OCT> * params,unsigned int)142 void load_construct_data(Archive & ar, boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
143 {
144     size_t max, min, re, oct;
145     ar >> boost::serialization::make_nvp("max", max);
146     ar >> boost::serialization::make_nvp("min", min);
147     ar >> boost::serialization::make_nvp("re", re);
148     ar >> boost::serialization::make_nvp("oct", oct);
149     if ( max != params->get_max_elements() || min != params->get_min_elements() ||
150          re != params->get_reinserted_elements() || oct != params->get_overlap_cost_threshold() )
151         // TODO change exception type
152         BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
153     // the constructor musn't be called for this type
154     //::new(params)boost::geometry::index::rstar<Max, Min, RE, OCT>();
155 }
156 template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
serialize(Archive &,boost::geometry::index::rstar<Max,Min,RE,OCT> &,unsigned int)157 void serialize(Archive &, boost::geometry::index::rstar<Max, Min, RE, OCT> &, unsigned int) {}
158 
159 // boost::geometry::index::dynamic_linear
160 
161 template<class Archive>
save_construct_data(Archive & ar,const boost::geometry::index::dynamic_linear * params,unsigned int)162 inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_linear * params, unsigned int )
163 {
164     size_t max = params->get_max_elements(), min = params->get_min_elements();
165     ar << boost::serialization::make_nvp("max", max);
166     ar << boost::serialization::make_nvp("min", min);
167 }
168 template<class Archive>
load_construct_data(Archive & ar,boost::geometry::index::dynamic_linear * params,unsigned int)169 inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_linear * params, unsigned int )
170 {
171     size_t max, min;
172     ar >> boost::serialization::make_nvp("max", max);
173     ar >> boost::serialization::make_nvp("min", min);
174     ::new(params)boost::geometry::index::dynamic_linear(max, min);
175 }
serialize(Archive &,boost::geometry::index::dynamic_linear &,unsigned int)176 template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_linear &, unsigned int) {}
177 
178 // boost::geometry::index::dynamic_quadratic
179 
180 template<class Archive>
save_construct_data(Archive & ar,const boost::geometry::index::dynamic_quadratic * params,unsigned int)181 inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_quadratic * params, unsigned int )
182 {
183     size_t max = params->get_max_elements(), min = params->get_min_elements();
184     ar << boost::serialization::make_nvp("max", max);
185     ar << boost::serialization::make_nvp("min", min);
186 }
187 template<class Archive>
load_construct_data(Archive & ar,boost::geometry::index::dynamic_quadratic * params,unsigned int)188 inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_quadratic * params, unsigned int )
189 {
190     size_t max, min;
191     ar >> boost::serialization::make_nvp("max", max);
192     ar >> boost::serialization::make_nvp("min", min);
193     ::new(params)boost::geometry::index::dynamic_quadratic(max, min);
194 }
serialize(Archive &,boost::geometry::index::dynamic_quadratic &,unsigned int)195 template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_quadratic &, unsigned int) {}
196 
197 // boost::geometry::index::dynamic_rstar
198 
199 template<class Archive>
save_construct_data(Archive & ar,const boost::geometry::index::dynamic_rstar * params,unsigned int)200 inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_rstar * params, unsigned int )
201 {
202     size_t max = params->get_max_elements()
203          , min = params->get_min_elements()
204          , re = params->get_reinserted_elements()
205          , oct = params->get_overlap_cost_threshold();
206     ar << boost::serialization::make_nvp("max", max);
207     ar << boost::serialization::make_nvp("min", min);
208     ar << boost::serialization::make_nvp("re", re);
209     ar << boost::serialization::make_nvp("oct", oct);
210 }
211 template<class Archive>
load_construct_data(Archive & ar,boost::geometry::index::dynamic_rstar * params,unsigned int)212 inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_rstar * params, unsigned int )
213 {
214     size_t max, min, re, oct;
215     ar >> boost::serialization::make_nvp("max", max);
216     ar >> boost::serialization::make_nvp("min", min);
217     ar >> boost::serialization::make_nvp("re", re);
218     ar >> boost::serialization::make_nvp("oct", oct);
219     ::new(params)boost::geometry::index::dynamic_rstar(max, min, re, oct);
220 }
serialize(Archive &,boost::geometry::index::dynamic_rstar &,unsigned int)221 template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_rstar &, unsigned int) {}
222 
223 }} // boost::serialization
224 
225 // TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
226 namespace boost { namespace geometry { namespace index { namespace detail {
227 
228 template <typename P, size_t I = 0, size_t D = geometry::dimension<P>::value>
229 struct serialize_point
230 {
231     template <typename Archive>
saveboost::geometry::index::detail::serialize_point232     static inline void save(Archive & ar, P const& p, unsigned int version)
233     {
234         typename coordinate_type<P>::type c = get<I>(p);
235         ar << boost::serialization::make_nvp("c", c);
236         serialize_point<P, I+1, D>::save(ar, p, version);
237     }
238 
239     template <typename Archive>
loadboost::geometry::index::detail::serialize_point240     static inline void load(Archive & ar, P & p, unsigned int version)
241     {
242         typename geometry::coordinate_type<P>::type c;
243         ar >> boost::serialization::make_nvp("c", c);
244         set<I>(p, c);
245         serialize_point<P, I+1, D>::load(ar, p, version);
246     }
247 };
248 
249 template <typename P, size_t D>
250 struct serialize_point<P, D, D>
251 {
saveboost::geometry::index::detail::serialize_point252     template <typename Archive> static inline void save(Archive &, P const&, unsigned int) {}
loadboost::geometry::index::detail::serialize_point253     template <typename Archive> static inline void load(Archive &, P &, unsigned int) {}
254 };
255 
256 }}}}
257 
258 // TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
259 namespace boost { namespace serialization {
260 
261 template<class Archive, typename T, size_t D, typename C>
save(Archive & ar,boost::geometry::model::point<T,D,C> const & p,unsigned int version)262 void save(Archive & ar, boost::geometry::model::point<T, D, C> const& p, unsigned int version)
263 {
264     boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::save(ar, p, version);
265 }
266 template<class Archive, typename T, size_t D, typename C>
load(Archive & ar,boost::geometry::model::point<T,D,C> & p,unsigned int version)267 void load(Archive & ar, boost::geometry::model::point<T, D, C> & p, unsigned int version)
268 {
269     boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::load(ar, p, version);
270 }
271 template<class Archive, typename T, size_t D, typename C>
serialize(Archive & ar,boost::geometry::model::point<T,D,C> & o,const unsigned int version)272 inline void serialize(Archive & ar, boost::geometry::model::point<T, D, C> & o, const unsigned int version) { split_free(ar, o, version); }
273 
274 template<class Archive, typename P>
serialize(Archive & ar,boost::geometry::model::box<P> & b,const unsigned int)275 inline void serialize(Archive & ar, boost::geometry::model::box<P> & b, const unsigned int)
276 {
277     ar & boost::serialization::make_nvp("min", b.min_corner());
278     ar & boost::serialization::make_nvp("max", b.max_corner());
279 }
280 
281 }} // boost::serialization
282 
283 // TODO - move to index/detail/rtree/visitors/save.hpp
284 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors {
285 
286 // TODO move saving and loading of the rtree outside the rtree, this will require adding some kind of members_view
287 
288 template <typename Archive, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
289 class save
290     : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
291 {
292 public:
293     typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
294     typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
295     typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
296 
save(Archive & archive,unsigned int version)297     save(Archive & archive, unsigned int version)
298         : m_archive(archive), m_version(version)
299     {}
300 
operator ()(internal_node const & n)301     inline void operator()(internal_node const& n)
302     {
303         typedef typename rtree::elements_type<internal_node>::type elements_type;
304         elements_type const& elements = rtree::elements(n);
305 
306         // CONSIDER: change to elements_type::size_type or size_type
307         // or use fixed-size type like uint32 or even uint16?
308         size_t s = elements.size();
309         m_archive << boost::serialization::make_nvp("s", s);
310 
311         for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
312         {
313             serialization_save(it->first, "b", m_archive);
314 
315             rtree::apply_visitor(*this, *it->second);
316         }
317     }
318 
operator ()(leaf const & l)319     inline void operator()(leaf const& l)
320     {
321         typedef typename rtree::elements_type<leaf>::type elements_type;
322         //typedef typename elements_type::size_type elements_size;
323         elements_type const& elements = rtree::elements(l);
324 
325         // CONSIDER: change to elements_type::size_type or size_type
326         // or use fixed-size type like uint32 or even uint16?
327         size_t s = elements.size();
328         m_archive << boost::serialization::make_nvp("s", s);
329 
330         for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
331         {
332             serialization_save(*it, "v", m_archive);
333         }
334     }
335 
336 private:
337     Archive & m_archive;
338     unsigned int m_version;
339 };
340 
341 }}}}}} // boost::geometry::index::detail::rtree::visitors
342 
343 // TODO - move to index/detail/rtree/load.hpp
344 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
345 
346 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
347 class load
348 {
349     typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
350     typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
351     typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
352 
353     typedef typename Options::parameters_type parameters_type;
354 
355     typedef typename Allocators::node_pointer node_pointer;
356     typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer;
357     typedef typename Allocators::size_type size_type;
358 
359 public:
360     template <typename Archive> inline static
apply(Archive & ar,unsigned int version,size_type leafs_level,size_type & values_count,parameters_type const & parameters,Translator const & translator,Allocators & allocators)361     node_pointer apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators)
362     {
363         values_count = 0;
364         return raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators);
365     }
366 
367 private:
368     template <typename Archive> inline static
raw_apply(Archive & ar,unsigned int version,size_type leafs_level,size_type & values_count,parameters_type const & parameters,Translator const & translator,Allocators & allocators,size_type current_level=0)369     node_pointer raw_apply(Archive & ar, unsigned int version, size_type leafs_level, size_type & values_count, parameters_type const& parameters, Translator const& translator, Allocators & allocators, size_type current_level = 0)
370     {
371         //BOOST_GEOMETRY_INDEX_ASSERT(current_level <= leafs_level, "invalid parameter");
372 
373         typedef typename rtree::elements_type<internal_node>::type elements_type;
374         typedef typename elements_type::value_type element_type;
375         //typedef typename elements_type::size_type elements_size;
376 
377         // CONSIDER: change to elements_type::size_type or size_type
378         // or use fixed-size type like uint32 or even uint16?
379         size_t elements_count;
380         ar >> boost::serialization::make_nvp("s", elements_count);
381 
382         if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )
383             BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
384 
385         if ( current_level < leafs_level )
386         {
387             node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators);              // MAY THROW (A)
388             subtree_destroyer auto_remover(n, allocators);
389             internal_node & in = rtree::get<internal_node>(*n);
390 
391             elements_type & elements = rtree::elements(in);
392 
393             elements.reserve(elements_count);                                                               // MAY THROW (A)
394 
395             for ( size_t i = 0 ; i < elements_count ; ++i )
396             {
397                 typedef typename elements_type::value_type::first_type box_type;
398                 box_type b = serialization_load<box_type>("b", ar);
399                 node_pointer n = raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators, current_level+1); // recursive call
400                 elements.push_back(element_type(b, n));
401             }
402 
403             auto_remover.release();
404             return n;
405         }
406         else
407         {
408             BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");
409 
410             node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators);                       // MAY THROW (A)
411             subtree_destroyer auto_remover(n, allocators);
412             leaf & l = rtree::get<leaf>(*n);
413 
414             typedef typename rtree::elements_type<leaf>::type elements_type;
415             typedef typename elements_type::value_type element_type;
416             elements_type & elements = rtree::elements(l);
417 
418             values_count += elements_count;
419 
420             elements.reserve(elements_count);                                                               // MAY THROW (A)
421 
422             for ( size_t i = 0 ; i < elements_count ; ++i )
423             {
424                 element_type el = serialization_load<element_type>("v", ar);                                     // MAY THROW (C)
425                 elements.push_back(el);                                                                     // MAY THROW (C)
426             }
427 
428             auto_remover.release();
429             return n;
430         }
431     }
432 };
433 
434 }}}}} // boost::geometry::index::detail::rtree
435 
436 // TODO - move to index/detail/rtree/private_view.hpp
437 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
438 
439 template <typename Rtree>
440 class const_private_view
441 {
442 public:
443     typedef typename Rtree::size_type size_type;
444 
445     typedef typename Rtree::translator_type translator_type;
446     typedef typename Rtree::value_type value_type;
447     typedef typename Rtree::options_type options_type;
448     typedef typename Rtree::box_type box_type;
449     typedef typename Rtree::allocators_type allocators_type;
450 
const_private_view(Rtree const & rt)451     const_private_view(Rtree const& rt) : m_rtree(rt) {}
452 
453     typedef typename Rtree::members_holder members_holder;
454 
members() const455     members_holder const& members() const { return m_rtree.m_members; }
456 
457 private:
458     const_private_view(const_private_view const&);
459     const_private_view & operator=(const_private_view const&);
460 
461     Rtree const& m_rtree;
462 };
463 
464 template <typename Rtree>
465 class private_view
466 {
467 public:
468     typedef typename Rtree::size_type size_type;
469 
470     typedef typename Rtree::translator_type translator_type;
471     typedef typename Rtree::value_type value_type;
472     typedef typename Rtree::options_type options_type;
473     typedef typename Rtree::box_type box_type;
474     typedef typename Rtree::allocators_type allocators_type;
475 
private_view(Rtree & rt)476     private_view(Rtree & rt) : m_rtree(rt) {}
477 
478     typedef typename Rtree::members_holder members_holder;
479 
members()480     members_holder & members() { return m_rtree.m_members; }
members() const481     members_holder const& members() const { return m_rtree.m_members; }
482 
483 private:
484     private_view(private_view const&);
485     private_view & operator=(private_view const&);
486 
487     Rtree & m_rtree;
488 };
489 
490 }}}}} // namespace boost::geometry::index::detail::rtree
491 
492 // TODO - move to index/serialization/rtree.hpp
493 namespace boost { namespace serialization {
494 
495 template<class Archive, typename V, typename P, typename I, typename E, typename A>
save(Archive & ar,boost::geometry::index::rtree<V,P,I,E,A> const & rt,unsigned int version)496 void save(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
497 {
498     namespace detail = boost::geometry::index::detail;
499 
500     typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
501     typedef detail::rtree::const_private_view<rtree> view;
502     typedef typename view::translator_type translator_type;
503     typedef typename view::value_type value_type;
504     typedef typename view::options_type options_type;
505     typedef typename view::box_type box_type;
506     typedef typename view::allocators_type allocators_type;
507 
508     view tree(rt);
509 
510     detail::serialization_save(tree.members().parameters(), "parameters", ar);
511 
512     ar << boost::serialization::make_nvp("values_count", tree.members().values_count);
513     ar << boost::serialization::make_nvp("leafs_level", tree.members().leafs_level);
514 
515     if ( tree.members().values_count )
516     {
517         BOOST_GEOMETRY_INDEX_ASSERT(tree.members().root, "root shouldn't be null_ptr");
518 
519         detail::rtree::visitors::save<Archive, value_type, options_type, translator_type, box_type, allocators_type> save_v(ar, version);
520         detail::rtree::apply_visitor(save_v, *tree.members().root);
521     }
522 }
523 
524 template<class Archive, typename V, typename P, typename I, typename E, typename A>
load(Archive & ar,boost::geometry::index::rtree<V,P,I,E,A> & rt,unsigned int version)525 void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
526 {
527     namespace detail = boost::geometry::index::detail;
528 
529     typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
530     typedef detail::rtree::private_view<rtree> view;
531     typedef typename view::size_type size_type;
532     typedef typename view::translator_type translator_type;
533     typedef typename view::value_type value_type;
534     typedef typename view::options_type options_type;
535     typedef typename view::box_type box_type;
536     typedef typename view::allocators_type allocators_type;
537 
538     typedef typename options_type::parameters_type parameters_type;
539     typedef typename allocators_type::node_pointer node_pointer;
540     typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
541 
542     view tree(rt);
543 
544     parameters_type params = detail::serialization_load<parameters_type>("parameters", ar);
545 
546     size_type values_count, leafs_level;
547     ar >> boost::serialization::make_nvp("values_count", values_count);
548     ar >> boost::serialization::make_nvp("leafs_level", leafs_level);
549 
550     node_pointer n(0);
551     if ( 0 < values_count )
552     {
553         size_type loaded_values_count = 0;
554         n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>
555             ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators());                                        // MAY THROW
556 
557         subtree_destroyer remover(n, tree.members().allocators());
558         if ( loaded_values_count != values_count )
559             BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type
560         remover.release();
561     }
562 
563     tree.members().parameters() = params;
564     tree.members().values_count = values_count;
565     tree.members().leafs_level = leafs_level;
566 
567     subtree_destroyer remover(tree.members().root, tree.members().allocators());
568     tree.members().root = n;
569 }
570 
571 template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
serialize(Archive & ar,boost::geometry::index::rtree<V,P,I,E,A> & rt,unsigned int version)572 void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
573 {
574     split_free(ar, rt, version);
575 }
576 
577 template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
serialize(Archive & ar,boost::geometry::index::rtree<V,P,I,E,A> const & rt,unsigned int version)578 void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
579 {
580     split_free(ar, rt, version);
581 }
582 
583 }} // boost::serialization
584 
585 #endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
586