serialization.hpp 24 KB

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