// // Copyright (C) 2003-2006 greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // #ifndef _SEQS_HPP_ #define _SEQS_HPP_ #include #include #include namespace python = boost::python; namespace RDKit { class AtomCountFunctor { private: const ROMOL_SPTR _mol; public: AtomCountFunctor(ROMOL_SPTR mol) : _mol(std::move(mol)) {} unsigned int operator()() const { return _mol->getNumAtoms(); } }; class BondCountFunctor { private: const ROMOL_SPTR _mol; public: BondCountFunctor(ROMOL_SPTR mol) : _mol(std::move(mol)) {} unsigned int operator()() const { return _mol->getNumBonds(); } }; class ConformerCountFunctor { private: const ROMOL_SPTR _mol; public: ConformerCountFunctor(ROMOL_SPTR mol) : _mol(std::move(mol)) {} unsigned int operator()() const { return _mol->getNumConformers(); } }; // Note: T1 should be some iterator type, // T2 is the value when we dereference T template class ReadOnlySeq { private: T1 _start, _end, _pos; int _size; T3 _lenFunc; size_t _origLen; const ROMOL_SPTR _mol; public: ~ReadOnlySeq() = default; ReadOnlySeq(ROMOL_SPTR mol, T1 start, T1 end, T3 lenFunc) : _start(start), _end(end), _pos(start), _size(-1), _lenFunc(lenFunc), _origLen(lenFunc()), _mol(std::move(mol)) {} ReadOnlySeq(const ReadOnlySeq &other) : _start(other._start), _end(other._end), _pos(other._pos), _size(other._size), _lenFunc(other._lenFunc), _origLen(other._origLen), _mol(other._mol) {} void reset() { // std::cerr << "**** reset ****" << this<< std::endl; _pos = _start; } ReadOnlySeq *__iter__() { // std::cerr << "**** ITER ****" << this << std::endl; reset(); // std::cerr << " finish ****" << this << std::endl; return this; } T2 next() { // std::cerr << "\tnext: " << _pos._pos << " " << _end._pos << std::endl; if (_pos == _end) { PyErr_SetString(PyExc_StopIteration, "End of sequence hit"); throw python::error_already_set(); } if (_lenFunc() != _origLen) { PyErr_SetString(PyExc_RuntimeError, "Sequence modified during iteration"); throw python::error_already_set(); } T2 res = *_pos; ++_pos; return res; } T2 get_item(int which) { // std::cerr << "get_item: " <= len()) { PyErr_SetString(PyExc_IndexError, "End of sequence hit"); throw python::error_already_set(); } if (_lenFunc() != _origLen) { PyErr_SetString(PyExc_RuntimeError, "Sequence modified during iteration"); throw python::error_already_set(); } T1 it = _start; for (int i = 0; i < which; i++) { ++it; } return *it; } int len() { // std::cerr << "len " << std::endl; if (_size < 0) { _size = 0; for (T1 tmp = _start; tmp != _end; tmp++) { // std::cerr << "\tincr: " << std::endl; _size++; } } // std::cerr << "\tret" << std::endl; return _size; } }; typedef ReadOnlySeq QueryAtomIterSeq; typedef ReadOnlySeq ConformerIterSeq; } // namespace RDKit #endif