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