Home | History | Annotate | Download | only in pat_trie_
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the terms
      7 // of the GNU General Public License as published by the Free Software
      8 // Foundation; either version 3, or (at your option) any later
      9 // version.
     10 
     11 // This library is distributed in the hope that it will be useful, but
     12 // WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 // General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
     26 
     27 // Permission to use, copy, modify, sell, and distribute this software
     28 // is hereby granted without fee, provided that the above copyright
     29 // notice appears in all copies, and that both that copyright notice
     30 // and this permission notice appear in supporting documentation. None
     31 // of the above authors, nor IBM Haifa Research Laboratories, make any
     32 // representation about the suitability of this software for any
     33 // purpose. It is provided "as is" without express or implied
     34 // warranty.
     35 
     36 /**
     37  * @file erase_fn_imps.hpp
     38  * Contains an implementation class for bin_search_tree_.
     39  */
     40 
     41 PB_DS_CLASS_T_DEC
     42 inline bool
     43 PB_DS_CLASS_C_DEC::
     44 erase(const_key_reference r_key)
     45 {
     46   node_pointer p_nd = find_imp(r_key);
     47   if (p_nd == NULL || p_nd->m_type == pat_trie_internal_node_type)
     48     {
     49       _GLIBCXX_DEBUG_ONLY(debug_base::check_key_does_not_exist(r_key));
     50       return false;
     51     }
     52 
     53   _GLIBCXX_DEBUG_ASSERT(p_nd->m_type == pat_trie_leaf_node_type);
     54   if (!synth_e_access_traits::equal_keys(PB_DS_V2F(reinterpret_cast<leaf_pointer>(p_nd)->value()), r_key))
     55     {
     56       _GLIBCXX_DEBUG_ONLY(debug_base::check_key_does_not_exist(r_key));
     57       return false;
     58     }
     59 
     60   _GLIBCXX_DEBUG_ONLY(debug_base::check_key_exists(r_key));
     61   erase_leaf(static_cast<leaf_pointer>(p_nd));
     62   _GLIBCXX_DEBUG_ONLY(assert_valid();)
     63   return true;
     64 }
     65 
     66 PB_DS_CLASS_T_DEC
     67 void
     68 PB_DS_CLASS_C_DEC::
     69 erase_fixup(internal_node_pointer p_nd)
     70 {
     71   _GLIBCXX_DEBUG_ASSERT(std::distance(p_nd->begin(), p_nd->end()) >= 1);
     72   if (std::distance(p_nd->begin(), p_nd->end()) == 1)
     73     {
     74       node_pointer p_parent = p_nd->m_p_parent;
     75       if (p_parent == m_p_head)
     76 	m_p_head->m_p_parent =* p_nd->begin();
     77       else
     78         {
     79 	  _GLIBCXX_DEBUG_ASSERT(p_parent->m_type == pat_trie_internal_node_type);
     80 	  node_pointer p_new_child =* p_nd->begin();
     81 	  static_cast<internal_node_pointer>(p_parent)->replace_child(
     82 								      p_new_child,
     83 								      pref_begin(p_new_child),
     84 								      pref_end(p_new_child),
     85 								      this);
     86         }
     87       (*p_nd->begin())->m_p_parent = p_nd->m_p_parent;
     88       p_nd->~internal_node();
     89       s_internal_node_allocator.deallocate(p_nd, 1);
     90 
     91       if (p_parent == m_p_head)
     92 	return;
     93 
     94       _GLIBCXX_DEBUG_ASSERT(p_parent->m_type == pat_trie_internal_node_type);
     95       p_nd = static_cast<internal_node_pointer>(p_parent);
     96     }
     97 
     98   while (true)
     99     {
    100       _GLIBCXX_DEBUG_ASSERT(std::distance(p_nd->begin(), p_nd->end()) > 1);
    101       p_nd->update_prefixes(this);
    102       apply_update(p_nd, (node_update* )this);
    103       _GLIBCXX_DEBUG_ONLY(p_nd->assert_valid(this);)
    104       if (p_nd->m_p_parent->m_type == pat_trie_head_node_type)
    105         return;
    106 
    107       _GLIBCXX_DEBUG_ASSERT(p_nd->m_p_parent->m_type ==
    108 		       pat_trie_internal_node_type);
    109 
    110       p_nd = static_cast<internal_node_pointer>(p_nd->m_p_parent);
    111     }
    112 }
    113 
    114 PB_DS_CLASS_T_DEC
    115 inline void
    116 PB_DS_CLASS_C_DEC::
    117 actual_erase_leaf(leaf_pointer p_l)
    118 {
    119   _GLIBCXX_DEBUG_ASSERT(m_size > 0);
    120   --m_size;
    121   _GLIBCXX_DEBUG_ONLY(erase_existing(PB_DS_V2F(p_l->value())));
    122   p_l->~leaf();
    123   s_leaf_allocator.deallocate(p_l, 1);
    124 }
    125 
    126 PB_DS_CLASS_T_DEC
    127 void
    128 PB_DS_CLASS_C_DEC::
    129 clear()
    130 {
    131   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    132   if (empty())
    133     return;
    134 
    135   clear_imp(m_p_head->m_p_parent);
    136   m_size = 0;
    137   initialize();
    138   _GLIBCXX_DEBUG_ONLY(debug_base::clear();)
    139   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    140 }
    141 
    142 PB_DS_CLASS_T_DEC
    143 void
    144 PB_DS_CLASS_C_DEC::
    145 clear_imp(node_pointer p_nd)
    146 {
    147   if (p_nd->m_type == pat_trie_internal_node_type)
    148     {
    149       _GLIBCXX_DEBUG_ASSERT(p_nd->m_type == pat_trie_internal_node_type);
    150       for (typename internal_node::iterator it =
    151 	     static_cast<internal_node_pointer>(p_nd)->begin();
    152 	   it != static_cast<internal_node_pointer>(p_nd)->end();
    153 	   ++it)
    154         {
    155 	  node_pointer p_child =* it;
    156 	  clear_imp(p_child);
    157         }
    158       s_internal_node_allocator.deallocate(static_cast<internal_node_pointer>(p_nd), 1);
    159       return;
    160     }
    161 
    162   _GLIBCXX_DEBUG_ASSERT(p_nd->m_type == pat_trie_leaf_node_type);
    163   static_cast<leaf_pointer>(p_nd)->~leaf();
    164   s_leaf_allocator.deallocate(static_cast<leaf_pointer>(p_nd), 1);
    165 }
    166 
    167 PB_DS_CLASS_T_DEC
    168 inline typename PB_DS_CLASS_C_DEC::const_iterator
    169 PB_DS_CLASS_C_DEC::
    170 erase(const_iterator it)
    171 {
    172   _GLIBCXX_DEBUG_ONLY(assert_valid());
    173 
    174   if (it == end())
    175     return it;
    176 
    177   const_iterator ret_it = it;
    178   ++ret_it;
    179   _GLIBCXX_DEBUG_ASSERT(it.m_p_nd->m_type == pat_trie_leaf_node_type);
    180   erase_leaf(static_cast<leaf_pointer>(it.m_p_nd));
    181   _GLIBCXX_DEBUG_ONLY(assert_valid());
    182   return ret_it;
    183 }
    184 
    185 #ifdef PB_DS_DATA_TRUE_INDICATOR
    186 PB_DS_CLASS_T_DEC
    187 inline typename PB_DS_CLASS_C_DEC::iterator
    188 PB_DS_CLASS_C_DEC::
    189 erase(iterator it)
    190 {
    191   _GLIBCXX_DEBUG_ONLY(assert_valid());
    192 
    193   if (it == end())
    194     return it;
    195   iterator ret_it = it;
    196   ++ret_it;
    197   _GLIBCXX_DEBUG_ASSERT(it.m_p_nd->m_type == pat_trie_leaf_node_type);
    198   erase_leaf(static_cast<leaf_pointer>(it.m_p_nd));
    199   _GLIBCXX_DEBUG_ONLY(assert_valid());
    200   return ret_it;
    201 }
    202 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
    203 
    204 PB_DS_CLASS_T_DEC
    205 inline typename PB_DS_CLASS_C_DEC::const_reverse_iterator
    206 PB_DS_CLASS_C_DEC::
    207 erase(const_reverse_iterator it)
    208 {
    209   _GLIBCXX_DEBUG_ONLY(assert_valid());
    210 
    211   if (it.m_p_nd == m_p_head)
    212     return it;
    213   const_reverse_iterator ret_it = it;
    214   ++ret_it;
    215 
    216   _GLIBCXX_DEBUG_ASSERT(it.m_p_nd->m_type == pat_trie_leaf_node_type);
    217   erase_leaf(static_cast<leaf_pointer>(it.m_p_nd));
    218   _GLIBCXX_DEBUG_ONLY(assert_valid());
    219   return ret_it;
    220 }
    221 
    222 #ifdef PB_DS_DATA_TRUE_INDICATOR
    223 PB_DS_CLASS_T_DEC
    224 inline typename PB_DS_CLASS_C_DEC::reverse_iterator
    225 PB_DS_CLASS_C_DEC::
    226 erase(reverse_iterator it)
    227 {
    228   _GLIBCXX_DEBUG_ONLY(assert_valid());
    229 
    230   if (it.m_p_nd == m_p_head)
    231     return it;
    232   reverse_iterator ret_it = it;
    233   ++ret_it;
    234 
    235   _GLIBCXX_DEBUG_ASSERT(it.m_p_nd->m_type == pat_trie_leaf_node_type);
    236   erase_leaf(static_cast<leaf_pointer>(it.m_p_nd));
    237   _GLIBCXX_DEBUG_ONLY(assert_valid());
    238   return ret_it;
    239 }
    240 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
    241 
    242 PB_DS_CLASS_T_DEC
    243 template<typename Pred>
    244 inline typename PB_DS_CLASS_C_DEC::size_type
    245 PB_DS_CLASS_C_DEC::
    246 erase_if(Pred pred)
    247 {
    248   size_type num_ersd = 0;
    249   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    250 
    251   iterator it = begin();
    252   while (it != end())
    253     {
    254       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    255         if (pred(*it))
    256 	  {
    257             ++num_ersd;
    258             it = erase(it);
    259 	  }
    260         else
    261 	  ++it;
    262     }
    263 
    264   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    265   return num_ersd;
    266 }
    267 
    268 PB_DS_CLASS_T_DEC
    269 void
    270 PB_DS_CLASS_C_DEC::
    271 erase_leaf(leaf_pointer p_l)
    272 {
    273   update_min_max_for_erased_leaf(p_l);
    274   if (p_l->m_p_parent->m_type == pat_trie_head_node_type)
    275     {
    276       _GLIBCXX_DEBUG_ASSERT(size() == 1);
    277       clear();
    278       return;
    279     }
    280 
    281   _GLIBCXX_DEBUG_ASSERT(size() > 1);
    282   _GLIBCXX_DEBUG_ASSERT(p_l->m_p_parent->m_type ==
    283 		   pat_trie_internal_node_type);
    284 
    285   internal_node_pointer p_parent =
    286     static_cast<internal_node_pointer>(p_l->m_p_parent);
    287 
    288   p_parent->remove_child(p_l);
    289   erase_fixup(p_parent);
    290   actual_erase_leaf(p_l);
    291 }
    292 
    293 PB_DS_CLASS_T_DEC
    294 void
    295 PB_DS_CLASS_C_DEC::
    296 update_min_max_for_erased_leaf(leaf_pointer p_l)
    297 {
    298   if (m_size == 1)
    299     {
    300       m_p_head->m_p_min = m_p_head;
    301       m_p_head->m_p_max = m_p_head;
    302       return;
    303     }
    304 
    305   if (p_l == static_cast<const_leaf_pointer>(m_p_head->m_p_min))
    306     {
    307       iterator it(p_l);
    308       ++it;
    309       m_p_head->m_p_min = it.m_p_nd;
    310       return;
    311     }
    312 
    313   if (p_l == static_cast<const_leaf_pointer>(m_p_head->m_p_max))
    314     {
    315       iterator it(p_l);
    316       --it;
    317       m_p_head->m_p_max = it.m_p_nd;
    318     }
    319 }
    320