Commit d5134000 by Maarten L. Hekkelman

- fix new row iterators

- Residue constructor for sugars
parent 6f93fa37
......@@ -15,4 +15,5 @@ config.log
libtool
rsrc/lib-version.txt
version-info*.txt
src/revision.hpp
\ No newline at end of file
src/revision.hpp
test/pdb2cif-test
......@@ -1199,39 +1199,96 @@ inline Condition Not(Condition&& cond)
// -----------------------------------------------------------------------
// iterators
template<typename RowType>
template<typename RowType, typename... Ts>
class iterator_impl
{
public:
template<typename, typename...> friend class iterator_impl;
static constexpr size_t N = sizeof...(Ts);
using iterator_category = std::forward_iterator_tag;
using value_type = RowType;
using value_type = std::conditional_t<N == 0, RowType, std::tuple<Ts...>>;
using difference_type = std::ptrdiff_t;
using pointer = RowType*;
using reference = RowType&;
using pointer = value_type*;
using reference = value_type&;
friend class Category;
iterator_impl(ItemRow* data) : mCurrent(data) {}
iterator_impl(const iterator_impl& i) : mCurrent(i.mCurrent) {}
// default constructor, equal to end()
iterator_impl() {}
iterator_impl(const iterator_impl& rhs)
: mCurrent(rhs.mCurrent), mValue(rhs.mValue), mCix(rhs.mCix)
{
}
iterator_impl(ItemRow* data)
: mCurrent(data)
{
static_assert(N == 0, "Only valid if this is a row iterator, not a row<xxx> iterator");
}
iterator_impl(ItemRow* data, const std::array<size_t,N>& cix)
: mCurrent(data), mCix(cix) {}
template<typename IRowType>
iterator_impl(iterator_impl<IRowType, Ts...>& rhs)
: mCurrent(rhs.mCurrent), mCix(rhs.mCix)
{
if constexpr (N > 0)
mValue = get(mCurrent, std::make_index_sequence<N>());
}
template<typename IteratorType>
iterator_impl(IteratorType& i)
: mCurrent(*i) {}
template<typename IRowType>
iterator_impl(const iterator_impl<IRowType>& rhs, const std::array<size_t,N>& cix)
: mCurrent(rhs.mCurrent), mCix(cix)
{
if constexpr (N > 0)
mValue = get(mCurrent, std::make_index_sequence<N>());
}
iterator_impl& operator=(const iterator_impl& i)
{
mCurrent = i.mCurrent;
if constexpr (N != 0)
{
mCix = i.mCix;
mValue = i.mValue;
}
return *this;
}
virtual ~iterator_impl() = default;
reference operator*() { return mCurrent; }
pointer operator->() { return &mCurrent; }
reference operator*()
{
if constexpr (N == 0)
return mCurrent;
else
return mValue;
}
pointer operator->()
{
if constexpr (N == 0)
return &mCurrent;
else
return &mValue;
}
RowType row() const
{
return mCurrent;
}
iterator_impl& operator++()
{
mCurrent.next();
if constexpr (N != 0)
mValue = get(mCurrent, std::make_index_sequence<N>());
return *this;
}
......@@ -1246,125 +1303,92 @@ class iterator_impl
bool operator!=(const iterator_impl& rhs) const { return mCurrent != rhs.mCurrent; }
private:
template<std::size_t... Is>
std::tuple<Ts...> get(Row row, std::index_sequence<Is...>) const
{
if (row)
return std::tuple<Ts...>{row[mCix[Is]].template as<Ts>()...};
return {};
}
Row mCurrent;
value_type mValue;
std::array<size_t, N> mCix;
};
// --------------------------------------------------------------------
// Iterator proxy to iterate over a subset of rows selected by a Condition
// template<typename RowType, typename...>
// class conditional_iterator_proxy;
// template<typename RowType>
// class conditional_iterator_proxy<RowType>
// {
// public:
// iterator proxy
// using base_iterator = iterator_impl<RowType>;
// class conditional_iterator_impl
// {
// public:
// using iterator_category = std::forward_iterator_tag;
// using value_type = RowType;
// using difference_type = std::ptrdiff_t;
// using pointer = RowType*;
// using reference = RowType&;
// conditional_iterator_impl(Category& cat, base_iterator pos, const Condition& cond);
// conditional_iterator_impl(const conditional_iterator_impl& i) = default;
// conditional_iterator_impl& operator=(const conditional_iterator_impl& i) = default;
// virtual ~conditional_iterator_impl() = default;
// reference operator*() { return *mBegin; }
// pointer operator->() { return &*mBegin; }
// conditional_iterator_impl& operator++()
// {
// while (mBegin != mEnd)
// {
// if (++mBegin == mEnd)
// break;
// if ((*mCondition)(*mCat, *mBegin))
// break;
// }
// return *this;
// }
// conditional_iterator_impl operator++(int)
// {
// conditional_iterator_impl result(*this);
// this->operator++();
// return result;
// }
// bool operator==(const conditional_iterator_impl& rhs) const { return mBegin == rhs.mBegin; }
// bool operator!=(const conditional_iterator_impl& rhs) const { return mBegin != rhs.mBegin; }
// private:
// Category* mCat;
// base_iterator mBegin, mEnd;
// const Condition* mCondition;
// };
template<typename RowType, typename... Ts>
class iterator_proxy
{
public:
static constexpr const size_t N = sizeof...(Ts);
// using iterator = conditional_iterator_impl;
// using reference = typename iterator::reference;
using iterator = iterator_impl<RowType, Ts...>;
using row_iterator = iterator_impl<RowType>;
// conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond);
iterator_proxy(Category& cat, row_iterator pos, char const* const columns[N]);
// conditional_iterator_proxy(conditional_iterator_proxy&& p);
// conditional_iterator_proxy& operator=(conditional_iterator_proxy&& p);
iterator_proxy(iterator_proxy&& p);
iterator_proxy& operator=(iterator_proxy&& p);
// conditional_iterator_proxy(const conditional_iterator_proxy&) = delete;
// conditional_iterator_proxy& operator=(const conditional_iterator_proxy&) = delete;
iterator_proxy(const iterator_proxy&) = delete;
iterator_proxy& operator=(const iterator_proxy&) = delete;
// iterator begin() const;
// iterator end() const;
iterator begin() const { return iterator(mCBegin, mCix); }
iterator end() const { return iterator(mCEnd, mCix); }
// bool empty() const;
bool empty() const { return mCBegin == mCEnd; }
// explicit operator bool() const { return not empty(); }
explicit operator bool() const { return not empty(); }
// size_t size() const { return std::distance(begin(), end()); }
size_t size() const { return std::distance(begin(), end()); }
// RowType front() { return *begin(); }
RowType front() { return *begin(); }
// Category& category() const { return *mCat;}
Category& category() const { return *mCat;}
// void swap(conditional_iterator_proxy& rhs);
void swap(iterator_proxy& rhs)
{
std::swap(mCat, rhs.mCat);
std::swap(mCBegin, rhs.mCBegin);
std::swap(mCEnd, rhs.mCEnd);
std::swap(mCix, rhs.mCix);
}
// private:
// Category* mCat;
// Condition mCondition;
// base_iterator mCBegin, mCEnd;
// };
private:
Category* mCat;
row_iterator mCBegin, mCEnd;
std::array<size_t,N> mCix;
};
// --------------------------------------------------------------------
// special case, returns tuples instead of a row
// conditional iterator proxy
template<typename RowType, typename... Ts>
class conditional_iterator_proxy
{
public:
using base_iterator = iterator_impl<RowType>;
static constexpr const size_t N = sizeof...(Ts);
using base_iterator = iterator_impl<RowType, Ts...>;
using value_type = typename base_iterator::value_type;
using row_type = std::remove_cv_t<RowType>;
using row_iterator = iterator_impl<row_type>;
class conditional_iterator_impl
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = std::conditional_t<N == 0, RowType, std::tuple<Ts...>>;
using value_type = conditional_iterator_proxy::value_type;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
// conditional_iterator_impl(Category& cat, base_iterator pos, const Condition& cond);
conditional_iterator_impl(Category& cat, base_iterator pos, const Condition& cond, std::array<size_t,N> columns);
conditional_iterator_impl(Category& cat, row_iterator pos, const Condition& cond, const std::array<size_t,N>& cix);
conditional_iterator_impl(const conditional_iterator_impl& i) = default;
conditional_iterator_impl& operator=(const conditional_iterator_impl& i) = default;
......@@ -1372,18 +1396,12 @@ class conditional_iterator_proxy
reference operator*()
{
if constexpr (N == 0)
return *mBegin;
else
return mCurrent;
return *mBegin;
}
pointer operator->()
{
if constexpr (N == 0)
return &*mBegin;
else
return &mCurrent;
return &*mBegin;
}
conditional_iterator_impl& operator++()
......@@ -1393,12 +1411,8 @@ class conditional_iterator_proxy
if (++mBegin == mEnd)
break;
if ((*mCondition)(*mCat, *mBegin))
{
if constexpr (N != 0)
mCurrent = get(*mBegin, std::make_index_sequence<N>());
if ((*mCondition)(*mCat, mBegin.row()))
break;
}
}
return *this;
......@@ -1416,24 +1430,16 @@ class conditional_iterator_proxy
private:
template<std::size_t... Is>
std::tuple<Ts...> get(Row row, std::index_sequence<Is...>) const
{
return std::tuple<Ts...>{row[mCix[Is]].template as<Ts>()...};
}
Category* mCat;
base_iterator mBegin, mEnd;
const Condition* mCondition;
value_type mCurrent;
std::array<size_t,N> mCix;
};
using iterator = conditional_iterator_impl;
using reference = typename iterator::reference;
conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond);
conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond, char const* const columns[N]);
// conditional_iterator_proxy(Category& cat, row_iterator pos, Condition&& cond);
conditional_iterator_proxy(Category& cat, row_iterator pos, Condition&& cond, char const* const columns[N]);
conditional_iterator_proxy(conditional_iterator_proxy&& p);
conditional_iterator_proxy& operator=(conditional_iterator_proxy&& p);
......@@ -1459,7 +1465,7 @@ class conditional_iterator_proxy
private:
Category* mCat;
Condition mCondition;
base_iterator mCBegin, mCEnd;
row_iterator mCBegin, mCEnd;
std::array<size_t,N> mCix;
};
......@@ -1639,8 +1645,8 @@ class Category
iterator begin();
iterator end();
const_iterator cbegin();
const_iterator cend();
const_iterator cbegin() const;
const_iterator cend() const;
const_iterator begin() const;
const_iterator end() const;
......@@ -1655,14 +1661,21 @@ class Category
Row operator[](Condition&& cond);
template<typename... Ts, size_t N>
iterator_proxy<Row, Ts...> rows(char const* const (&columns)[N])
{
static_assert(sizeof...(Ts) == N, "The number of column titles should be equal to the number of types to return");
return iterator_proxy<Row, Ts...>(*this, begin(), columns );
}
conditional_iterator_proxy<Row> find(Condition&& cond)
{
return { *this, begin(), std::forward<Condition>(cond) };
return find(cbegin(), std::forward<Condition>(cond));
}
conditional_iterator_proxy<Row> find(const_iterator pos, Condition&& cond)
{
return { *this, pos, std::forward<Condition>(cond) };
return { *this, pos, std::forward<Condition>(cond), {} };
}
template<typename... Ts, size_t N>
......@@ -1672,10 +1685,12 @@ class Category
return { *this, begin(), std::forward<Condition>(cond), columns };
}
// conditional_iterator_proxy<Row> find(const_iterator pos, Condition&& cond)
// {
// return { *this, pos, std::forward<Condition>(cond) };
// }
template<typename... Ts, size_t N>
conditional_iterator_proxy<Row, Ts...> find(const_iterator pos, Condition&& cond, char const* const (&columns)[N])
{
static_assert(sizeof...(Ts) == N, "The number of column titles should be equal to the number of types to return");
return { *this, pos, std::forward<Condition>(cond), columns };
}
bool exists(Condition&& cond) const;
......@@ -1914,19 +1929,22 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b)
// --------------------------------------------------------------------
template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_impl::conditional_iterator_impl(Category& cat, base_iterator pos, const Condition& cond, std::array<size_t,N> cix)
: mCat(&cat), mBegin(pos), mEnd(cat.end()), mCondition(&cond), mCix(cix)
iterator_proxy<RowType, Ts...>::iterator_proxy(Category& cat, row_iterator pos, char const* const columns[N])
: mCat(&cat)
, mCBegin(pos)
, mCEnd(cat.end())
{
// skip until the first row matching cond
for (size_t i = 0; i < N; ++i)
mCix[i] = mCat->getColumnIndex(columns[i]);
}
while (mBegin != mEnd and not (*mCondition)(*mCat, *mBegin))
++mBegin;
// --------------------------------------------------------------------
if constexpr (N != 0)
{
if (mBegin != mEnd)
mCurrent = get(*mBegin, std::make_index_sequence<N>());
}
template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_impl::conditional_iterator_impl(
Category& cat, row_iterator pos, const Condition& cond, const std::array<size_t,N>& cix)
: mCat(&cat), mBegin(pos, cix), mEnd(cat.end(), cix), mCondition(&cond)
{
}
template<typename RowType, typename... Ts>
......@@ -1934,25 +1952,22 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(condition
: mCat(nullptr), mCBegin(p.mCBegin), mCEnd(p.mCEnd), mCix(p.mCix)
{
std::swap(mCat, p.mCat);
std::swap(mCix, p.mCix);
mCondition.swap(p.mCondition);
}
template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond)
: mCat(&cat), mCondition(std::move(cond))
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category& cat, row_iterator pos, Condition&& cond, const char* const columns[N])
: mCat(&cat)
, mCondition(std::move(cond))
, mCBegin(pos)
, mCEnd(cat.end())
{
mCondition.prepare(cat);
while (mCBegin != mCEnd and not mCondition(*mCat, *mCBegin))
while (mCBegin != mCEnd and not mCondition(*mCat, mCBegin.row()))
++mCBegin;
}
template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond, const char* const columns[N])
: conditional_iterator_proxy(cat, pos, std::forward<Condition>(cond))
{
for (size_t i = 0; i < N; ++i)
mCix[i] = mCat->getColumnIndex(columns[i]);
}
......
......@@ -484,59 +484,8 @@ class Structure
/// Will asssign new atom_id's to all atoms. Be carefull
void sortAtoms();
// // iterator for all residues
// class residue_iterator : public std::iterator<std::forward_iterator_tag, const Residue>
// {
// public:
// typedef std::iterator<std::forward_iterator_tag, const Residue> baseType;
// typedef typename baseType::pointer pointer;
// typedef typename baseType::reference reference;
// typedef std::list<Polymer>::const_iterator poly_iterator;
// residue_iterator(const Structure* s, poly_iterator polyIter, size_t polyResIndex, size_t nonPolyIndex);
// reference operator*();
// pointer operator->();
// residue_iterator& operator++();
// residue_iterator operator++(int);
// bool operator==(const residue_iterator& rhs) const;
// bool operator!=(const residue_iterator& rhs) const;
// private:
// const Structure& mStructure;
// poly_iterator mPolyIter;
// size_t mPolyResIndex;
// size_t mNonPolyIndex;
// };
// class residue_view
// {
// public:
// residue_view(const Structure* s) : mStructure(s) {}
// residue_view(const residue_view& rhs) : mStructure(rhs.mStructure) {}
// residue_view& operator=(residue_view& rhs)
// {
// mStructure = rhs.mStructure;
// return *this;
// }
// residue_iterator begin() const { return residue_iterator(mStructure, mStructure->mPolymers.begin(), 0, 0); }
// residue_iterator end() const { return residue_iterator(mStructure, mStructure->mPolymers.end(), 0, mStructure->mNonPolymers.size()); }
// size_t size() const
// {
// size_t ps = std::accumulate(mStructure->mPolymers.begin(), mStructure->mPolymers.end(), 0UL, [](size_t s, auto& p) { return s + p.size(); });
// return ps + mStructure->mNonPolymers.size();
// }
// private:
// const Structure* mStructure;
// };
// residue_view residues() const { return residue_view(this); }
const std::vector<Residue>& getNonPolymers() const { return mNonPolymers; }
const std::vector<Residue>& getBranchResidues() const { return mBranchResidues; }
private:
friend Polymer;
......
......@@ -1741,7 +1741,17 @@ Category::iterator Category::begin()
Category::iterator Category::end()
{
return iterator(nullptr);
return iterator();
}
Category::const_iterator Category::cbegin() const
{
return const_iterator(mHead);
}
Category::const_iterator Category::cend() const
{
return const_iterator();
}
Category::const_iterator Category::begin() const
......@@ -1751,7 +1761,7 @@ Category::const_iterator Category::begin() const
Category::const_iterator Category::end() const
{
return const_iterator(nullptr);
return const_iterator();
}
bool Category::hasParent(Row r, const Category& parentCat, const ValidateLink& link) const
......
......@@ -716,21 +716,29 @@ std::ostream& operator<<(std::ostream& os, const Atom& atom)
// --------------------------------------------------------------------
// residue
// First constructor used to be for waters only, but now accepts sugars as well.
Residue::Residue(const Structure& structure, const std::string& compoundID,
const std::string& asymID, const std::string& authSeqID)
: mStructure(&structure), mCompoundID(compoundID)
, mAsymID(asymID), mAuthSeqID(authSeqID)
{
assert(mCompoundID == "HOH");
for (auto& a: mStructure->atoms())
{
if (a.labelAsymID() != mAsymID or
a.labelCompID() != mCompoundID)
continue;
if (not mAuthSeqID.empty() and a.authSeqID() != mAuthSeqID) // water!
continue;
if (compoundID == "HOH")
{
if (not mAuthSeqID.empty() and a.authSeqID() != mAuthSeqID)
continue;
}
else
{
if (mSeqID > 0 and a.labelSeqID() != mSeqID)
continue;
}
mAtoms.push_back(a);
}
......@@ -1842,6 +1850,25 @@ const Residue& Structure::getResidue(const std::string& asymID, const std::strin
}
}
if (seqID == 0)
{
for (auto& res: mNonPolymers)
{
if (res.asymID() != asymID or res.compoundID() != compID)
continue;
return res;
}
}
for (auto& res: mBranchResidues)
{
if (res.asymID() != asymID or res.compoundID() != compID or res.seqID() != seqID)
continue;
return res;
}
throw std::out_of_range("Could not find residue " + asymID + '/' + std::to_string(seqID));
}
......
......@@ -1154,6 +1154,41 @@ _test.name
// query tests
for (const auto& [id, name]: db["test"].rows<int, std::optional<std::string>>({ "id", "name" }))
{
switch (id)
{
case 1: BOOST_CHECK(name == "aap"); break;
case 2: BOOST_CHECK(name == "noot"); break;
case 3: BOOST_CHECK(name == "mies"); break;
case 4:
case 5: BOOST_CHECK(not name); break;
default:
BOOST_CHECK(false);
}
}
}
BOOST_AUTO_TEST_CASE(c3)
{
cif::VERBOSE = 1;
auto f = R"(data_TEST
#
loop_
_test.id
_test.name
1 aap
2 noot
3 mies
4 .
5 ?
)"_cf;
auto& db = f.firstDatablock();
// query tests
for (const auto& [id, name]: db["test"].find<int, std::optional<std::string>>(cif::All(), { "id", "name" }))
{
switch (id)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment