slice_nonunique_index.hpp

См. документацию.
00001 /*
00002 
00003 Copyright (c) 2002-2005, Yauheni Akhotnikau
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008 
00009 - Redistributions of source code must retain the above copyright notice, this
00010 list of conditions and the following disclaimer.
00011 
00012 - Redistributions in binary form must reproduce the above copyright notice, this
00013 list of conditions and the following disclaimer in the documentation and/or
00014 other materials provided with the distribution.
00015 
00016 - The name of the author may not be used to endorse or promote products derived
00017 from this software without specific prior written permission.
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00020 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00022 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00024 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00027 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00028 OF SUCH DAMAGE.
00029 
00030 */
00031 
00032 /*
00033   ObjESSty-1
00034 */
00035 
00042 #if !defined( _OESS_1__DB__CLN__SLICE_NONUNIQUE_INDEX_HPP_ )
00043 #define _OESS_1__DB__CLN__SLICE_NONUNIQUE_INDEX_HPP_
00044 
00045 #include <map>
00046 #include <iterator>
00047 
00048 #include <oess_1/db/h/declspec.hpp>
00049 
00050 #include <oess_1/db/cln/h/slice_index_base.hpp>
00051 
00052 namespace oess_1
00053 {
00054 
00055 namespace db
00056 {
00057 
00058 namespace cln
00059 {
00060 
00065 template<
00066   // Класс элемента раздела.
00067   class Item,
00068   // Класс ключа элемента.
00069   class Key,
00070   // Класс извлекателя ключа.
00071   class Key_extractor >
00072 class    slice_nonunique_index_t :
00073   public slice_index_base_t
00074 {
00075 private :
00078   typedef std::multimap< Key, oess_1::ent_id_t >
00079     key_map_t;
00080 
00083   typedef std::map< oess_1::ent_id_t, Key >
00084     id_map_t;
00085 
00087   slice_image_iface_t< Item > * m_slice;
00088 
00090   key_map_t m_keys;
00092   id_map_t  m_ids;
00093 
00095   Key_extractor m_key_extractor;
00096 
00097 public :
00099   class iterator
00100     : public std::iterator<
00101         std::forward_iterator_tag,
00102         Item >
00103   {
00104     typedef std::iterator< std::forward_iterator_tag, Item > base_type_t;
00105     private :
00107       typedef typename key_map_t::iterator it_t;
00108 
00110       it_t  m_it;
00111 
00114       slice_image_iface_t< Item > * m_slice;
00115 
00117 
00121       auto_ptr_3::soft_obj_ptr_t< Item >  m_value;
00122 
00123     public :
00124       iterator()
00125       :
00126         m_slice( 0 )
00127       {}
00128       iterator(
00129         slice_image_iface_t< Item > * slice,
00130         const it_t & it )
00131       :
00132         m_it( it )
00133       , m_slice( slice )
00134       {}
00135       iterator(
00136         const iterator & o )
00137       : m_it( o.m_it )
00138       , m_slice( o.m_slice )
00139       {}
00140       ~iterator()
00141       {}
00142 
00143       iterator &
00144       operator=(
00145         const iterator & o )
00146       {
00147         iterator t( o );
00148         swap( t );
00149         return *this;
00150       }
00151 
00152       void
00153       swap( iterator & o )
00154       {
00155         std::swap( m_it, o.m_it );
00156         std::swap( m_slice, o.m_slice );
00157         m_value.swap( o.m_value );
00158       }
00159 
00160       typename base_type_t::reference
00161       operator*()
00162       {
00163         if( !m_value.get() )
00164           // Нужно загружать объект.
00165           m_slice->get( m_it->second, m_value );
00166         return *m_value;
00167       }
00168 
00169       typename base_type_t::pointer
00170       operator->()
00171       {
00172         if( !m_value.get() )
00173           // Нужно загружать объект.
00174           m_slice->get( m_it->second, m_value );
00175         return m_value.get();
00176       }
00177 
00178       iterator &
00179       operator++()
00180       {
00181         m_value.reset();
00182         ++m_it;
00183         return *this;
00184       }
00185 
00186       iterator
00187       operator++(int)
00188       {
00189         m_value.reset();
00190         return iterator( m_slice, m_it++ );
00191       }
00192 
00193       bool
00194       operator==( const iterator & o ) const
00195       {
00196         return ( m_it == o.m_it );
00197       }
00198 
00199       bool
00200       operator!=( const iterator & o ) const
00201       {
00202         return ( m_it != o.m_it );
00203       }
00204 
00205       const oess_1::ent_id_t &
00206       id() const
00207       {
00208         return m_it->second;
00209       }
00210   };
00211 
00213   class const_iterator
00214     : public std::iterator<
00215         std::forward_iterator_tag,
00216         Item,
00217         ptrdiff_t,
00218         const Item *,
00219         const Item & >
00220   {
00221     private :
00223       typedef typename key_map_t::const_iterator it_t;
00224 
00226       it_t  m_it;
00227 
00230       slice_image_iface_t< Item > * m_slice;
00231 
00233 
00237       auto_ptr_3::soft_obj_ptr_t< Item >  m_value;
00238 
00239     public :
00240       typedef const Item *  pointer;
00241       typedef const Item &  reference;
00242 
00243       const_iterator()
00244       :
00245         m_slice( 0 )
00246       {}
00247       const_iterator(
00248         slice_image_iface_t< Item > * slice,
00249         const it_t & it )
00250       :
00251         m_it( it )
00252       , m_slice( slice )
00253       {}
00254       const_iterator(
00255         const const_iterator & o )
00256       : m_it( o.m_it )
00257       , m_slice( o.m_slice )
00258       {}
00259       ~const_iterator()
00260       {}
00261 
00262       const_iterator &
00263       operator=(
00264         const const_iterator & o )
00265       {
00266         const_iterator t( o );
00267         swap( t );
00268         return *this;
00269       }
00270 
00271       void
00272       swap( const_iterator & o )
00273       {
00274         std::swap( m_it, o.m_it );
00275         std::swap( m_slice, o.m_slice );
00276         m_value.swap( o.m_value );
00277       }
00278 
00279       reference
00280       operator*()
00281       {
00282         if( !m_value.get() )
00283           // Нужно загружать объект.
00284           m_slice->get( m_it->second, m_value );
00285         return *m_value;
00286       }
00287 
00288       pointer
00289       operator->()
00290       {
00291         if( !m_value.get() )
00292           // Нужно загружать объект.
00293           m_slice->get( m_it->second, m_value );
00294         return m_value.get();
00295       }
00296 
00297       const_iterator &
00298       operator++()
00299       {
00300         m_value.reset();
00301         ++m_it;
00302         return *this;
00303       }
00304 
00305       const_iterator
00306       operator++(int)
00307       {
00308         m_value.reset();
00309         return const_iterator( m_slice, m_it++ );
00310       }
00311 
00312       bool
00313       operator==( const const_iterator & o ) const
00314       {
00315         return ( m_it == o.m_it );
00316       }
00317 
00318       bool
00319       operator!=( const const_iterator & o ) const
00320       {
00321         return ( m_it != o.m_it );
00322       }
00323 
00324       const oess_1::ent_id_t &
00325       id() const
00326       {
00327         return m_it->second;
00328       }
00329   };
00330 
00331 public:
00334   slice_nonunique_index_t(
00335     slice_image_iface_t< Item > & slice,
00337     const Key_extractor & key_extractor,
00340     unsigned int attach_flags = 0 )
00341   :
00342     m_slice( &slice )
00343   , m_key_extractor( key_extractor )
00344   {
00345     m_slice->attach( *this, attach_flags );
00346   }
00347   virtual ~slice_nonunique_index_t()
00348   {}
00349 
00351   iterator
00352   begin()
00353   {
00354     return iterator( m_slice, m_keys.begin() );
00355   }
00356 
00358   const_iterator
00359   begin() const
00360   {
00361     return const_iterator( m_slice, m_keys.begin() );
00362   }
00363 
00365   iterator
00366   end()
00367   {
00368     return iterator( m_slice, m_keys.end() );
00369   }
00370 
00372   const_iterator
00373   end() const
00374   {
00375     return const_iterator( m_slice, m_keys.end() );
00376   }
00377 
00379 
00383   iterator
00384   find( const Key & o )
00385   {
00386     return iterator( m_slice, m_keys.find( o ) );
00387   }
00388 
00390 
00394   const_iterator
00395   find( const Key & o ) const
00396   {
00397     return const_iterator( m_slice, m_keys.find( o ) );
00398   }
00399 
00401 
00405   iterator
00406   lower_bound( const Key & o )
00407   {
00408     return iterator( m_slice, m_keys.lower_bound( o ) );
00409   }
00410 
00412 
00416   const_iterator
00417   lower_bound( const Key & o ) const
00418   {
00419     return const_iterator( m_slice, m_keys.lower_bound( o ) );
00420   }
00421 
00423 
00427   iterator
00428   upper_bound( const Key & o )
00429   {
00430     return iterator( m_slice, m_keys.upper_bound( o ) );
00431   }
00432 
00434 
00438   const_iterator
00439   upper_bound( const Key & o ) const
00440   {
00441     return const_iterator( m_slice, m_keys.upper_bound( o ) );
00442   }
00443 
00445 
00449   void
00450   erase( const iterator & it )
00451   {
00452     if( it != end() )
00453     {
00454       // Здесь нужно обязательно сохранить копию id.
00455       // Поскольку далее везде используется ссылка на
00456       // id, то нельзя передавать ссылку, возвращаемую
00457       // методом it.id(). Ведь итератор указывает на
00458       // объект, который будет удален!
00459       oess_1::ent_id_t id_for_erasing = it.id();
00460       m_slice->erase( id_for_erasing );
00461     }
00462   }
00463 
00465 
00471   void
00472   erase( const Key & o )
00473   {
00474     // Используется самая простая и, вероятно, не эффективная
00475     // реализация: метод erase(it) вызывается до тех пор, пока
00476     // в индексе есть элементы с указанным ключем.
00477     iterator it = find( o );
00478     while( it != end() )
00479       {
00480         erase( it );
00481         it = find( o );
00482       }
00483   }
00484 
00486   unsigned int
00487   size() const
00488   {
00489     return m_keys.size();
00490   }
00491 
00496   virtual void
00497   on_clear()
00498   {
00499     m_keys.clear();
00500     m_ids.clear();
00501   }
00502 
00507   virtual void
00508   on_insert(
00509     const oess_1::ent_id_t & id,
00510     const oess_1::stdsn::serializable_t & o )
00511   {
00512     const Item & real_obj = dynamic_cast< const Item & >( o );
00513     Key k( m_key_extractor( real_obj ) );
00514 
00515     insert_pair( k, id );
00516     m_ids[ id ] = k;
00517   }
00518 
00520   virtual void
00521   on_erase(
00522     const oess_1::ent_id_t & id )
00523   {
00524     typename id_map_t::iterator it_id( m_ids.find( id ) );
00525     if( it_id != m_ids.end() )
00526     {
00527       remove_pair( it_id->second, id );
00528       m_ids.erase( it_id );
00529     }
00530   }
00531 
00533   virtual void
00534   on_update(
00535     const oess_1::ent_id_t & id,
00536     const oess_1::stdsn::serializable_t & o )
00537   {
00538     typename id_map_t::iterator it_id( m_ids.find( id ) );
00539     if( it_id != m_ids.end() )
00540     {
00541       const Item & real_obj = dynamic_cast< const Item & >( o );
00542       Key k( m_key_extractor( real_obj ) );
00543 
00544       if( k < it_id->second || k > it_id->second )
00545         {
00546           remove_pair( it_id->second, id );
00547           insert_pair( k, id );
00548           it_id->second = k;
00549         }
00550     }
00551   }
00552 
00554   virtual void
00555   on_attach()
00556   {
00557     // Ничего не нужно делать.
00558   }
00559 
00561   virtual void
00562   on_detach()
00563   {
00564     // Очищаем всю информацию.
00565     m_keys.clear();
00566     m_ids.clear();
00567     m_slice = 0;
00568   }
00569 
00572 private :
00574   void
00575   insert_pair(
00576     const Key & k,
00577     const oess_1::ent_id_t & id )
00578     {
00579       m_keys.insert( typename key_map_t::value_type( k, id ) );
00580     }
00581 
00583   void
00584   remove_pair(
00585     const Key & k,
00586     const oess_1::ent_id_t & id )
00587     {
00588       for( typename key_map_t::iterator it = m_keys.lower_bound( k ),
00589           it_end = m_keys.upper_bound( k );
00590           it != it_end; ++it )
00591         if( it->second == id )
00592           {
00593             m_keys.erase( it );
00594             return;
00595           }
00596     }
00597 };
00598 
00599 } /* namespace cln */
00600 
00601 } /* namespace db */
00602 
00603 } /* namespace oess_1 */
00604 
00605 #endif
00606 

Документация по ObjESSty. Последние изменения: Fri Oct 13 18:35:35 2006. Создано системой  doxygen 1.4.7
Hosted by uCoz