1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
//
// Copyright (C) 2003-2006 greg Landrum and Rational Discovery LLC
//
// @@ All Rights Reserved @@
//
#ifndef _SEQS_HPP_
#define _SEQS_HPP_
#include <GraphMol/RDKitBase.h>
#include <RDBoost/python.h>
#include <iostream>
#include <utility>
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 T1, class T2, class T3>
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<T1, T2, T3> &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<T1, T2, T3> *__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: " <<which<< std::endl;
if (which >= 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<ROMol::QueryAtomIterator, Atom *, AtomCountFunctor>
QueryAtomIterSeq;
typedef ReadOnlySeq<ROMol::ConformerIterator, CONFORMER_SPTR &,
ConformerCountFunctor>
ConformerIterSeq;
} // namespace RDKit
#endif
|