1 /**********************************************************************
2 obiter.h - STL-style iterators for Open Babel.
3 
4 Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5 Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison
6 
7 This file is part of the Open Babel project.
8 For more information, see <http://openbabel.org/>
9 
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation version 2 of the License.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 ***********************************************************************/
19 
20 #ifndef OB_OBITER_H
21 #define OB_OBITER_H
22 
23 #include <openbabel/babelconfig.h>
24 #include <openbabel/bitvec.h>
25 
26 #include <vector>
27 #include <stack>
28 #include <queue>
29 
30 
31 namespace OpenBabel
32 {
33   class OBMol;
34   class OBAtom;
35   class OBBond;
36   class OBResidue;
37 
38   // more detailed descriptions and documentation in obiter.cpp
39 
40   //! \brief Iterate over all atoms in an OBMol
41   class OBAPI OBMolAtomIter {
42     std::vector<OBAtom*>::iterator _i;
43     OBMol *_parent;
44     OBAtom *_ptr;
45   public:
46 
OBMolAtomIter()47     OBMolAtomIter() :_parent(nullptr), _ptr(nullptr) { }
48     OBMolAtomIter(OBMol *mol);
49     OBMolAtomIter(OBMol &mol);
50     OBMolAtomIter(const OBMolAtomIter &ai);
~OBMolAtomIter()51     ~OBMolAtomIter() { }
52 
53     OBMolAtomIter& operator=(const OBMolAtomIter &ai);
54     //! \return Whether the iterator can still advance (i.e., visit more atoms)
55     operator bool() const        { return _ptr != nullptr; }
56     //! Preincrement iterator -- advance to next atom and return
57     OBMolAtomIter& operator++();
58     //! Postincrement iterator -- return the current atom and advance
59     OBMolAtomIter  operator++(int);
60     //! \return a pointer to the current atom
61     OBAtom* operator->() const   { return _ptr;      }
62     //! \return a reference to the current atom
63     OBAtom& operator*() const    { return *_ptr;     }
64   };
65 
66   //! \brief Iterate over all atoms in an OBMol in a depth-first search (DFS)
67   class OBAPI OBMolAtomDFSIter {
68     OBMol               *_parent;
69     OBAtom              *_ptr;
70     OBBitVec             _notVisited;
71     std::stack<OBAtom *> _stack;
72   public:
73 
OBMolAtomDFSIter()74     OBMolAtomDFSIter() : _parent(nullptr), _ptr(nullptr) { }
75     OBMolAtomDFSIter(OBMol *mol, int StartIndex=1);
76     OBMolAtomDFSIter(OBMol &mol, int StartIndex=1);
77     OBMolAtomDFSIter(const OBMolAtomDFSIter &ai);
~OBMolAtomDFSIter()78     ~OBMolAtomDFSIter() { }
79 
80     OBMolAtomDFSIter& operator=(const OBMolAtomDFSIter &ai);
81     //! \return Whether the iterator can still advance (i.e., visit more atoms)
82     operator bool() const        { return _ptr != nullptr; }
83     //! Preincrement -- advance to the next atom in the DFS list and return
84     OBMolAtomDFSIter& operator++();
85     //! Postincrement -- return the current atom and advance to the next atom
86     OBMolAtomDFSIter  operator++(int);
87     //! \return a pointer to the current atom
88     OBAtom* operator->() const   { return _ptr;      }
89     //! \return a reference to the current atom
90     OBAtom& operator*() const    { return *_ptr;     }
91     /// \return NULL if at the last atom in a fragment, else the next atom
next()92     OBAtom* next()
93     {
94       if(_stack.empty())
95         return nullptr; //end of a disconnected fragment
96       else
97         return _stack.top(); //the next atom
98     }
99   };
100 
101   //! \brief Iterate over all atoms in an OBMol in a breadth-first search (BFS)
102   class OBAPI OBMolAtomBFSIter {
103     OBMol               *_parent;
104     OBAtom              *_ptr;
105     OBBitVec             _notVisited;
106     std::queue<OBAtom *> _queue;
107     std::vector<int>     _depth;
108   public:
109 
OBMolAtomBFSIter()110     OBMolAtomBFSIter(): _parent(nullptr), _ptr(nullptr) { }
111     OBMolAtomBFSIter(OBMol *mol, int StartIndex = 1);
112     OBMolAtomBFSIter(OBMol &mol, int StartIndex = 1);
113     OBMolAtomBFSIter(const OBMolAtomBFSIter &ai);
~OBMolAtomBFSIter()114     ~OBMolAtomBFSIter() { }
115 
116     OBMolAtomBFSIter& operator=(const OBMolAtomBFSIter &ai);
117     //! \return Whether the iterator can still advance (i.e., visit more atoms)
118     operator bool() const        { return _ptr != nullptr; }
119     //! Preincrement -- advance to the next atom in the BFS list and return
120     OBMolAtomBFSIter& operator++();
121     //! Postincrement -- return the current atom and advance to the next atom
122     OBMolAtomBFSIter  operator++(int);
123     //! \return a pointer to the current atom
124     OBAtom* operator->() const   { return _ptr;      }
125     //! \return a reference to the current atom
126     OBAtom& operator*() const    { return *_ptr;     }
127     //! \return the current depth of the iterator
128     //! \since version 2.2
129     int CurrentDepth() const;
130   };
131 
132   //! \brief Iterate over all bonds in an OBMol in a breadth-first search (BFS)
133   class OBAPI OBMolBondBFSIter {
134     OBMol               *_parent;
135     OBBond              *_ptr;
136     OBBitVec             _notVisited;
137     std::queue<OBBond *> _queue;
138     std::vector<int>     _depth;
139   public:
140 
OBMolBondBFSIter()141     OBMolBondBFSIter(): _parent(nullptr), _ptr(nullptr) { }
142     OBMolBondBFSIter(OBMol *mol, int StartIndex = 0);
143     OBMolBondBFSIter(OBMol &mol, int StartIndex = 0);
144     OBMolBondBFSIter(const OBMolBondBFSIter &ai);
~OBMolBondBFSIter()145     ~OBMolBondBFSIter() { }
146 
147     OBMolBondBFSIter& operator=(const OBMolBondBFSIter &ai);
148     //! \return Whether the iterator can still advance (i.e., visit more atoms)
149     operator bool() const        { return _ptr != nullptr; }
150     //! Preincrement -- advance to the next atom in the BFS list and return
151     OBMolBondBFSIter& operator++();
152     //! Postincrement -- return the current atom and advance to the next atom
153     OBMolBondBFSIter  operator++(int);
154     //! \return a pointer to the current atom
155     OBBond* operator->() const   { return _ptr;      }
156     //! \return a reference to the current atom
157     OBBond& operator*() const    { return *_ptr;     }
158     //! \return the current depth of the iterator
159     //! \since version 2.2
160     int CurrentDepth() const;
161   };
162 
163   //! \brief Iterate over all bonds in an OBMol
164   class OBAPI OBMolBondIter {
165     std::vector<OBBond*>::iterator _i;
166     OBMol *_parent;
167     OBBond *_ptr;
168   public:
169 
OBMolBondIter()170     OBMolBondIter() : _parent(nullptr), _ptr(nullptr) {}
171     OBMolBondIter(OBMol *mol);
172     OBMolBondIter(OBMol &mol);
173     OBMolBondIter(const OBMolBondIter &bi);
~OBMolBondIter()174     ~OBMolBondIter() { }
175 
176     OBMolBondIter& operator=(const OBMolBondIter &bi);
177     //! \return Whether the iterator can still advance (i.e., visit more bonds)
178     operator bool() const        { return _ptr != nullptr; }
179     //! Preincrement -- advance to the next bond and return
180     OBMolBondIter& operator++();
181     //! Postincrement -- return the current bond and advance to the next
182     OBMolBondIter  operator++(int);
183     //! \return a pointer to the current bond
184     OBBond* operator->() const   { return _ptr;      }
185     //! \return a reference to the current bond
186     OBBond& operator*() const    { return *_ptr;     }
187   };
188 
189   //! \brief Iterate over all neighboring atoms to an OBAtom
190   class OBAPI OBAtomAtomIter {
191     std::vector<OBBond*>::iterator _i;
192     OBAtom *_parent;
193     OBAtom *_ptr;
194   public:
195 
OBAtomAtomIter()196     OBAtomAtomIter() : _parent(nullptr), _ptr(nullptr) { }
197     OBAtomAtomIter(OBAtom *atm);
198     OBAtomAtomIter(OBAtom &atm);
199     OBAtomAtomIter(const OBAtomAtomIter &ai);
~OBAtomAtomIter()200     ~OBAtomAtomIter() { }
201 
202     OBAtomAtomIter& operator=(const OBAtomAtomIter &ai);
203      //! \return Whether the iterator can still advance (i.e., visit more neighbors)
204     operator bool() const        { return _ptr != nullptr; }
205     //! Preincrement -- advance to the next neighbor and return
206     OBAtomAtomIter& operator++();
207     //! Postincrement -- return the current neighbor and advance to the next
208     OBAtomAtomIter  operator++(int);
209     //! \return a pointer to the current atom
210     OBAtom* operator->() const   { return _ptr;      }
211     //! \return a reference to the current atom
212     OBAtom& operator*() const    { return *_ptr;     }
213   };
214 
215   //! \brief Iterate over all bonds on an OBAtom
216   class OBAPI OBAtomBondIter {
217     std::vector<OBBond*>::iterator _i;
218     OBAtom *_parent;
219     OBBond *_ptr;
220   public:
221 
OBAtomBondIter()222     OBAtomBondIter(): _parent(nullptr), _ptr(nullptr) { }
223     OBAtomBondIter(OBAtom *atm);
224     OBAtomBondIter(OBAtom &atm);
225     OBAtomBondIter(const OBAtomBondIter &bi);
~OBAtomBondIter()226     ~OBAtomBondIter() { }
227 
228     OBAtomBondIter& operator=(const OBAtomBondIter &bi);
229     //! \return Whether the iterator can still advance (i.e., visit more bonds)
230     operator bool() const        { return _ptr != nullptr; }
231     //! Preincrement -- advance to the next bond and return
232     OBAtomBondIter& operator++();
233     //! Postincrement -- return the current state and advance to the next bond
234     OBAtomBondIter  operator++(int);
235     //! \return a pointer to the current bond
236     OBBond* operator->() const   { return _ptr; }
237     //! \return a reference to the current bond
238     OBBond& operator*() const    { return *_ptr;}
239   };
240 
241   //! \brief Iterate over all residues in an OBMol
242   class OBAPI OBResidueIter {
243     std::vector<OBResidue*>::iterator _i;
244     OBResidue *_ptr;
245     OBMol *_parent;
246   public:
247 
OBResidueIter()248     OBResidueIter() : _ptr(nullptr), _parent(nullptr) { }
249     OBResidueIter(OBMol *mol);
250     OBResidueIter(OBMol &mol);
251     OBResidueIter(const OBResidueIter &ri);
~OBResidueIter()252     ~OBResidueIter() { }
253 
254     OBResidueIter& operator=(const OBResidueIter &ri);
255     //! \return Whether the iterator can still advance (i.e., visit more residues)
256     operator bool() const        { return _ptr != nullptr; }
257     //! Preincrement -- advance to the next residue and return
258     OBResidueIter& operator++();
259     //! Postincrement -- return the current state and advance to the next residue
260     OBResidueIter  operator++(int);
261     //! \return a pointer to the current residue
262     OBResidue* operator->() const{ return _ptr; }
263     //! \return a reference to the current residue
264     OBResidue& operator*() const { return *_ptr;}
265   };
266 
267   //! \brief Iterate over all atoms in an OBResidue
268   class OBAPI OBResidueAtomIter {
269     std::vector<OBAtom*>::iterator _i;
270     OBResidue *_parent;
271     OBAtom    *_ptr;
272   public:
273 
OBResidueAtomIter()274     OBResidueAtomIter() : _parent(nullptr), _ptr(nullptr) { }
275     OBResidueAtomIter(OBResidue *res);
276     OBResidueAtomIter(OBResidue &res);
277     OBResidueAtomIter(const OBResidueAtomIter &ri);
~OBResidueAtomIter()278     ~OBResidueAtomIter() { }
279 
280     OBResidueAtomIter &operator = (const OBResidueAtomIter &ri);
281     //! \return Whether the iterator can still advance (i.e., visit more atoms in this residue)
282     operator bool() const        { return _ptr != nullptr; }
283     //! Preincrement -- advance to the next atom (if any) and return
284     OBResidueAtomIter& operator++ ();
285     //! Postincrement -- return the current state and advance to the next atom (if any)
286     OBResidueAtomIter  operator++ (int);
287     //! \return a pointer to the current atom
288     OBAtom *operator->() const   { return _ptr; }
289     //! \return a reference to the current atom
290     OBAtom &operator*() const    { return *_ptr;}
291   };
292 
293   //! \brief Iterate over all angles in an OBMol
294   class OBAPI OBMolAngleIter {
295     OBMol     *_parent;
296     std::vector<std::vector<unsigned int> > _vangle;
297     std::vector<std::vector<unsigned int> >::iterator _i;
298     std::vector<unsigned int> _angle;
299   public:
300 
OBMolAngleIter()301     OBMolAngleIter() :_parent(nullptr) { }
302     OBMolAngleIter(OBMol *mol);
303     OBMolAngleIter(OBMol &mol);
304     OBMolAngleIter(const OBMolAngleIter &ai);
~OBMolAngleIter()305     ~OBMolAngleIter() { }
306 
307     OBMolAngleIter& operator=(const OBMolAngleIter &ai);
308     //! \return Whether the iterator can still advance (i.e., visit more angles)
309     operator bool() const        { return (_i != _vangle.end()); }
310     //! Preincrement -- advance to the next angle and return
311     OBMolAngleIter& operator++();
312     //! \return A vector of three atom indexes specifying the angle
313     //! \see OBAtom::GetIdx()
314     std::vector<unsigned int> operator*() const    { return _angle;     }
315   };
316 
317   //! \brief Iterate over all torsions in an OBMol
318   class OBAPI OBMolTorsionIter {
319     OBMol *_parent;
320     std::vector<std::vector<unsigned int> > _vtorsion;
321     std::vector<std::vector<unsigned int> >::iterator _i;
322     std::vector<unsigned int> _torsion;
323   public:
324 
OBMolTorsionIter()325     OBMolTorsionIter() :_parent(nullptr) { }
326     OBMolTorsionIter(OBMol *mol);
327     OBMolTorsionIter(OBMol &mol);
328     OBMolTorsionIter(const OBMolTorsionIter &ai);
~OBMolTorsionIter()329     ~OBMolTorsionIter() { }
330 
331     OBMolTorsionIter& operator=(const OBMolTorsionIter &ai);
332     //! \return Whether the iterator can still advance (i.e., visit more torsions)
333     operator bool() const        { return (_i != _vtorsion.end()); }
334     //! Preincrement -- advance to the next torsion and return
335     OBMolTorsionIter& operator++();
336     //! \return A vector of four atom indexes specifying the torsion
337     //! \see OBAtom::GetIdx()
338     std::vector<unsigned int> operator*() const    { return _torsion;     }
339   };
340 
341   //! \brief Iterate over all pairs of atoms (>1-4) in an OBMol
342   class OBAPI OBMolPairIter {
343     std::vector<OBAtom*>::iterator _i;
344     std::vector<OBAtom*>::iterator _j;
345     OBMol *_parent;
346     //std::vector<std::vector<unsigned int> > _vpair;
347     //std::vector<std::vector<unsigned int> >::iterator _i;
348     std::vector<unsigned int> _pair;
349 
350   public:
351 
OBMolPairIter()352     OBMolPairIter() :_parent(nullptr) { }
353     OBMolPairIter(OBMol *mol);
354     OBMolPairIter(OBMol &mol);
355     OBMolPairIter(const OBMolPairIter &ai);
~OBMolPairIter()356     ~OBMolPairIter() { }
357 
358     OBMolPairIter& operator=(const OBMolPairIter &ai);
359     //! \return Whether the iterator can still advance (i.e., visit more 1-4 atom pairs)
360     operator bool() const        { return _pair.size()>0; }
361     //! Preincrement -- advance to the next 1-4 atom pair and return
362     OBMolPairIter& operator++();
363     //! \return A vector of two atom indexes specifying the 1-4 atom pair
364     //! \see OBAtom::GetIdx()
365     std::vector<unsigned int> operator*() const    { return _pair;     }
366   };
367 
368   class OBRing;
369   class OBRingData;
370 
371   //! \brief Iterate over all rings in an OBMol
372   class OBAPI OBMolRingIter {
373     std::vector<OBRing*>::iterator _i;
374     OBRing *_ptr;
375     OBMol *_parent;
376     OBRingData *_rings;
377   public:
378 
OBMolRingIter()379     OBMolRingIter() : _ptr(nullptr), _parent(nullptr), _rings(nullptr) { }
380     OBMolRingIter(OBMol *mol);
381     OBMolRingIter(OBMol &mol);
382     OBMolRingIter(const OBMolRingIter &ri);
~OBMolRingIter()383     ~OBMolRingIter() { }
384 
385     OBMolRingIter& operator=(const OBMolRingIter &ri);
386     //! \return Whether the iterator can advance (i.e., there are more rings)
387     operator bool()      const { return _ptr != nullptr; }
388     //! Preincrement -- advance to the next ring (if any) and return
389     OBMolRingIter& operator++();
390     //! Postincrement -- return the current state and advance to the next ring
391     OBMolRingIter  operator++(int);
392     //! \return A pointer to the current ring (if any)
393     OBRing* operator->() const { return _ptr; }
394     //! \return A reference to the current ring (if any)
395     OBRing& operator*()  const { return *_ptr;}
396   };
397 
398 #define FOR_ATOMS_OF_MOL(a,m)     for( OpenBabel::OBMolAtomIter     a(m); a; ++a )
399 #define FOR_BONDS_OF_MOL(b,m)     for( OpenBabel::OBMolBondIter     b(m); b; ++b )
400 #define FOR_NBORS_OF_ATOM(a,p)    for( OpenBabel::OBAtomAtomIter    a(p); a; ++a )
401 #define FOR_BONDS_OF_ATOM(b,p)    for( OpenBabel::OBAtomBondIter    b(p); b; ++b )
402 #define FOR_RESIDUES_OF_MOL(r,m)  for( OpenBabel::OBResidueIter     r(m); r; ++r )
403 #define FOR_ATOMS_OF_RESIDUE(a,r) for( OpenBabel::OBResidueAtomIter a(r); a; ++a )
404 #define FOR_DFS_OF_MOL(a,m)       for( OpenBabel::OBMolAtomDFSIter  a(m); a; ++a )
405 #define FOR_BFS_OF_MOL(a,m)       for( OpenBabel::OBMolAtomBFSIter  a(m); a; ++a )
406 #define FOR_BONDBFS_OF_MOL(b,m)   for( OpenBabel::OBMolBondBFSIter  b(m); b; ++b )
407 #define FOR_RINGS_OF_MOL(r,m)     for( OpenBabel::OBMolRingIter     r(m); r; ++r )
408 #define FOR_ANGLES_OF_MOL(a,m)    for( OpenBabel::OBMolAngleIter    a(m); a; ++a )
409 #define FOR_TORSIONS_OF_MOL(t,m)  for( OpenBabel::OBMolTorsionIter  t(m); t; ++t )
410 #define FOR_PAIRS_OF_MOL(p,m)     for( OpenBabel::OBMolPairIter     p(m); p; ++p )
411 
412 } // namespace OpenBabel
413 #endif // OB_OBITER_H
414 
415 //! \file obiter.h
416 //! \brief STL-style iterators for Open Babel.
417