123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598 |
- // Boost.Geometry Index
- //
- // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
- //
- // Use, modification and distribution is subject to the Boost Software License,
- // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
- #define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
- //#include <boost/serialization/serialization.hpp>
- #include <boost/serialization/split_member.hpp>
- #include <boost/serialization/version.hpp>
- //#include <boost/serialization/nvp.hpp>
- // TODO
- // how about using the unsigned type capable of storing Max in compile-time versions?
- // TODO
- // - add wrappers for Point and Box and implement serialize for those wrappers instead of
- // raw geometries
- // PROBLEM: after implementing this, how Values would be set?
- // - store the name of the parameters to know how to load and detect errors
- // - in the header, once store info about the Indexable and Bounds types (geometry type, point CS, Dim, etc.)
- // each geometry save without this info
- // TODO - move to index/detail/serialization.hpp
- namespace boost { namespace geometry { namespace index { namespace detail {
- // TODO - use boost::move?
- template<typename T>
- class serialization_storage
- {
- public:
- template <typename Archive>
- serialization_storage(Archive & ar, unsigned int version)
- {
- boost::serialization::load_construct_data_adl(ar, this->address(), version);
- }
- ~serialization_storage()
- {
- this->address()->~T();
- }
- T * address()
- {
- return static_cast<T*>(m_storage.address());
- }
- private:
- boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> m_storage;
- };
- // TODO - save and load item_version? see: collections_load_imp and collections_save_imp
- // this should be done once for the whole container
- // versions of all used types should be stored
- template <typename T, typename Archive> inline
- T serialization_load(const char * name, Archive & ar)
- {
- namespace bs = boost::serialization;
- serialization_storage<T> storage(ar, bs::version<T>::value); // load_construct_data
- ar >> boost::serialization::make_nvp(name, *storage.address()); // serialize
- //ar >> *storage.address(); // serialize
- return *storage.address();
- }
- template <typename T, typename Archive> inline
- void serialization_save(T const& t, const char * name, Archive & ar)
- {
- namespace bs = boost::serialization;
- bs::save_construct_data_adl(ar, boost::addressof(t), bs::version<T>::value); // save_construct_data
- ar << boost::serialization::make_nvp(name, t); // serialize
- //ar << t; // serialize
- }
-
- }}}}
- // TODO - move to index/serialization/rtree.hpp
- namespace boost { namespace serialization {
- // boost::geometry::index::linear
- template<class Archive, size_t Max, size_t Min>
- void save_construct_data(Archive & ar, const boost::geometry::index::linear<Max, Min> * params, unsigned int )
- {
- size_t max = params->get_max_elements(), min = params->get_min_elements();
- ar << boost::serialization::make_nvp("max", max);
- ar << boost::serialization::make_nvp("min", min);
- }
- template<class Archive, size_t Max, size_t Min>
- void load_construct_data(Archive & ar, boost::geometry::index::linear<Max, Min> * params, unsigned int )
- {
- size_t max, min;
- ar >> boost::serialization::make_nvp("max", max);
- ar >> boost::serialization::make_nvp("min", min);
- if ( max != params->get_max_elements() || min != params->get_min_elements() )
- // TODO change exception type
- BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
- // the constructor musn't be called for this type
- //::new(params)boost::geometry::index::linear<Max, Min>();
- }
- template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::linear<Max, Min> &, unsigned int) {}
- // boost::geometry::index::quadratic
- template<class Archive, size_t Max, size_t Min>
- void save_construct_data(Archive & ar, const boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
- {
- size_t max = params->get_max_elements(), min = params->get_min_elements();
- ar << boost::serialization::make_nvp("max", max);
- ar << boost::serialization::make_nvp("min", min);
- }
- template<class Archive, size_t Max, size_t Min>
- void load_construct_data(Archive & ar, boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
- {
- size_t max, min;
- ar >> boost::serialization::make_nvp("max", max);
- ar >> boost::serialization::make_nvp("min", min);
- if ( max != params->get_max_elements() || min != params->get_min_elements() )
- // TODO change exception type
- BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
- // the constructor musn't be called for this type
- //::new(params)boost::geometry::index::quadratic<Max, Min>();
- }
- template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::quadratic<Max, Min> &, unsigned int) {}
- // boost::geometry::index::rstar
- template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
- void save_construct_data(Archive & ar, const boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
- {
- size_t max = params->get_max_elements()
- , min = params->get_min_elements()
- , re = params->get_reinserted_elements()
- , oct = params->get_overlap_cost_threshold();
- ar << boost::serialization::make_nvp("max", max);
- ar << boost::serialization::make_nvp("min", min);
- ar << boost::serialization::make_nvp("re", re);
- ar << boost::serialization::make_nvp("oct", oct);
- }
- template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
- void load_construct_data(Archive & ar, boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
- {
- size_t max, min, re, oct;
- ar >> boost::serialization::make_nvp("max", max);
- ar >> boost::serialization::make_nvp("min", min);
- ar >> boost::serialization::make_nvp("re", re);
- ar >> boost::serialization::make_nvp("oct", oct);
- if ( max != params->get_max_elements() || min != params->get_min_elements() ||
- re != params->get_reinserted_elements() || oct != params->get_overlap_cost_threshold() )
- // TODO change exception type
- BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
- // the constructor musn't be called for this type
- //::new(params)boost::geometry::index::rstar<Max, Min, RE, OCT>();
- }
- template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
- void serialize(Archive &, boost::geometry::index::rstar<Max, Min, RE, OCT> &, unsigned int) {}
- // boost::geometry::index::dynamic_linear
- template<class Archive>
- inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_linear * params, unsigned int )
- {
- size_t max = params->get_max_elements(), min = params->get_min_elements();
- ar << boost::serialization::make_nvp("max", max);
- ar << boost::serialization::make_nvp("min", min);
- }
- template<class Archive>
- inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_linear * params, unsigned int )
- {
- size_t max, min;
- ar >> boost::serialization::make_nvp("max", max);
- ar >> boost::serialization::make_nvp("min", min);
- ::new(params)boost::geometry::index::dynamic_linear(max, min);
- }
- template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_linear &, unsigned int) {}
- // boost::geometry::index::dynamic_quadratic
- template<class Archive>
- inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_quadratic * params, unsigned int )
- {
- size_t max = params->get_max_elements(), min = params->get_min_elements();
- ar << boost::serialization::make_nvp("max", max);
- ar << boost::serialization::make_nvp("min", min);
- }
- template<class Archive>
- inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_quadratic * params, unsigned int )
- {
- size_t max, min;
- ar >> boost::serialization::make_nvp("max", max);
- ar >> boost::serialization::make_nvp("min", min);
- ::new(params)boost::geometry::index::dynamic_quadratic(max, min);
- }
- template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_quadratic &, unsigned int) {}
- // boost::geometry::index::dynamic_rstar
- template<class Archive>
- inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_rstar * params, unsigned int )
- {
- size_t max = params->get_max_elements()
- , min = params->get_min_elements()
- , re = params->get_reinserted_elements()
- , oct = params->get_overlap_cost_threshold();
- ar << boost::serialization::make_nvp("max", max);
- ar << boost::serialization::make_nvp("min", min);
- ar << boost::serialization::make_nvp("re", re);
- ar << boost::serialization::make_nvp("oct", oct);
- }
- template<class Archive>
- inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_rstar * params, unsigned int )
- {
- size_t max, min, re, oct;
- ar >> boost::serialization::make_nvp("max", max);
- ar >> boost::serialization::make_nvp("min", min);
- ar >> boost::serialization::make_nvp("re", re);
- ar >> boost::serialization::make_nvp("oct", oct);
- ::new(params)boost::geometry::index::dynamic_rstar(max, min, re, oct);
- }
- template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_rstar &, unsigned int) {}
- }} // boost::serialization
- // TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
- namespace boost { namespace geometry { namespace index { namespace detail {
- template <typename P, size_t I = 0, size_t D = geometry::dimension<P>::value>
- struct serialize_point
- {
- template <typename Archive>
- static inline void save(Archive & ar, P const& p, unsigned int version)
- {
- typename coordinate_type<P>::type c = get<I>(p);
- ar << boost::serialization::make_nvp("c", c);
- serialize_point<P, I+1, D>::save(ar, p, version);
- }
- template <typename Archive>
- static inline void load(Archive & ar, P & p, unsigned int version)
- {
- typename geometry::coordinate_type<P>::type c;
- ar >> boost::serialization::make_nvp("c", c);
- set<I>(p, c);
- serialize_point<P, I+1, D>::load(ar, p, version);
- }
- };
- template <typename P, size_t D>
- struct serialize_point<P, D, D>
- {
- template <typename Archive> static inline void save(Archive &, P const&, unsigned int) {}
- template <typename Archive> static inline void load(Archive &, P &, unsigned int) {}
- };
- }}}}
- // TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
- namespace boost { namespace serialization {
- template<class Archive, typename T, size_t D, typename C>
- void save(Archive & ar, boost::geometry::model::point<T, D, C> const& p, unsigned int version)
- {
- boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::save(ar, p, version);
- }
- template<class Archive, typename T, size_t D, typename C>
- void load(Archive & ar, boost::geometry::model::point<T, D, C> & p, unsigned int version)
- {
- boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::load(ar, p, version);
- }
- template<class Archive, typename T, size_t D, typename C>
- inline void serialize(Archive & ar, boost::geometry::model::point<T, D, C> & o, const unsigned int version) { split_free(ar, o, version); }
- template<class Archive, typename P>
- inline void serialize(Archive & ar, boost::geometry::model::box<P> & b, const unsigned int)
- {
- ar & boost::serialization::make_nvp("min", b.min_corner());
- ar & boost::serialization::make_nvp("max", b.max_corner());
- }
- }} // boost::serialization
- // TODO - move to index/detail/rtree/visitors/save.hpp
- namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors {
- // TODO move saving and loading of the rtree outside the rtree, this will require adding some kind of members_view
- template <typename Archive, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
- class save
- : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
- {
- public:
- typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
- typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
- typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
- save(Archive & archive, unsigned int version)
- : m_archive(archive), m_version(version)
- {}
- inline void operator()(internal_node const& n)
- {
- typedef typename rtree::elements_type<internal_node>::type elements_type;
- elements_type const& elements = rtree::elements(n);
- // CONSIDER: change to elements_type::size_type or size_type
- // or use fixed-size type like uint32 or even uint16?
- size_t s = elements.size();
- m_archive << boost::serialization::make_nvp("s", s);
- for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
- {
- serialization_save(it->first, "b", m_archive);
- rtree::apply_visitor(*this, *it->second);
- }
- }
- inline void operator()(leaf const& l)
- {
- typedef typename rtree::elements_type<leaf>::type elements_type;
- //typedef typename elements_type::size_type elements_size;
- elements_type const& elements = rtree::elements(l);
- // CONSIDER: change to elements_type::size_type or size_type
- // or use fixed-size type like uint32 or even uint16?
- size_t s = elements.size();
- m_archive << boost::serialization::make_nvp("s", s);
- for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
- {
- serialization_save(*it, "v", m_archive);
- }
- }
- private:
- Archive & m_archive;
- unsigned int m_version;
- };
- }}}}}} // boost::geometry::index::detail::rtree::visitors
- // TODO - move to index/detail/rtree/load.hpp
- namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
- template <typename MembersHolder>
- class load
- {
- typedef typename MembersHolder::parameters_type parameters_type;
- typedef typename MembersHolder::translator_type translator_type;
- typedef typename MembersHolder::allocators_type allocators_type;
- typedef typename MembersHolder::node node;
- typedef typename MembersHolder::internal_node internal_node;
- typedef typename MembersHolder::leaf leaf;
- typedef typename allocators_type::node_pointer node_pointer;
- typedef typename allocators_type::size_type size_type;
- typedef rtree::subtree_destroyer<MembersHolder> subtree_destroyer;
- public:
- template <typename Archive> inline static
- node_pointer 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)
- {
- values_count = 0;
- return raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators);
- }
- private:
- template <typename Archive> inline static
- node_pointer 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)
- {
- //BOOST_GEOMETRY_INDEX_ASSERT(current_level <= leafs_level, "invalid parameter");
- typedef typename rtree::elements_type<internal_node>::type elements_type;
- typedef typename elements_type::value_type element_type;
- //typedef typename elements_type::size_type elements_size;
- // CONSIDER: change to elements_type::size_type or size_type
- // or use fixed-size type like uint32 or even uint16?
- size_t elements_count;
- ar >> boost::serialization::make_nvp("s", elements_count);
- if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )
- BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
- if ( current_level < leafs_level )
- {
- node_pointer n = rtree::create_node<allocators_type, internal_node>::apply(allocators); // MAY THROW (A)
- subtree_destroyer auto_remover(n, allocators);
- internal_node & in = rtree::get<internal_node>(*n);
- elements_type & elements = rtree::elements(in);
- elements.reserve(elements_count); // MAY THROW (A)
- for ( size_t i = 0 ; i < elements_count ; ++i )
- {
- typedef typename elements_type::value_type::first_type box_type;
- box_type b = serialization_load<box_type>("b", ar);
- node_pointer n = raw_apply(ar, version, leafs_level, values_count, parameters, translator, allocators, current_level+1); // recursive call
- elements.push_back(element_type(b, n));
- }
- auto_remover.release();
- return n;
- }
- else
- {
- BOOST_GEOMETRY_INDEX_ASSERT(current_level == leafs_level, "unexpected value");
- node_pointer n = rtree::create_node<allocators_type, leaf>::apply(allocators); // MAY THROW (A)
- subtree_destroyer auto_remover(n, allocators);
- leaf & l = rtree::get<leaf>(*n);
- typedef typename rtree::elements_type<leaf>::type elements_type;
- typedef typename elements_type::value_type element_type;
- elements_type & elements = rtree::elements(l);
- values_count += elements_count;
- elements.reserve(elements_count); // MAY THROW (A)
- for ( size_t i = 0 ; i < elements_count ; ++i )
- {
- element_type el = serialization_load<element_type>("v", ar); // MAY THROW (C)
- elements.push_back(el); // MAY THROW (C)
- }
- auto_remover.release();
- return n;
- }
- }
- };
- }}}}} // boost::geometry::index::detail::rtree
- // TODO - move to index/detail/rtree/private_view.hpp
- namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
- template <typename Rtree>
- class const_private_view
- {
- public:
- typedef typename Rtree::size_type size_type;
- typedef typename Rtree::translator_type translator_type;
- typedef typename Rtree::value_type value_type;
- typedef typename Rtree::options_type options_type;
- typedef typename Rtree::box_type box_type;
- typedef typename Rtree::allocators_type allocators_type;
- const_private_view(Rtree const& rt) : m_rtree(rt) {}
- typedef typename Rtree::members_holder members_holder;
- members_holder const& members() const { return m_rtree.m_members; }
- private:
- const_private_view(const_private_view const&);
- const_private_view & operator=(const_private_view const&);
- Rtree const& m_rtree;
- };
- template <typename Rtree>
- class private_view
- {
- public:
- typedef typename Rtree::size_type size_type;
- typedef typename Rtree::translator_type translator_type;
- typedef typename Rtree::value_type value_type;
- typedef typename Rtree::options_type options_type;
- typedef typename Rtree::box_type box_type;
- typedef typename Rtree::allocators_type allocators_type;
- private_view(Rtree & rt) : m_rtree(rt) {}
- typedef typename Rtree::members_holder members_holder;
- members_holder & members() { return m_rtree.m_members; }
- members_holder const& members() const { return m_rtree.m_members; }
- private:
- private_view(private_view const&);
- private_view & operator=(private_view const&);
- Rtree & m_rtree;
- };
- }}}}} // namespace boost::geometry::index::detail::rtree
- // TODO - move to index/serialization/rtree.hpp
- namespace boost { namespace serialization {
- template<class Archive, typename V, typename P, typename I, typename E, typename A>
- void save(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
- {
- namespace detail = boost::geometry::index::detail;
- typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
- typedef detail::rtree::const_private_view<rtree> view;
- typedef typename view::translator_type translator_type;
- typedef typename view::value_type value_type;
- typedef typename view::options_type options_type;
- typedef typename view::box_type box_type;
- typedef typename view::allocators_type allocators_type;
- view tree(rt);
- detail::serialization_save(tree.members().parameters(), "parameters", ar);
- ar << boost::serialization::make_nvp("values_count", tree.members().values_count);
- ar << boost::serialization::make_nvp("leafs_level", tree.members().leafs_level);
- if ( tree.members().values_count )
- {
- BOOST_GEOMETRY_INDEX_ASSERT(tree.members().root, "root shouldn't be null_ptr");
- detail::rtree::visitors::save<Archive, value_type, options_type, translator_type, box_type, allocators_type> save_v(ar, version);
- detail::rtree::apply_visitor(save_v, *tree.members().root);
- }
- }
- template<class Archive, typename V, typename P, typename I, typename E, typename A>
- void load(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
- {
- namespace detail = boost::geometry::index::detail;
- typedef boost::geometry::index::rtree<V, P, I, E, A> rtree;
- typedef detail::rtree::private_view<rtree> view;
- typedef typename view::size_type size_type;
- typedef typename view::translator_type translator_type;
- typedef typename view::value_type value_type;
- typedef typename view::options_type options_type;
- typedef typename view::box_type box_type;
- typedef typename view::allocators_type allocators_type;
- typedef typename view::members_holder members_holder;
- typedef typename options_type::parameters_type parameters_type;
- typedef typename allocators_type::node_pointer node_pointer;
- typedef detail::rtree::subtree_destroyer<members_holder> subtree_destroyer;
- view tree(rt);
- parameters_type params = detail::serialization_load<parameters_type>("parameters", ar);
- size_type values_count, leafs_level;
- ar >> boost::serialization::make_nvp("values_count", values_count);
- ar >> boost::serialization::make_nvp("leafs_level", leafs_level);
- node_pointer n(0);
- if ( 0 < values_count )
- {
- size_type loaded_values_count = 0;
- n = detail::rtree::load<members_holder>
- ::apply(ar, version, leafs_level, loaded_values_count, params, tree.members().translator(), tree.members().allocators()); // MAY THROW
- subtree_destroyer remover(n, tree.members().allocators());
- if ( loaded_values_count != values_count )
- BOOST_THROW_EXCEPTION(std::runtime_error("unexpected number of values")); // TODO change exception type
- remover.release();
- }
- tree.members().parameters() = params;
- tree.members().values_count = values_count;
- tree.members().leafs_level = leafs_level;
- subtree_destroyer remover(tree.members().root, tree.members().allocators());
- tree.members().root = n;
- }
- template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
- void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> & rt, unsigned int version)
- {
- split_free(ar, rt, version);
- }
- template<class Archive, typename V, typename P, typename I, typename E, typename A> inline
- void serialize(Archive & ar, boost::geometry::index::rtree<V, P, I, E, A> const& rt, unsigned int version)
- {
- split_free(ar, rt, version);
- }
- }} // boost::serialization
- #endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
|