libstdc++
ov_tree_map_.hpp
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006, 2009, 2011 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the terms
00007 // of the GNU General Public License as published by the Free Software
00008 // Foundation; either version 3, or (at your option) any later
00009 // version.
00010 
00011 // This library is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
00026 
00027 // Permission to use, copy, modify, sell, and distribute this software
00028 // is hereby granted without fee, provided that the above copyright
00029 // notice appears in all copies, and that both that copyright notice
00030 // and this permission notice appear in supporting documentation. None
00031 // of the above authors, nor IBM Haifa Research Laboratories, make any
00032 // representation about the suitability of this software for any
00033 // purpose. It is provided "as is" without express or implied
00034 // warranty.
00035 
00036 /**
00037  * @file ov_tree_map_/ov_tree_map_.hpp
00038  * Contains an implementation class for ov_tree.
00039  */
00040 
00041 #include <map>
00042 #include <set>
00043 #include <ext/pb_ds/exception.hpp>
00044 #include <ext/pb_ds/tree_policy.hpp>
00045 #include <ext/pb_ds/detail/eq_fn/eq_by_less.hpp>
00046 #include <ext/pb_ds/detail/types_traits.hpp>
00047 #include <ext/pb_ds/detail/type_utils.hpp>
00048 #include <ext/pb_ds/detail/tree_trace_base.hpp>
00049 #ifdef _GLIBCXX_DEBUG
00050 #include <ext/pb_ds/detail/debug_map_base.hpp>
00051 #endif
00052 #include <utility>
00053 #include <functional>
00054 #include <algorithm>
00055 #include <vector>
00056 #include <assert.h>
00057 #include <debug/debug.h>
00058 
00059 namespace __gnu_pbds
00060 {
00061   namespace detail
00062   {
00063 #ifdef PB_DS_DATA_TRUE_INDICATOR
00064 #define PB_DS_OV_TREE_NAME ov_tree_map
00065 #define PB_DS_CONST_NODE_ITERATOR_NAME ov_tree_node_const_iterator_map
00066 #endif
00067 
00068 #ifdef PB_DS_DATA_FALSE_INDICATOR
00069 #define PB_DS_OV_TREE_NAME ov_tree_set
00070 #define PB_DS_CONST_NODE_ITERATOR_NAME ov_tree_node_const_iterator_set
00071 #endif
00072 
00073 #define PB_DS_CLASS_T_DEC \
00074     template<typename Key, typename Mapped, typename Cmp_Fn, \
00075          typename Node_And_It_Traits, typename _Alloc>
00076 
00077 #define PB_DS_CLASS_C_DEC \
00078    PB_DS_OV_TREE_NAME<Key, Mapped, Cmp_Fn, Node_And_It_Traits, _Alloc>
00079 
00080 #define PB_DS_OV_TREE_TRAITS_BASE \
00081     types_traits<Key, Mapped, _Alloc, false>
00082 
00083 #ifdef _GLIBCXX_DEBUG
00084 #define PB_DS_DEBUG_MAP_BASE_C_DEC \
00085     debug_map_base<Key, eq_by_less<Key, Cmp_Fn>, \
00086         typename _Alloc::template rebind<Key>::other::const_reference>
00087 #endif
00088 
00089 #ifdef PB_DS_TREE_TRACE
00090 #define PB_DS_TREE_TRACE_BASE_C_DEC \
00091     tree_trace_base<typename Node_And_It_Traits::node_const_iterator,   \
00092             typename Node_And_It_Traits::node_iterator,     \
00093             Cmp_Fn, false, _Alloc>
00094 #endif
00095 
00096 #ifndef PB_DS_CHECK_KEY_EXISTS
00097 #  error Missing definition
00098 #endif
00099 
00100     /**
00101      *  @brief Ordered-vector tree associative-container.
00102      *  @ingroup branch-detail
00103      */
00104     template<typename Key, typename Mapped, typename Cmp_Fn,
00105          typename Node_And_It_Traits, typename _Alloc>
00106     class PB_DS_OV_TREE_NAME :
00107 #ifdef _GLIBCXX_DEBUG
00108       protected PB_DS_DEBUG_MAP_BASE_C_DEC,
00109 #endif
00110 #ifdef PB_DS_TREE_TRACE
00111       public PB_DS_TREE_TRACE_BASE_C_DEC,
00112 #endif
00113       public Cmp_Fn,
00114       public Node_And_It_Traits::node_update,
00115       public PB_DS_OV_TREE_TRAITS_BASE
00116     {
00117     private:
00118       typedef PB_DS_OV_TREE_TRAITS_BASE             traits_base;
00119       typedef Node_And_It_Traits            traits_type;
00120 
00121       typedef typename remove_const<typename traits_base::value_type>::type non_const_value_type;
00122 
00123       typedef typename _Alloc::template rebind<non_const_value_type>::other value_allocator;
00124       typedef typename value_allocator::pointer     value_vector;
00125 
00126 #ifdef _GLIBCXX_DEBUG
00127       typedef PB_DS_DEBUG_MAP_BASE_C_DEC        debug_base;
00128 #endif
00129 
00130 #ifdef PB_DS_TREE_TRACE
00131       typedef PB_DS_TREE_TRACE_BASE_C_DEC       trace_base;
00132 #endif
00133 
00134       typedef typename traits_base::pointer         mapped_pointer_;
00135       typedef typename traits_base::const_pointer   mapped_const_pointer_;
00136 
00137       typedef typename traits_type::metadata_type   metadata_type;
00138 
00139       typedef typename _Alloc::template rebind<metadata_type>::other metadata_allocator;
00140       typedef typename metadata_allocator::pointer  metadata_pointer;
00141       typedef typename metadata_allocator::const_reference metadata_const_reference;
00142       typedef typename metadata_allocator::reference    metadata_reference;
00143 
00144       typedef typename traits_type::null_node_update_pointer
00145       null_node_update_pointer;
00146 
00147     public:
00148       typedef ov_tree_tag                container_category;
00149       typedef _Alloc                    allocator_type;
00150       typedef typename _Alloc::size_type        size_type;
00151       typedef typename _Alloc::difference_type      difference_type;
00152       typedef Cmp_Fn                    cmp_fn;
00153 
00154       typedef typename traits_base::key_type        key_type;
00155       typedef typename traits_base::key_pointer     key_pointer;
00156       typedef typename traits_base::key_const_pointer   key_const_pointer;
00157       typedef typename traits_base::key_reference   key_reference;
00158       typedef typename traits_base::key_const_reference key_const_reference;
00159       typedef typename traits_base::mapped_type     mapped_type;
00160       typedef typename traits_base::mapped_pointer  mapped_pointer;
00161       typedef typename traits_base::mapped_const_pointer mapped_const_pointer;
00162       typedef typename traits_base::mapped_reference    mapped_reference;
00163       typedef typename traits_base::mapped_const_reference mapped_const_reference;
00164       typedef typename traits_base::value_type      value_type;
00165       typedef typename traits_base::pointer         pointer;
00166       typedef typename traits_base::const_pointer   const_pointer;
00167       typedef typename traits_base::reference       reference;
00168       typedef typename traits_base::const_reference     const_reference;
00169 
00170       typedef const_pointer                 point_const_iterator;
00171 #ifdef PB_DS_DATA_TRUE_INDICATOR
00172       typedef pointer                   point_iterator;
00173 #else
00174       typedef point_const_iterator          point_iterator;
00175 #endif
00176 
00177       typedef point_iterator                iterator;
00178       typedef point_const_iterator          const_iterator;
00179 
00180       /// Conditional destructor.
00181       template<typename Size_Type>
00182         class cond_dtor
00183         {
00184     public:
00185       cond_dtor(value_vector a_vec, iterator& r_last_it, 
00186             Size_Type total_size) 
00187       : m_a_vec(a_vec), m_r_last_it(r_last_it), m_max_size(total_size),
00188         m_no_action(false)
00189       { }
00190 
00191       ~cond_dtor()
00192       {
00193         if (m_no_action)
00194           return;
00195         iterator it = m_a_vec;
00196         while (it != m_r_last_it)
00197           {
00198         it->~value_type();
00199         ++it;
00200           }
00201         
00202         if (m_max_size > 0)
00203           value_allocator().deallocate(m_a_vec, m_max_size);
00204       }
00205 
00206       inline void
00207       set_no_action()
00208       { m_no_action = true; }
00209       
00210     protected:
00211       value_vector      m_a_vec;
00212       iterator&         m_r_last_it;
00213       const Size_Type   m_max_size;
00214       bool          m_no_action;
00215        };
00216       
00217       typedef typename traits_type::node_update     node_update;
00218       typedef typename traits_type::node_iterator   node_iterator;
00219       typedef typename traits_type::node_const_iterator node_const_iterator;
00220 
00221 
00222       PB_DS_OV_TREE_NAME();
00223 
00224       PB_DS_OV_TREE_NAME(const Cmp_Fn&);
00225 
00226       PB_DS_OV_TREE_NAME(const Cmp_Fn&, const node_update&);
00227 
00228       PB_DS_OV_TREE_NAME(const PB_DS_CLASS_C_DEC&);
00229 
00230       ~PB_DS_OV_TREE_NAME();
00231 
00232       void
00233       swap(PB_DS_CLASS_C_DEC&);
00234 
00235       template<typename It>
00236       void
00237       copy_from_range(It, It);
00238 
00239       inline size_type
00240       max_size() const;
00241 
00242       inline bool
00243       empty() const;
00244 
00245       inline size_type
00246       size() const;
00247 
00248       Cmp_Fn&
00249       get_cmp_fn();
00250 
00251       const Cmp_Fn&
00252       get_cmp_fn() const;
00253 
00254       inline mapped_reference
00255       operator[](key_const_reference r_key)
00256       {
00257 #ifdef PB_DS_DATA_TRUE_INDICATOR
00258     PB_DS_ASSERT_VALID((*this))
00259     point_iterator it = lower_bound(r_key);
00260     if (it != end() && !Cmp_Fn::operator()(r_key, PB_DS_V2F(*it)))
00261       {
00262         PB_DS_CHECK_KEY_EXISTS(r_key)
00263         PB_DS_ASSERT_VALID((*this))
00264          return it->second;
00265       }
00266     return insert_new_val(it, std::make_pair(r_key, mapped_type()))->second;
00267 #else
00268     insert(r_key);
00269     return traits_base::s_null_type;
00270 #endif
00271       }
00272 
00273       inline std::pair<point_iterator, bool>
00274       insert(const_reference r_value)
00275       {
00276     PB_DS_ASSERT_VALID((*this))
00277     key_const_reference r_key = PB_DS_V2F(r_value);
00278     point_iterator it = lower_bound(r_key);
00279 
00280     if (it != end()&&  !Cmp_Fn::operator()(r_key, PB_DS_V2F(*it)))
00281       {
00282         PB_DS_ASSERT_VALID((*this))
00283         PB_DS_CHECK_KEY_EXISTS(r_key)
00284         return std::make_pair(it, false);
00285       }
00286 
00287     return std::make_pair(insert_new_val(it, r_value), true);
00288       }
00289 
00290       inline point_iterator
00291       lower_bound(key_const_reference r_key)
00292       {
00293     pointer it = m_a_values;
00294     pointer e_it = m_a_values + m_size;
00295     while (it != e_it)
00296       {
00297         pointer mid_it = it + ((e_it - it) >> 1);
00298         if (cmp_fn::operator()(PB_DS_V2F(*mid_it), r_key))
00299           it = ++mid_it;
00300         else
00301           e_it = mid_it;
00302       }
00303     return it;
00304       }
00305 
00306       inline point_const_iterator
00307       lower_bound(key_const_reference r_key) const
00308       { return const_cast<PB_DS_CLASS_C_DEC& >(*this).lower_bound(r_key); }
00309 
00310       inline point_iterator
00311       upper_bound(key_const_reference r_key)
00312       {
00313     iterator pot_it = lower_bound(r_key);
00314     if (pot_it != end() && !Cmp_Fn::operator()(r_key, PB_DS_V2F(*pot_it)))
00315       {
00316         PB_DS_CHECK_KEY_EXISTS(r_key)
00317         return ++pot_it;
00318       }
00319 
00320     PB_DS_CHECK_KEY_DOES_NOT_EXIST(r_key)
00321     return pot_it;
00322       }
00323 
00324       inline point_const_iterator
00325       upper_bound(key_const_reference r_key) const
00326       { return const_cast<PB_DS_CLASS_C_DEC&>(*this).upper_bound(r_key); }
00327 
00328       inline point_iterator
00329       find(key_const_reference r_key)
00330       {
00331     PB_DS_ASSERT_VALID((*this))
00332     iterator pot_it = lower_bound(r_key);
00333     if (pot_it != end() && !Cmp_Fn::operator()(r_key, PB_DS_V2F(*pot_it)))
00334       {
00335         PB_DS_CHECK_KEY_EXISTS(r_key)
00336         return pot_it;
00337       }
00338 
00339     PB_DS_CHECK_KEY_DOES_NOT_EXIST(r_key)
00340     return end();
00341       }
00342 
00343       inline point_const_iterator
00344       find(key_const_reference r_key) const
00345       { return (const_cast<PB_DS_CLASS_C_DEC&>(*this).find(r_key)); }
00346 
00347       bool
00348       erase(key_const_reference);
00349 
00350       template<typename Pred>
00351       inline size_type
00352       erase_if(Pred);
00353 
00354       inline iterator
00355       erase(iterator it)
00356       { return erase_imp<iterator>(it); }
00357 
00358       void
00359       clear();
00360 
00361       void
00362       join(PB_DS_CLASS_C_DEC&);
00363 
00364       void
00365       split(key_const_reference, PB_DS_CLASS_C_DEC&);
00366 
00367       inline iterator
00368       begin()
00369       { return m_a_values; }
00370 
00371       inline const_iterator
00372       begin() const
00373       { return m_a_values; }
00374 
00375       inline iterator
00376       end()
00377       { return m_end_it; }
00378 
00379       inline const_iterator
00380       end() const
00381       { return m_end_it; }
00382 
00383       /// Returns a const node_iterator corresponding to the node at the
00384       /// root of the tree.
00385       inline node_const_iterator
00386       node_begin() const;
00387 
00388       /// Returns a node_iterator corresponding to the node at the
00389       /// root of the tree.
00390       inline node_iterator
00391       node_begin();
00392 
00393       /// Returns a const node_iterator corresponding to a node just
00394       /// after a leaf of the tree.
00395       inline node_const_iterator
00396       node_end() const;
00397 
00398       /// Returns a node_iterator corresponding to a node just
00399       /// after a leaf of the tree.
00400       inline node_iterator
00401       node_end();
00402 
00403     private:
00404 
00405       inline void
00406       update(node_iterator, null_node_update_pointer);
00407 
00408       template<typename Node_Update>
00409       void
00410       update(node_iterator, Node_Update*);
00411 
00412       void
00413       reallocate_metadata(null_node_update_pointer, size_type);
00414 
00415       template<typename Node_Update_>
00416       void
00417       reallocate_metadata(Node_Update_*, size_type);
00418 
00419       template<typename It>
00420       void
00421       copy_from_ordered_range(It, It);
00422 
00423       void
00424       value_swap(PB_DS_CLASS_C_DEC&);
00425 
00426       template<typename It>
00427       void
00428       copy_from_ordered_range(It, It, It, It);
00429 
00430       template<typename Ptr>
00431       inline static Ptr
00432       mid_pointer(Ptr p_begin, Ptr p_end)
00433       {
00434     _GLIBCXX_DEBUG_ASSERT(p_end >= p_begin);
00435     return (p_begin + (p_end - p_begin) / 2);
00436       }
00437 
00438       inline iterator
00439       insert_new_val(iterator it, const_reference r_value)
00440       {
00441 #ifdef PB_DS_REGRESSION
00442     typename _Alloc::group_adjustor adjust(m_size);
00443 #endif
00444 
00445     PB_DS_CHECK_KEY_DOES_NOT_EXIST(PB_DS_V2F(r_value))
00446 
00447     value_vector a_values = s_value_alloc.allocate(m_size + 1);
00448 
00449     iterator source_it = begin();
00450     iterator source_end_it = end();
00451     iterator target_it = a_values;
00452     iterator ret_it;
00453 
00454     cond_dtor<size_type> cd(a_values, target_it, m_size + 1);
00455     while (source_it != it)
00456       {
00457         new (const_cast<void*>(static_cast<const void*>(target_it)))
00458           value_type(*source_it++);
00459         ++target_it;
00460       }
00461 
00462     new (const_cast<void*>(static_cast<const void*>(ret_it = target_it)))
00463       value_type(r_value);
00464     ++target_it;
00465 
00466     while (source_it != source_end_it)
00467       {
00468         new (const_cast<void*>(static_cast<const void*>(target_it)))
00469           value_type(*source_it++);
00470         ++target_it;
00471       }
00472 
00473     reallocate_metadata((node_update*)this, m_size + 1);
00474     cd.set_no_action();
00475     if (m_size != 0)
00476       {
00477         cond_dtor<size_type> cd1(m_a_values, m_end_it, m_size);
00478       }
00479 
00480     ++m_size;
00481     m_a_values = a_values;
00482     m_end_it = m_a_values + m_size;
00483     _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_value)));
00484     update(node_begin(), (node_update* )this);
00485     PB_DS_ASSERT_VALID((*this))
00486     return ret_it;
00487       }
00488 
00489 #ifdef _GLIBCXX_DEBUG
00490       void
00491       assert_valid(const char*, int) const;
00492 
00493       void
00494       assert_iterators(const char*, int) const;
00495 #endif
00496 
00497       template<typename It>
00498       It
00499       erase_imp(It);
00500 
00501       inline node_const_iterator
00502       PB_DS_node_begin_imp() const;
00503 
00504       inline node_const_iterator
00505       PB_DS_node_end_imp() const;
00506 
00507       inline node_iterator
00508       PB_DS_node_begin_imp();
00509 
00510       inline node_iterator
00511       PB_DS_node_end_imp();
00512 
00513     private:
00514       static value_allocator    s_value_alloc;
00515       static metadata_allocator s_metadata_alloc;
00516 
00517       value_vector      m_a_values;
00518       metadata_pointer      m_a_metadata;
00519       iterator          m_end_it;
00520       size_type         m_size;
00521     };
00522 
00523 #include <ext/pb_ds/detail/ov_tree_map_/constructors_destructor_fn_imps.hpp>
00524 #include <ext/pb_ds/detail/ov_tree_map_/iterators_fn_imps.hpp>
00525 #include <ext/pb_ds/detail/ov_tree_map_/debug_fn_imps.hpp>
00526 #include <ext/pb_ds/detail/ov_tree_map_/erase_fn_imps.hpp>
00527 #include <ext/pb_ds/detail/ov_tree_map_/insert_fn_imps.hpp>
00528 #include <ext/pb_ds/detail/ov_tree_map_/info_fn_imps.hpp>
00529 #include <ext/pb_ds/detail/ov_tree_map_/split_join_fn_imps.hpp>
00530 #include <ext/pb_ds/detail/bin_search_tree_/policy_access_fn_imps.hpp>
00531 
00532 #undef PB_DS_CLASS_C_DEC
00533 #undef PB_DS_CLASS_T_DEC
00534 #undef PB_DS_OV_TREE_NAME
00535 #undef PB_DS_OV_TREE_TRAITS_BASE
00536 #undef PB_DS_DEBUG_MAP_BASE_C_DEC
00537 #ifdef PB_DS_TREE_TRACE
00538 #undef PB_DS_TREE_TRACE_BASE_C_DEC
00539 #endif
00540 #undef PB_DS_CONST_NODE_ITERATOR_NAME
00541   } // namespace detail
00542 } // namespace __gnu_pbds