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 MembersHolder>
347 class load
348 {
349     typedef typename MembersHolder::parameters_type parameters_type;
350     typedef typename MembersHolder::translator_type translator_type;
351     typedef typename MembersHolder::allocators_type allocators_type;
352 
353     typedef typename MembersHolder::node node;
354     typedef typename MembersHolder::internal_node internal_node;
355     typedef typename MembersHolder::leaf leaf;
356 
357     typedef typename allocators_type::node_pointer node_pointer;
358     typedef typename allocators_type::size_type size_type;
359 
360     typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
361 
362 public:
363     template <typename Archive> inline static
apply(Archive & ar,unsigned int version,size_type leafs_level,size_type & values_count,parameters_type const & parameters,translator_type const & translator,allocators_type & allocators)364     node_pointer apply(Archive & ar, unsigned int version, size_type leafs_level,
365                        size_type & values_count,
366                        parameters_type const& parameters,
367                        translator_type const& translator,
368                        allocators_type & allocators)
369     {
370         values_count = 0;
371         return raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators);
372     }
373 
374 private:
375     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_type const & translator,allocators_type & allocators,size_type current_level=0)376     node_pointer raw_apply(Archive & ar, unsigned int version, size_type leafs_level,
377                            size_type & values_count,
378                            parameters_type const& parameters,
379                            translator_type const& translator,
380                            allocators_type & allocators,
381                            size_type current_level = 0)
382     {
383         //BOOST_GEOMETRY_INDEX_ASSERT(current_level <= leafs_level, "invalid parameter");
384 
385         typedef typename rtree::elements_type<internal_node>::type elements_type;
386         typedef typename elements_type::value_type element_type;
387         //typedef typename elements_type::size_type elements_size;
388 
389         // CONSIDER: change to elements_type::size_type or size_type
390         // or use fixed-size type like uint32 or even uint16?
391         size_t elements_count;
392         ar >> boost::serialization::make_nvp("s", elements_count);
393 
394         if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )
395             BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
396 
397         if ( current_level < leafs_level )
398         {
399             node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators);              // MAY THROW (A)
400             subtree_destroyer auto_remover(n, allocators);
401             internal_node & in = rtree::get<internal_node>(*n);
402 
403             elements_type & elements = rtree::elements(in);
404 
405             elements.reserve(elements_count);                                                               // MAY THROW (A)
406 
407             for ( size_t i = 0 ; i < elements_count ; ++i )
408             {
409                 typedef typename elements_type::value_type::first_type box_type;
410                 box_type b = serialization_load<box_type>("b", ar);
411                 node_pointer n = raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators, current_level+1); // recursive call
412                 elements.push_back(element_type(b, n));
413             }
414 
415             auto_remover.release();
416             return n;
417         }
418         else
419         {
420             BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");
421 
422             node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators);                       // MAY THROW (A)
423             subtree_destroyer auto_remover(n, allocators);
424             leaf & l = rtree::get<leaf>(*n);
425 
426             typedef typename rtree::elements_type<leaf>::type elements_type;
427             typedef typename elements_type::value_type element_type;
428             elements_type & elements = rtree::elements(l);
429 
430             values_count += elements_count;
431 
432             elements.reserve(elements_count);                                                               // MAY THROW (A)
433 
434             for ( size_t i = 0 ; i < elements_count ; ++i )
435             {
436                 element_type el = serialization_load<element_type>("v", ar);                                     // MAY THROW (C)
437                 elements.push_back(el);                                                                     // MAY THROW (C)
438             }
439 
440             auto_remover.release();
441             return n;
442         }
443     }
444 };
445 
446 }}}}} // boost::geometry::index::detail::rtree
447 
448 // TODO - move to index/detail/rtree/private_view.hpp
449 namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
450 
451 template <typename Rtree>
452 class const_private_view
453 {
454 public:
455     typedef typename Rtree::size_type size_type;
456 
457     typedef typename Rtree::translator_type translator_type;
458     typedef typename Rtree::value_type value_type;
459     typedef typename Rtree::options_type options_type;
460     typedef typename Rtree::box_type box_type;
461     typedef typename Rtree::allocators_type allocators_type;
462 
const_private_view(Rtree const & rt)463     const_private_view(Rtree const& rt) : m_rtree(rt) {}
464 
465     typedef typename Rtree::members_holder members_holder;
466 
members() const467     members_holder const& members() const { return m_rtree.m_members; }
468 
469 private:
470     const_private_view(const_private_view const&);
471     const_private_view & operator=(const_private_view const&);
472 
473     Rtree const& m_rtree;
474 };
475 
476 template <typename Rtree>
477 class private_view
478 {
479 public:
480     typedef typename Rtree::size_type size_type;
481 
482     typedef typename Rtree::translator_type translator_type;
483     typedef typename Rtree::value_type value_type;
484     typedef typename Rtree::options_type options_type;
485     typedef typename Rtree::box_type box_type;
486     typedef typename Rtree::allocators_type allocators_type;
487 
private_view(Rtree & rt)488     private_view(Rtree & rt) : m_rtree(rt) {}
489 
490     typedef typename Rtree::members_holder members_holder;
491 
members()492     members_holder & members() { return m_rtree.m_members; }
members() const493     members_holder const& members() const { return m_rtree.m_members; }
494 
495 private:
496     private_view(private_view const&);
497     private_view & operator=(private_view const&);
498 
499     Rtree & m_rtree;
500 };
501 
502 }}}}} // namespace boost::geometry::index::detail::rtree
503 
504 // TODO - move to index/serialization/rtree.hpp
505 namespace boost { namespace serialization {
506 
507 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)508 void save(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
509 {
510     namespace detail = boost::geometry::index::detail;
511 
512     typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
513     typedef detail::rtree::const_private_view<rtree> view;
514     typedef typename view::translator_type translator_type;
515     typedef typename view::value_type value_type;
516     typedef typename view::options_type options_type;
517     typedef typename view::box_type box_type;
518     typedef typename view::allocators_type allocators_type;
519 
520     view tree(rt);
521 
522     detail::serialization_save(tree.members().parameters(), "parameters", ar);
523 
524     ar << boost::serialization::make_nvp("values_count", tree.members().values_count);
525     ar << boost::serialization::make_nvp("leafs_level", tree.members().leafs_level);
526 
527     if ( tree.members().values_count )
528     {
529         BOOST_GEOMETRY_INDEX_ASSERT(tree.members().root, "root shouldn't be null_ptr");
530 
531         detail::rtree::visitors::save<Archive, value_type, options_type, translator_type, box_type, allocators_type> save_v(ar, version);
532         detail::rtree::apply_visitor(save_v, *tree.members().root);
533     }
534 }
535 
536 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)537 void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
538 {
539     namespace detail = boost::geometry::index::detail;
540 
541     typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
542     typedef detail::rtree::private_view<rtree> view;
543     typedef typename view::size_type size_type;
544     typedef typename view::translator_type translator_type;
545     typedef typename view::value_type value_type;
546     typedef typename view::options_type options_type;
547     typedef typename view::box_type box_type;
548     typedef typename view::allocators_type allocators_type;
549 
550     typedef typename options_type::parameters_type parameters_type;
551     typedef typename allocators_type::node_pointer node_pointer;
552     typedef detail::rtree::subtree_destroyer<value_type, options_type, translator_type, box_type, allocators_type> subtree_destroyer;
553 
554     view tree(rt);
555 
556     parameters_type params = detail::serialization_load<parameters_type>("parameters", ar);
557 
558     size_type values_count, leafs_level;
559     ar >> boost::serialization::make_nvp("values_count", values_count);
560     ar >> boost::serialization::make_nvp("leafs_level", leafs_level);
561 
562     node_pointer n(0);
563     if ( 0 < values_count )
564     {
565         size_type loaded_values_count = 0;
566         n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>
567             ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators());                                        // MAY THROW
568 
569         subtree_destroyer remover(n, tree.members().allocators());
570         if ( loaded_values_count != values_count )
571             BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type
572         remover.release();
573     }
574 
575     tree.members().parameters() = params;
576     tree.members().values_count = values_count;
577     tree.members().leafs_level = leafs_level;
578 
579     subtree_destroyer remover(tree.members().root, tree.members().allocators());
580     tree.members().root = n;
581 }
582 
583 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)584 void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
585 {
586     split_free(ar, rt, version);
587 }
588 
589 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)590 void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
591 {
592     split_free(ar, rt, version);
593 }
594 
595 }} // boost::serialization
596 
597 #endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
598