iterators.h
Go to the documentation of this file.
00001 // Copyright (c) 2009-2010  INRIA Sophia-Antipolis (France).
00002 // All rights reserved.
00003 //
00004 //This file is part of ESBTL.
00005 //
00006 //ESBTL is free software: you can redistribute it and/or modify
00007 //it under the terms of the GNU General Public License as published by
00008 //the Free Software Foundation, either version 3 of the License, or
00009 //(at your option) any later version.
00010 //
00011 //ESBTL is distributed in the hope that it will be useful,
00012 //but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //GNU General Public License for more details.
00015 //
00016 //You should have received a copy of the GNU General Public License
00017 //along with ESBTL.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 //
00020 //Additional permission under GNU GPL version 3 section 7
00021 //
00022 //If you modify this Library, or any covered work, by linking or
00023 //combining it with CGAL (or a modified version of that library), the
00024 //licensors of this Library grant you additional permission to convey
00025 //the resulting work. Corresponding Source for a non-source form of
00026 //such a combination shall include the source code for the parts of CGAL
00027 //used as well as that of the covered work. 
00028 //
00029 //
00030 //
00031 // Author(s)     :  Sébastien Loriot
00032 
00033 
00034 
00035 #ifndef ESBTL_ITERATORS_H
00036 #define ESBTL_ITERATORS_H
00037 
00038 #include <boost/iterator/iterator_facade.hpp>
00039 
00040 namespace ESBTL{
00042 namespace internal{
00043   
00044 template <class T,bool b>
00045 struct do_add_const_to_ref;
00046 
00047 template <class T>
00048 struct do_add_const_to_ref<T,true>{typedef const T& type;};
00049 
00050 template <class T>
00051 struct do_add_const_to_ref<T,false>{typedef T& type;};
00052 
00053 template <class T,bool b>
00054 struct do_add_const;
00055 
00056 template <class T>
00057 struct do_add_const<T,true>{typedef const T type;};
00058 
00059 template <class T>
00060 struct do_add_const<T,false>{typedef T type;};
00061 
00062 
00063 template <class T,bool b>
00064 struct do_add_const_to_ptr;
00065 
00066 template <class T>
00067 struct do_add_const_to_ptr<T,true>{typedef const T* type;};
00068 
00069 template <class T>
00070 struct do_add_const_to_ptr<T,false>{typedef T* type;};
00071 
00072 
00073 template <class T,bool b>
00074 struct do_get_const_iterator;
00075 
00076 template <class T>
00077 struct do_get_const_iterator<T,true>{typedef typename T::const_iterator type;};
00078 
00079 template <class T>
00080 struct do_get_const_iterator<T,false>{typedef typename T::iterator type;};
00081   
00082 
00083 //In the following we define
00084 // Chains_iterator_from_model 
00085 // Residues_iterator_from_model
00086 // Atoms_iterator_from_model
00087 // Residues_iterator_from_chain
00088 // Atoms_iterator_from_chain
00089 // Atoms_iterator_from_residue
00090 // Model_iterator_from_system
00091 // Coarse_atom_from_model
00092 
00093 
00094 //iterator over all chains of a model
00095 //-----------------------------------
00096 template <class Model,bool is_const>
00097 class Chains_iterator_from_model:
00098 public boost::iterator_facade<
00099     Chains_iterator_from_model<Model,is_const>,
00100     typename do_add_const<typename Model::Chain,is_const>::type,
00101     boost::forward_traversal_tag>
00102 {
00103 private:
00104   typedef typename Model::System::Chain   Chain;
00105 public:
00106   Chains_iterator_from_model(typename do_get_const_iterator<typename Model::Chain_container,is_const>::type it):
00107     chain_it(it){}
00108   
00109 private:
00110   friend class boost::iterator_core_access;
00111 
00112   void increment(){++chain_it;}
00113   bool equal(Chains_iterator_from_model const& other) const{ return other.chain_it==chain_it; }
00114   typename do_add_const_to_ref<Chain,is_const>::type dereference() const {return Model::dereference(chain_it);}
00115   
00116 //data member
00117   typename do_get_const_iterator<typename Model::Chain_container,is_const>::type chain_it;
00118 };
00119 
00120 //iterator over all residues of a chain
00121 template <class Chain,bool is_const>
00122 class Residues_iterator_from_chain:
00123 public boost::iterator_facade<
00124     Residues_iterator_from_chain<Chain,is_const>,
00125     typename do_add_const<typename Chain::Residue,is_const>::type,
00126     boost::forward_traversal_tag>
00127 {
00128 private:
00129   typedef typename Chain::Residue   Residue;
00130 public:
00131   Residues_iterator_from_chain(typename do_get_const_iterator<typename Chain::Residue_container,is_const>::type it):
00132     res_it(it){}
00133   Residues_iterator_from_chain(){}
00134 private:
00135   friend class boost::iterator_core_access;
00136 
00137   void increment(){++res_it;}
00138   bool equal(Residues_iterator_from_chain const& other) const{ return other.res_it==res_it; }
00139   typename do_add_const_to_ref<Residue,is_const>::type dereference() const {return Chain::dereference(res_it);}
00140   
00141 //data member
00142   typename do_get_const_iterator<typename Chain::Residue_container,is_const>::type res_it;
00143 };
00144 
00145 //iterator over all residues of a model
00146 template <class Model,bool is_const>
00147 class Residues_iterator_from_model:
00148 public boost::iterator_facade<
00149     Residues_iterator_from_model<Model,is_const>,
00150     typename do_add_const<typename Model::Chain::Residue,is_const>::type,
00151     boost::forward_traversal_tag>
00152 {
00153 private:
00154   typedef typename Model::Chain::Residue   Residue;
00155   Chains_iterator_from_model<Model,is_const>                    chain_it;
00156   Chains_iterator_from_model<Model,is_const>                    chain_end;
00157   Residues_iterator_from_chain<typename Model::Chain,is_const>  res_it;
00158   Residues_iterator_from_chain<typename Model::Chain,is_const>  res_end;
00159 public:
00160   Residues_iterator_from_model(typename do_add_const_to_ref<Model,is_const>::type model,bool is_end=false):
00161     chain_it(is_end?model.chains_end():model.chains_begin()),chain_end(model.chains_end())
00162   {
00163     if (chain_it!=chain_end){
00164       res_it=chain_it->residues_begin();
00165       res_end=chain_it->residues_end();
00166     }
00167   }
00168 private:
00169   friend class boost::iterator_core_access;
00170 
00171   void increment(){
00172     ++res_it;
00173     if (res_it==res_end){
00174       do{
00175         ++chain_it;
00176         if (chain_it!=chain_end){
00177           res_it=chain_it->residues_begin();
00178           res_end=chain_it->residues_end();
00179         }
00180         else{break;}
00181       }while (res_it==res_end);
00182     }
00183   }
00184   bool equal(Residues_iterator_from_model const& other) const{
00185     return chain_it==other.chain_it && ( chain_it==chain_end || other.res_it==res_it ); 
00186   }
00187   typename do_add_const_to_ref<Residue,is_const>::type dereference() const {return *res_it;}
00188 };
00189 
00190 //iterator over all atoms of a residue
00191 template <class Residue,bool is_const>
00192 class Atoms_iterator_from_residue:
00193 public boost::iterator_facade<
00194     Atoms_iterator_from_residue<Residue,is_const>,
00195     typename do_add_const<typename Residue::Atom,is_const>::type,
00196     boost::forward_traversal_tag>
00197 {
00198 private:
00199   typedef typename Residue::Atom   Atom;
00200 public:
00201   //for end
00202   Atoms_iterator_from_residue(typename do_get_const_iterator<typename Residue::Atom_container,is_const>::type it):
00203     atm_it(it),atm_end(it){}
00204   //for begin
00205   Atoms_iterator_from_residue(
00206     typename do_get_const_iterator<typename Residue::Atom_container,is_const>::type it,
00207     typename do_get_const_iterator<typename Residue::Atom_container,is_const>::type end
00208   ):atm_it(it),atm_end(end)
00209   {}
00210 
00211   Atoms_iterator_from_residue(){}
00212 private:
00213   friend class boost::iterator_core_access;
00214 
00215   void increment(){
00216     ++atm_it; 
00217   }
00218   
00219   bool equal(Atoms_iterator_from_residue const& other) const{ return other.atm_it==atm_it; }
00220   typename do_add_const_to_ref<Atom,is_const>::type dereference() const {return Residue::dereference(atm_it);}
00221   
00222 //data member
00223   typename do_get_const_iterator<typename Residue::Atom_container,is_const>::type atm_it;
00224   typename do_get_const_iterator<typename Residue::Atom_container,is_const>::type atm_end;
00225 };
00226 
00227 //iterator over all atoms of a chain
00228 template <class Chain,bool is_const>
00229 class Atoms_iterator_from_chain:
00230 public boost::iterator_facade<
00231     Atoms_iterator_from_chain<Chain,is_const>,
00232     typename do_add_const<typename Chain::Residue::Atom,is_const>::type,
00233     boost::forward_traversal_tag>
00234 {
00235 private:
00236   typedef typename Chain::Residue::Atom                       Atom;
00237 
00238   Residues_iterator_from_chain<Chain,is_const>                   res_it;
00239   Residues_iterator_from_chain<Chain,is_const>                   res_end;
00240   Atoms_iterator_from_residue<typename Chain::Residue,is_const>  atm_it;
00241   Atoms_iterator_from_residue<typename Chain::Residue,is_const>  atm_end;
00242 public:
00243   Atoms_iterator_from_chain(){}
00244   Atoms_iterator_from_chain(typename do_add_const_to_ref<Chain,is_const>::type chain,bool is_end=false):
00245     res_it(is_end?chain.residues_end():chain.residues_begin()),res_end(chain.residues_end())
00246   {
00247     if (res_it!=res_end){
00248       atm_it=res_it->atoms_begin();
00249       atm_end=res_it->atoms_end();
00250       make_valid();
00251     }
00252   }
00253 private:
00254   friend class boost::iterator_core_access;
00255 
00256   void increment(){
00257     ++atm_it;
00258     make_valid();
00259   }
00260   
00261   void make_valid(){
00262     while(atm_it==atm_end){
00263       ++res_it;
00264       if (res_it==res_end) break;
00265       atm_it=res_it->atoms_begin();
00266       atm_end=res_it->atoms_end();
00267     }    
00268   }
00269   
00270   bool equal(Atoms_iterator_from_chain const& other) const{
00271     return res_it==other.res_it && ( res_it==res_end || other.atm_it==atm_it ); 
00272   }
00273   typename do_add_const_to_ref<Atom,is_const>::type dereference() const {return *atm_it;}
00274 };
00275 
00276 
00277 
00278 
00279 //iterator over all atoms of a model
00280 template <class Model,bool is_const>
00281 class Atoms_iterator_from_model:
00282 public boost::iterator_facade<
00283     Atoms_iterator_from_model<Model,is_const>,
00284     typename do_add_const<typename Model::Chain::Residue::Atom,is_const>::type,
00285     boost::forward_traversal_tag>
00286 {
00287 private:
00288   typedef typename Model::Chain::Residue::Atom                       Atom;
00289 
00290   Chains_iterator_from_model<Model,is_const>                   chain_it;
00291   Chains_iterator_from_model<Model,is_const>                   chain_end;
00292   Atoms_iterator_from_chain<typename Model::Chain,is_const>  atm_it;
00293   Atoms_iterator_from_chain<typename Model::Chain,is_const>  atm_end;
00294 public:
00295   Atoms_iterator_from_model(typename do_add_const_to_ref<Model,is_const>::type model,bool is_end=false):
00296     chain_it(is_end?model.chains_end():model.chains_begin()),chain_end(model.chains_end())
00297   {
00298     if (chain_it!=chain_end){
00299       atm_it=chain_it->atoms_begin();
00300       atm_end=chain_it->atoms_end();
00301       make_valid();
00302     }
00303   }
00304   
00305   bool is_end(){
00306     return chain_it==chain_end;
00307   }
00308   
00309 private:
00310   friend class boost::iterator_core_access;
00311 
00312   void increment(){
00313     ++atm_it;
00314     make_valid();
00315   }
00316   
00317   void make_valid(){
00318     while (atm_it==atm_end){
00319       ++chain_it;
00320       if (chain_it==chain_end) break;
00321       atm_it=chain_it->atoms_begin();
00322       atm_end=chain_it->atoms_end();
00323     }    
00324   }
00325   
00326   bool equal(Atoms_iterator_from_model const& other) const{
00327     return chain_it==other.chain_it && ( chain_it==chain_end || other.atm_it==atm_it ); 
00328   }
00329   typename do_add_const_to_ref<Atom,is_const>::type dereference() const {return *atm_it;}
00330 };
00331 
00332 //iterator over all model of a system
00333 //-----------------------------------
00334 template <class System,bool is_const>
00335 class Model_iterator_from_system:
00336 public boost::iterator_facade<
00337     Model_iterator_from_system<System,is_const>,
00338     typename do_add_const<typename System::Model,is_const>::type,
00339     boost::forward_traversal_tag>
00340 {
00341 private:
00342   typedef typename System::Model Model;
00343 public:
00344   Model_iterator_from_system(typename do_get_const_iterator<typename System::Model_container,is_const>::type it):
00345     model_it(it){}
00346   
00347 private:
00348   friend class boost::iterator_core_access;
00349 
00350   void increment(){++model_it;}
00351   bool equal(Model_iterator_from_system const& other) const{ return other.model_it==model_it; }
00352   typename do_add_const_to_ref<Model,is_const>::type dereference() const {return System::dereference(model_it);}
00353   
00354 //data member
00355   typename do_get_const_iterator<typename System::Model_container,is_const>::type model_it;
00356 };
00357 
00358 
00359 //iterator over all coarse_atom of a model
00360 //-----------------------------------
00361 template <class Model,bool is_const>
00362 class Coarse_atom_from_model:
00363 public boost::iterator_facade<
00364     Coarse_atom_from_model<Model,is_const>,
00365     typename do_add_const<typename Model::Chain::Residue::Coarse_atom,is_const>::type,
00366     boost::forward_traversal_tag>
00367 {
00368 private:
00369   typedef typename Model::Chain::Residue::Coarse_atom Coarse_atom;
00370 public:
00371   Coarse_atom_from_model(typename do_add_const_to_ref<Model,is_const>::type model,bool is_end=false):
00372     res_it(is_end?model.residues_end():model.residues_begin()),res_end(model.residues_end())
00373     {
00374       if (res_it!=res_end){
00375         atm_it=res_it->coarse_atoms_begin();
00376         atm_end=res_it->coarse_atoms_end();
00377         make_valid();
00378       }
00379     }
00380   
00381 private:
00382   friend class boost::iterator_core_access;
00383 
00384   void increment(){
00385     ++atm_it;
00386     make_valid();
00387   }
00388   
00389   void make_valid(){
00390     while(atm_it==atm_end){
00391       ++res_it;
00392       if (res_it==res_end) break;
00393       atm_it=res_it->coarse_atoms_begin();
00394       atm_end=res_it->coarse_atoms_end();
00395     }    
00396   }
00397   bool equal(Coarse_atom_from_model const& other) const{ return other.res_it==res_it && (res_it==res_end || other.atm_it==atm_it); }
00398   typename do_add_const_to_ref<Coarse_atom,is_const>::type dereference() const {return Model::Chain::Residue::dereference(atm_it);}
00399   
00400 //data member
00401   Residues_iterator_from_model<Model,is_const> res_it;
00402   Residues_iterator_from_model<Model,is_const> res_end;
00403  typename do_get_const_iterator <typename Model::Chain::Residue::Coarse_atom_container,is_const>::type  atm_it;
00404  typename do_get_const_iterator <typename Model::Chain::Residue::Coarse_atom_container,is_const>::type atm_end;
00405 };
00406 
00407   
00408 }//namespace internal
00410 }//namespace ESBTL
00411 
00412 #endif //ESBTL_ITERATORS_H