serialization.hpp 25 KB

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