serialization.hpp 25 KB

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