slice_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_INDEX_HPP_ )
00043 #define _OESS_1__DB__CLN__SLICE_INDEX_HPP_
00044 
00045 #include <map>
00046 
00047 #include <oess_1/db/h/declspec.hpp>
00048 
00049 #include <oess_1/db/cln/h/slice_index_base.hpp>
00050 
00051 namespace oess_1
00052 {
00053 
00054 namespace db
00055 {
00056 
00057 namespace cln
00058 {
00059 
00064 template<
00065   // Класс элемента раздела.
00066   class Item,
00067   // Класс ключа элемента.
00068   class Key,
00069   // Класс извлекателя ключа.
00070   class Key_extractor >
00071 class    slice_index_t :
00072   public slice_index_base_t
00073 {
00074 private :
00077   typedef std::map< Key, oess_1::ent_id_t >
00078     key_map_t;
00079 
00082   typedef std::map< oess_1::ent_id_t, Key >
00083     id_map_t;
00084 
00086   slice_image_iface_t< Item > * m_slice;
00087 
00089   key_map_t m_keys;
00091   id_map_t  m_ids;
00092 
00094   Key_extractor m_key_extractor;
00095 
00096 public :
00098   class iterator
00099   {
00100     private :
00102       typedef typename key_map_t::iterator it_t;
00103 
00105       it_t  m_it;
00106 
00109       slice_image_iface_t< Item > * m_slice;
00110 
00112 
00116       auto_ptr_3::soft_obj_ptr_t< Item >  m_value;
00117 
00118     public :
00119       typedef Item *  pointer;
00120       typedef Item &  reference;
00121 
00122       iterator()
00123       :
00124         m_slice( 0 )
00125       {}
00126       iterator(
00127         slice_image_iface_t< Item > * slice,
00128         const it_t & it )
00129       :
00130         m_it( it )
00131       , m_slice( slice )
00132       {}
00133       iterator(
00134         const iterator & o )
00135       {
00136         (*this) = o;
00137       }
00138       ~iterator()
00139       {}
00140 
00141       iterator &
00142       operator=(
00143         const iterator & o )
00144       {
00145         if( &o != this )
00146         {
00147           m_value.reset();
00148           m_it = o.m_it;
00149           m_slice = o.m_slice;
00150         }
00151         return *this;
00152       }
00153 
00154       reference
00155       operator*()
00156       {
00157         if( !m_value.get() )
00158           // Нужно загружать объект.
00159           m_slice->get( m_it->second, m_value );
00160         return *m_value;
00161       }
00162 
00163       pointer
00164       operator->()
00165       {
00166         if( !m_value.get() )
00167           // Нужно загружать объект.
00168           m_slice->get( m_it->second, m_value );
00169         return m_value.get();
00170       }
00171 
00172       iterator &
00173       operator++()
00174       {
00175         m_value.reset();
00176         ++m_it;
00177         return *this;
00178       }
00179 
00180       iterator
00181       operator++(int)
00182       {
00183         m_value.reset();
00184         return iterator( m_slice, m_it++ );
00185       }
00186 
00187       bool
00188       operator==( const iterator & o ) const
00189       {
00190         return ( m_it == o.m_it );
00191       }
00192 
00193       bool
00194       operator!=( const iterator & o ) const
00195       {
00196         return ( m_it != o.m_it );
00197       }
00198 
00199       const oess_1::ent_id_t &
00200       id() const
00201       {
00202         return m_it->second;
00203       }
00204   };
00205 
00207   class const_iterator
00208   {
00209     private :
00211       typedef typename key_map_t::const_iterator it_t;
00212 
00214       it_t  m_it;
00215 
00218       slice_image_iface_t< Item > * m_slice;
00219 
00221 
00225       auto_ptr_3::soft_obj_ptr_t< Item >  m_value;
00226 
00227     public :
00228       typedef const Item *  pointer;
00229       typedef const Item &  reference;
00230 
00231       const_iterator()
00232       :
00233         m_slice( 0 )
00234       {}
00235       const_iterator(
00236         slice_image_iface_t< Item > * slice,
00237         const it_t & it )
00238       :
00239         m_it( it )
00240       , m_slice( slice )
00241       {}
00242       const_iterator(
00243         const const_iterator & o )
00244       {
00245         (*this) = o;
00246       }
00247       ~const_iterator()
00248       {}
00249 
00250       const_iterator &
00251       operator=(
00252         const const_iterator & o )
00253       {
00254         if( &o != this )
00255         {
00256           m_value.reset();
00257           m_it = o.m_it;
00258           m_slice = o.m_slice;
00259         }
00260         return *this;
00261       }
00262 
00263       reference
00264       operator*()
00265       {
00266         if( !m_value.get() )
00267           // Нужно загружать объект.
00268           m_slice->get( m_it->second, m_value );
00269         return *m_value;
00270       }
00271 
00272       pointer
00273       operator->()
00274       {
00275         if( !m_value.get() )
00276           // Нужно загружать объект.
00277           m_slice->get( m_it->second, m_value );
00278         return m_value.get();
00279       }
00280 
00281       const_iterator &
00282       operator++()
00283       {
00284         m_value.reset();
00285         ++m_it;
00286         return *this;
00287       }
00288 
00289       const_iterator
00290       operator++(int)
00291       {
00292         m_value.reset();
00293         return const_iterator( m_slice, m_it++ );
00294       }
00295 
00296       bool
00297       operator==( const const_iterator & o ) const
00298       {
00299         return ( m_it == o.m_it );
00300       }
00301 
00302       bool
00303       operator!=( const const_iterator & o ) const
00304       {
00305         return ( m_it != o.m_it );
00306       }
00307 
00308       const oess_1::ent_id_t &
00309       id() const
00310       {
00311         return m_it->second;
00312       }
00313   };
00314 
00315 public:
00318   slice_index_t(
00319     slice_image_iface_t< Item > & slice,
00321     const Key_extractor & key_extractor,
00324     unsigned int attach_flags = 0 )
00325   :
00326     m_slice( &slice )
00327   , m_key_extractor( key_extractor )
00328   {
00329     m_slice->attach( *this, attach_flags );
00330   }
00331   virtual ~slice_index_t()
00332   {}
00333 
00335   iterator
00336   begin()
00337   {
00338     return iterator( m_slice, m_keys.begin() );
00339   }
00340 
00342   const_iterator
00343   begin() const
00344   {
00345     return const_iterator( m_slice, m_keys.begin() );
00346   }
00347 
00349   iterator
00350   end()
00351   {
00352     return iterator( m_slice, m_keys.end() );
00353   }
00354 
00356   const_iterator
00357   end() const
00358   {
00359     return const_iterator( m_slice, m_keys.end() );
00360   }
00361 
00363 
00367   iterator
00368   find( const Key & o )
00369   {
00370     return iterator( m_slice, m_keys.find( o ) );
00371   }
00372 
00374 
00378   const_iterator
00379   find( const Key & o ) const
00380   {
00381     return const_iterator( m_slice, m_keys.find( o ) );
00382   }
00383 
00385 
00389   iterator
00390   lower_bound( const Key & o )
00391   {
00392     return iterator( m_slice, m_keys.lower_bound( o ) );
00393   }
00394 
00396 
00400   const_iterator
00401   lower_bound( const Key & o ) const
00402   {
00403     return const_iterator( m_slice, m_keys.lower_bound( o ) );
00404   }
00405 
00407 
00411   iterator
00412   upper_bound( const Key & o )
00413   {
00414     return iterator( m_slice, m_keys.upper_bound( o ) );
00415   }
00416 
00418 
00422   const_iterator
00423   upper_bound( const Key & o ) const
00424   {
00425     return const_iterator( m_slice, m_keys.upper_bound( o ) );
00426   }
00427 
00429 
00433   void
00434   erase( const iterator & it )
00435   {
00436     if( it != end() )
00437     {
00438       // Здесь нужно обязательно сохранить копию id.
00439       // Поскольку далее везде используется ссылка на
00440       // id, то нельзя передавать ссылку, возвращаемую
00441       // методом it.id(). Ведь итератор указывает на
00442       // объект, который будет удален!
00443       oess_1::ent_id_t id_for_erasing = it.id();
00444       m_slice->erase( id_for_erasing );
00445     }
00446   }
00447 
00449 
00453   void
00454   erase( const Key & o )
00455   {
00456     erase( find( o ) );
00457   }
00458 
00460 
00463   unsigned int
00464   size() const
00465   {
00466     return m_keys.size();
00467   }
00468 
00473   virtual void
00474   on_clear()
00475   {
00476     m_keys.clear();
00477     m_ids.clear();
00478   }
00479 
00484   virtual void
00485   on_insert(
00486     const oess_1::ent_id_t & id,
00487     const oess_1::stdsn::serializable_t & o )
00488   {
00489     const Item & real_obj = dynamic_cast< const Item & >( o );
00490     Key k( m_key_extractor( real_obj ) );
00491 
00492     m_keys[ k ] = id;
00493     m_ids[ id ] = k;
00494   }
00495 
00497   virtual void
00498   on_erase(
00499     const oess_1::ent_id_t & id )
00500   {
00501     typename id_map_t::iterator it_id( m_ids.find( id ) );
00502     if( it_id != m_ids.end() )
00503     {
00504       m_keys.erase( it_id->second );
00505       m_ids.erase( it_id );
00506     }
00507   }
00508 
00510   virtual void
00511   on_update(
00512     const oess_1::ent_id_t & id,
00513     const oess_1::stdsn::serializable_t & o )
00514   {
00515     typename id_map_t::iterator it_id( m_ids.find( id ) );
00516     if( it_id != m_ids.end() )
00517     {
00518       const Item & real_obj = dynamic_cast< const Item & >( o );
00519       Key k( m_key_extractor( real_obj ) );
00520 
00521       // Удаляем у себя старый ключ.
00522       m_keys.erase( it_id->second );
00523       // Устанавливаем у себя новый ключ.
00524       m_keys[ k ] = id;
00525       it_id->second = k;
00526     }
00527   }
00528 
00530   virtual void
00531   on_attach()
00532   {
00533     // Ничего не нужно делать.
00534   }
00535 
00537   virtual void
00538   on_detach()
00539   {
00540     // Очищаем всю информацию.
00541     m_keys.clear();
00542     m_ids.clear();
00543     m_slice = 0;
00544   }
00545 
00547 };
00548 
00549 } /* namespace cln */
00550 
00551 } /* namespace db */
00552 
00553 } /* namespace oess_1 */
00554 
00555 #endif

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