// Boost.Geometry Index // // R-tree nodes based on runtime-polymorphism, storing static-size containers // test version throwing exceptions on creation // // Copyright (c) 2011-2013 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_TEST_RTREE_EXCEPTIONS_HPP #define BOOST_GEOMETRY_INDEX_TEST_RTREE_EXCEPTIONS_HPP #include #include #include namespace boost { namespace geometry { namespace index { template struct linear_throwing : public linear {}; template struct quadratic_throwing : public quadratic {}; template ::value> struct rstar_throwing : public rstar {}; namespace detail { namespace rtree { // options implementation (from options.hpp) struct node_throwing_d_mem_static_tag {}; template struct options_type< linear_throwing > { typedef options< linear_throwing, insert_default_tag, choose_by_content_diff_tag, split_default_tag, linear_tag, node_throwing_d_mem_static_tag > type; }; template struct options_type< quadratic_throwing > { typedef options< quadratic_throwing, insert_default_tag, choose_by_content_diff_tag, split_default_tag, quadratic_tag, node_throwing_d_mem_static_tag > type; }; template struct options_type< rstar_throwing > { typedef options< rstar_throwing, insert_reinsert_tag, choose_by_overlap_diff_tag, split_default_tag, rstar_tag, node_throwing_d_mem_static_tag > type; }; }} // namespace detail::rtree // node implementation namespace detail { namespace rtree { template struct dynamic_internal_node : public dynamic_node { typedef throwing_varray< std::pair< Box, typename Allocators::node_pointer >, Parameters::max_elements + 1 > elements_type; template inline dynamic_internal_node(Dummy) {} void apply_visitor(dynamic_visitor & v) { v(*this); } void apply_visitor(dynamic_visitor & v) const { v(*this); } elements_type elements; }; template struct dynamic_leaf : public dynamic_node { typedef throwing_varray elements_type; template inline dynamic_leaf(Dummy) {} void apply_visitor(dynamic_visitor & v) { v(*this); } void apply_visitor(dynamic_visitor & v) const { v(*this); } elements_type elements; }; // elements derived type template struct container_from_elements_type, NewValue> { typedef throwing_varray type; }; // nodes traits template struct node { typedef dynamic_node type; }; template struct internal_node { typedef dynamic_internal_node type; }; template struct leaf { typedef dynamic_leaf type; }; template struct visitor { typedef dynamic_visitor type; }; // allocators template class allocators { BOOST_COPYABLE_AND_MOVABLE_ALT(allocators) public: typedef Allocator allocator_type; typedef typename allocator_type::size_type size_type; typedef typename allocator_type::template rebind< typename node::type >::other::pointer node_pointer; typedef typename allocator_type::template rebind< typename internal_node::type >::other::pointer internal_node_pointer; typedef typename allocator_type::template rebind< typename internal_node::type >::other internal_node_allocator_type; typedef typename allocator_type::template rebind< typename leaf::type >::other leaf_allocator_type; inline allocators() : allocator() , internal_node_allocator() , leaf_allocator() {} inline explicit allocators(Allocator alloc) : allocator(alloc) , internal_node_allocator(allocator) , leaf_allocator(allocator) {} inline allocators(allocators const& a) : allocator(a.allocator) , internal_node_allocator(a.internal_node_allocator) , leaf_allocator(a.leaf_allocator) {} inline allocators(BOOST_RV_REF(allocators) a) : allocator(boost::move(a.allocator)) , internal_node_allocator(boost::move(a.internal_node_allocator)) , leaf_allocator(boost::move(a.leaf_allocator)) {} void swap(allocators & a) { boost::swap(allocator, a.allocator); boost::swap(internal_node_allocator, a.internal_node_allocator); boost::swap(leaf_allocator, a.leaf_allocator); } allocator_type allocator; internal_node_allocator_type internal_node_allocator; leaf_allocator_type leaf_allocator; }; struct node_bad_alloc : public std::exception { const char * what() const throw() { return "internal node creation failed."; } }; struct throwing_node_settings { static void throw_if_required() { // throw if counter meets max count if ( get_max_calls_ref() <= get_calls_counter_ref() ) throw node_bad_alloc(); else ++get_calls_counter_ref(); } static void reset_calls_counter() { get_calls_counter_ref() = 0; } static void set_max_calls(size_t mc) { get_max_calls_ref() = mc; } static size_t & get_calls_counter_ref() { static size_t cc = 0; return cc; } static size_t & get_max_calls_ref() { static size_t mc = (std::numeric_limits::max)(); return mc; } }; // create_node template struct create_node< Allocators, dynamic_internal_node > { static inline typename Allocators::node_pointer apply(Allocators & allocators) { // throw if counter meets max count throwing_node_settings::throw_if_required(); return create_dynamic_node< typename Allocators::node_pointer, dynamic_internal_node >::apply(allocators.internal_node_allocator, allocators.internal_node_allocator); } }; template struct create_node< Allocators, dynamic_leaf > { static inline typename Allocators::node_pointer apply(Allocators & allocators) { // throw if counter meets max count throwing_node_settings::throw_if_required(); return create_dynamic_node< typename Allocators::node_pointer, dynamic_leaf >::apply(allocators.leaf_allocator, allocators.leaf_allocator); } }; }} // namespace detail::rtree }}} // namespace boost::geometry::index #endif // BOOST_GEOMETRY_INDEX_TEST_RTREE_EXCEPTIONS_HPP