Commit 6f93fa37 by Maarten L. Hekkelman

new conditional iterator type

parent 598f953c
...@@ -574,7 +574,7 @@ namespace detail ...@@ -574,7 +574,7 @@ namespace detail
} }
template<typename... Ts> template<typename... Ts>
auto tie(Ts&... v) -> detail::tieWrap<Ts&...> auto tie(Ts&... v)
{ {
return detail::tieWrap<Ts&...>(std::forward<Ts&>(v)...); return detail::tieWrap<Ts&...>(std::forward<Ts&>(v)...);
} }
...@@ -682,16 +682,21 @@ class Row ...@@ -682,16 +682,21 @@ class Row
return detail::ItemReference(itemTag.c_str(), column, *this); return detail::ItemReference(itemTag.c_str(), column, *this);
} }
template<typename... C> template<typename... Ts, size_t N>
auto get(C... columns) const -> detail::getRowResult<C...> std::tuple<Ts...> get(char const * const (&columns)[N])
{ {
std::array<size_t,sizeof...(C)> cix; static_assert(sizeof...(Ts) == N, "Number of columns should be equal to number of types to return");
auto c = cix.begin(); std::array<size_t, N> cix;
for (auto col: { columns... }) for (size_t i = 0; i < N; ++i)
*c++ = ColumnForItemTag(col); cix[i] = ColumnForItemTag(columns[i]);
return detail::getRowResult<Ts...>(*this, std::move(cix));
}
return detail::getRowResult<C...>(*this, std::move(cix)); template<typename... C>
auto get(C... columns) const
{
return detail::getRowResult<C...>(*this, { ColumnForItemTag(columns)... });
} }
void assign(const std::vector<Item>& values); void assign(const std::vector<Item>& values);
...@@ -751,9 +756,9 @@ struct AllConditionImpl : public ConditionImpl ...@@ -751,9 +756,9 @@ struct AllConditionImpl : public ConditionImpl
virtual void str(std::ostream& os) const { os << "*"; } virtual void str(std::ostream& os) const { os << "*"; }
}; };
struct orConditionImpl; struct OrConditionImpl;
struct andConditionImpl; struct AndConditionImpl;
struct notConditionImpl; struct NotConditionImpl;
} }
...@@ -805,9 +810,9 @@ class Condition ...@@ -805,9 +810,9 @@ class Condition
friend Condition operator||(Condition&& a, Condition&& b); friend Condition operator||(Condition&& a, Condition&& b);
friend Condition operator&&(Condition&& a, Condition&& b); friend Condition operator&&(Condition&& a, Condition&& b);
friend struct detail::orConditionImpl; friend struct detail::OrConditionImpl;
friend struct detail::andConditionImpl; friend struct detail::AndConditionImpl;
friend struct detail::notConditionImpl; friend struct detail::NotConditionImpl;
void swap(Condition& rhs) void swap(Condition& rhs)
{ {
...@@ -901,11 +906,11 @@ struct KeyMatchesConditionImpl : public ConditionImpl ...@@ -901,11 +906,11 @@ struct KeyMatchesConditionImpl : public ConditionImpl
}; };
template<typename T> template<typename T>
struct anyIsConditionImpl : public ConditionImpl struct AnyIsConditionImpl : public ConditionImpl
{ {
typedef T valueType; typedef T valueType;
anyIsConditionImpl(const valueType& value) AnyIsConditionImpl(const valueType& value)
: mValue(value) {} : mValue(value) {}
virtual bool test(const Category& c, const Row& r) const; virtual bool test(const Category& c, const Row& r) const;
...@@ -917,9 +922,9 @@ struct anyIsConditionImpl : public ConditionImpl ...@@ -917,9 +922,9 @@ struct anyIsConditionImpl : public ConditionImpl
valueType mValue; valueType mValue;
}; };
struct anyMatchesConditionImpl : public ConditionImpl struct AnyMatchesConditionImpl : public ConditionImpl
{ {
anyMatchesConditionImpl(const std::regex& rx) AnyMatchesConditionImpl(const std::regex& rx)
: mRx(rx) {} : mRx(rx) {}
virtual bool test(const Category& c, const Row& r) const; virtual bool test(const Category& c, const Row& r) const;
...@@ -931,31 +936,16 @@ struct anyMatchesConditionImpl : public ConditionImpl ...@@ -931,31 +936,16 @@ struct anyMatchesConditionImpl : public ConditionImpl
std::regex mRx; std::regex mRx;
}; };
struct allConditionImpl : public ConditionImpl struct AndConditionImpl : public ConditionImpl
{
allConditionImpl() {}
virtual bool test(const Category& c, const Row& r) const
{
return true;
}
virtual void str(std::ostream& os) const
{
os << "*";
}
};
struct andConditionImpl : public ConditionImpl
{ {
andConditionImpl(Condition&& a, Condition&& b) AndConditionImpl(Condition&& a, Condition&& b)
: mA(nullptr), mB(nullptr) : mA(nullptr), mB(nullptr)
{ {
std::swap(mA, a.mImpl); std::swap(mA, a.mImpl);
std::swap(mB, b.mImpl); std::swap(mB, b.mImpl);
} }
~andConditionImpl() ~AndConditionImpl()
{ {
delete mA; delete mA;
delete mB; delete mB;
...@@ -985,16 +975,16 @@ struct andConditionImpl : public ConditionImpl ...@@ -985,16 +975,16 @@ struct andConditionImpl : public ConditionImpl
ConditionImpl* mB; ConditionImpl* mB;
}; };
struct orConditionImpl : public ConditionImpl struct OrConditionImpl : public ConditionImpl
{ {
orConditionImpl(Condition&& a, Condition&& b) OrConditionImpl(Condition&& a, Condition&& b)
: mA(nullptr), mB(nullptr) : mA(nullptr), mB(nullptr)
{ {
std::swap(mA, a.mImpl); std::swap(mA, a.mImpl);
std::swap(mB, b.mImpl); std::swap(mB, b.mImpl);
} }
~orConditionImpl() ~OrConditionImpl()
{ {
delete mA; delete mA;
delete mB; delete mB;
...@@ -1024,15 +1014,15 @@ struct orConditionImpl : public ConditionImpl ...@@ -1024,15 +1014,15 @@ struct orConditionImpl : public ConditionImpl
ConditionImpl* mB; ConditionImpl* mB;
}; };
struct notConditionImpl : public ConditionImpl struct NotConditionImpl : public ConditionImpl
{ {
notConditionImpl(Condition&& a) NotConditionImpl(Condition&& a)
: mA(nullptr) : mA(nullptr)
{ {
std::swap(mA, a.mImpl); std::swap(mA, a.mImpl);
} }
~notConditionImpl() ~NotConditionImpl()
{ {
delete mA; delete mA;
} }
...@@ -1062,7 +1052,7 @@ struct notConditionImpl : public ConditionImpl ...@@ -1062,7 +1052,7 @@ struct notConditionImpl : public ConditionImpl
inline Condition operator&&(Condition&& a, Condition&& b) inline Condition operator&&(Condition&& a, Condition&& b)
{ {
if (a.mImpl and b.mImpl) if (a.mImpl and b.mImpl)
return Condition(new detail::andConditionImpl(std::move(a), std::move(b))); return Condition(new detail::AndConditionImpl(std::move(a), std::move(b)));
if (a.mImpl) if (a.mImpl)
return Condition(std::move(a)); return Condition(std::move(a));
return Condition(std::move(b)); return Condition(std::move(b));
...@@ -1071,7 +1061,7 @@ inline Condition operator&&(Condition&& a, Condition&& b) ...@@ -1071,7 +1061,7 @@ inline Condition operator&&(Condition&& a, Condition&& b)
inline Condition operator||(Condition&& a, Condition&& b) inline Condition operator||(Condition&& a, Condition&& b)
{ {
if (a.mImpl and b.mImpl) if (a.mImpl and b.mImpl)
return Condition(new detail::orConditionImpl(std::move(a), std::move(b))); return Condition(new detail::OrConditionImpl(std::move(a), std::move(b)));
if (a.mImpl) if (a.mImpl)
return Condition(std::move(a)); return Condition(std::move(a));
return Condition(std::move(b)); return Condition(std::move(b));
...@@ -1117,13 +1107,13 @@ inline Condition operator==(const Key& key, const Empty&) ...@@ -1117,13 +1107,13 @@ inline Condition operator==(const Key& key, const Empty&)
template<typename T> template<typename T>
Condition operator!=(const Key& key, const T& v) Condition operator!=(const Key& key, const T& v)
{ {
return Condition(new detail::notConditionImpl(operator==(key, v))); return Condition(new detail::NotConditionImpl(operator==(key, v)));
} }
inline Condition operator!=(const Key& key, const char* v) inline Condition operator!=(const Key& key, const char* v)
{ {
std::string value(v ? v : ""); std::string value(v ? v : "");
return Condition(new detail::notConditionImpl(operator==(key, value))); return Condition(new detail::NotConditionImpl(operator==(key, value)));
} }
template<typename T> template<typename T>
...@@ -1185,7 +1175,7 @@ struct any ...@@ -1185,7 +1175,7 @@ struct any
template<typename T> template<typename T>
Condition operator==(const T& v) const Condition operator==(const T& v) const
{ {
return Condition(new detail::anyIsConditionImpl<T>(v)); return Condition(new detail::AnyIsConditionImpl<T>(v));
} }
}; };
...@@ -1193,17 +1183,17 @@ template<> ...@@ -1193,17 +1183,17 @@ template<>
inline inline
Condition any::operator==(const std::regex& rx) const Condition any::operator==(const std::regex& rx) const
{ {
return Condition(new detail::anyMatchesConditionImpl(rx)); return Condition(new detail::AnyMatchesConditionImpl(rx));
} }
inline Condition All() inline Condition All()
{ {
return Condition(new detail::allConditionImpl()); return Condition(new detail::AllConditionImpl());
} }
inline Condition Not(Condition&& cond) inline Condition Not(Condition&& cond)
{ {
return Condition(new detail::notConditionImpl(std::move(cond))); return Condition(new detail::NotConditionImpl(std::move(cond)));
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
...@@ -1262,30 +1252,139 @@ class iterator_impl ...@@ -1262,30 +1252,139 @@ class iterator_impl
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Iterator proxy to iterate over a subset of rows selected by a Condition // Iterator proxy to iterate over a subset of rows selected by a Condition
template<typename RowType> // template<typename RowType, typename...>
// class conditional_iterator_proxy;
// template<typename RowType>
// class conditional_iterator_proxy<RowType>
// {
// public:
// 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;
// };
// using iterator = conditional_iterator_impl;
// using reference = typename iterator::reference;
// conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond);
// conditional_iterator_proxy(conditional_iterator_proxy&& p);
// conditional_iterator_proxy& operator=(conditional_iterator_proxy&& p);
// conditional_iterator_proxy(const conditional_iterator_proxy&) = delete;
// conditional_iterator_proxy& operator=(const conditional_iterator_proxy&) = delete;
// iterator begin() const;
// iterator end() const;
// bool empty() const;
// explicit operator bool() const { return not empty(); }
// size_t size() const { return std::distance(begin(), end()); }
// RowType front() { return *begin(); }
// Category& category() const { return *mCat;}
// void swap(conditional_iterator_proxy& rhs);
// private:
// Category* mCat;
// Condition mCondition;
// base_iterator mCBegin, mCEnd;
// };
// --------------------------------------------------------------------
// special case, returns tuples instead of a row
template<typename RowType, typename... Ts>
class conditional_iterator_proxy class conditional_iterator_proxy
{ {
public: public:
using base_iterator = iterator_impl<RowType>; using base_iterator = iterator_impl<RowType>;
static constexpr const size_t N = sizeof...(Ts);
class conditional_iterator_impl class conditional_iterator_impl
{ {
public: public:
using iterator_category = std::forward_iterator_tag; 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 difference_type = std::ptrdiff_t;
using pointer = RowType*; using pointer = value_type*;
using reference = RowType&; 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);
conditional_iterator_impl(Category& cat, base_iterator pos, const Condition& cond, std::array<size_t,N> columns);
conditional_iterator_impl(const conditional_iterator_impl& i) = default; conditional_iterator_impl(const conditional_iterator_impl& i) = default;
conditional_iterator_impl& operator=(const conditional_iterator_impl& i) = default; conditional_iterator_impl& operator=(const conditional_iterator_impl& i) = default;
virtual ~conditional_iterator_impl() = default; virtual ~conditional_iterator_impl() = default;
reference operator*() { return *mBegin; } reference operator*()
pointer operator->() { return &*mBegin; } {
if constexpr (N == 0)
return *mBegin;
else
return mCurrent;
}
pointer operator->()
{
if constexpr (N == 0)
return &*mBegin;
else
return &mCurrent;
}
conditional_iterator_impl& operator++() conditional_iterator_impl& operator++()
{ {
...@@ -1295,8 +1394,12 @@ class conditional_iterator_proxy ...@@ -1295,8 +1394,12 @@ class conditional_iterator_proxy
break; break;
if ((*mCondition)(*mCat, *mBegin)) if ((*mCondition)(*mCat, *mBegin))
{
if constexpr (N != 0)
mCurrent = get(*mBegin, std::make_index_sequence<N>());
break; break;
} }
}
return *this; return *this;
} }
...@@ -1312,15 +1415,25 @@ class conditional_iterator_proxy ...@@ -1312,15 +1415,25 @@ class conditional_iterator_proxy
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: 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; Category* mCat;
base_iterator mBegin, mEnd; base_iterator mBegin, mEnd;
const Condition* mCondition; const Condition* mCondition;
value_type mCurrent;
std::array<size_t,N> mCix;
}; };
using iterator = conditional_iterator_impl; using iterator = conditional_iterator_impl;
using reference = typename iterator::reference; 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);
conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond, char const* const columns[N]);
conditional_iterator_proxy(conditional_iterator_proxy&& p); conditional_iterator_proxy(conditional_iterator_proxy&& p);
conditional_iterator_proxy& operator=(conditional_iterator_proxy&& p); conditional_iterator_proxy& operator=(conditional_iterator_proxy&& p);
...@@ -1347,6 +1460,7 @@ class conditional_iterator_proxy ...@@ -1347,6 +1460,7 @@ class conditional_iterator_proxy
Category* mCat; Category* mCat;
Condition mCondition; Condition mCondition;
base_iterator mCBegin, mCEnd; base_iterator mCBegin, mCEnd;
std::array<size_t,N> mCix;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -1551,6 +1665,18 @@ class Category ...@@ -1551,6 +1665,18 @@ class Category
return { *this, pos, std::forward<Condition>(cond) }; return { *this, pos, std::forward<Condition>(cond) };
} }
template<typename... Ts, size_t N>
conditional_iterator_proxy<Row, Ts...> find(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, begin(), std::forward<Condition>(cond), columns };
}
// conditional_iterator_proxy<Row> find(const_iterator pos, Condition&& cond)
// {
// return { *this, pos, std::forward<Condition>(cond) };
// }
bool exists(Condition&& cond) const; bool exists(Condition&& cond) const;
RowSet orderBy(const std::string& Item) RowSet orderBy(const std::string& Item)
...@@ -1733,7 +1859,7 @@ namespace detail ...@@ -1733,7 +1859,7 @@ namespace detail
template<typename T> template<typename T>
inline inline
bool anyIsConditionImpl<T>::test(const Category& c, const Row& r) const bool AnyIsConditionImpl<T>::test(const Category& c, const Row& r) const
{ {
bool result = false; bool result = false;
for (auto& f: c.fields()) for (auto& f: c.fields())
...@@ -1752,7 +1878,7 @@ bool anyIsConditionImpl<T>::test(const Category& c, const Row& r) const ...@@ -1752,7 +1878,7 @@ bool anyIsConditionImpl<T>::test(const Category& c, const Row& r) const
return result; return result;
} }
inline bool anyMatchesConditionImpl::test(const Category& c, const Row& r) const inline bool AnyMatchesConditionImpl::test(const Category& c, const Row& r) const
{ {
bool result = false; bool result = false;
for (auto& f: c.fields()) for (auto& f: c.fields())
...@@ -1787,26 +1913,32 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b) ...@@ -1787,26 +1913,32 @@ inline void swap(cif::detail::ItemReference& a, cif::detail::ItemReference& b)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template<typename RowType> template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType>::conditional_iterator_impl::conditional_iterator_impl(Category& cat, base_iterator pos, const Condition& cond) 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) : mCat(&cat), mBegin(pos), mEnd(cat.end()), mCondition(&cond), mCix(cix)
{ {
// skip until the first row matching cond // skip until the first row matching cond
while (mBegin != mEnd and not (*mCondition)(*mCat, *mBegin)) while (mBegin != mEnd and not (*mCondition)(*mCat, *mBegin))
++mBegin; ++mBegin;
if constexpr (N != 0)
{
if (mBegin != mEnd)
mCurrent = get(*mBegin, std::make_index_sequence<N>());
}
} }
template<typename RowType> template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType>::conditional_iterator_proxy(conditional_iterator_proxy&& p) conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(conditional_iterator_proxy&& p)
: mCat(nullptr), mCBegin(p.mCBegin), mCEnd(p.mCEnd) : mCat(nullptr), mCBegin(p.mCBegin), mCEnd(p.mCEnd), mCix(p.mCix)
{ {
std::swap(mCat, p.mCat); std::swap(mCat, p.mCat);
mCondition.swap(p.mCondition); mCondition.swap(p.mCondition);
} }
template<typename RowType> template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType>::conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond) conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category& cat, base_iterator pos, Condition&& cond)
: mCat(&cat), mCondition(std::move(cond)) : mCat(&cat), mCondition(std::move(cond))
, mCBegin(pos) , mCBegin(pos)
, mCEnd(cat.end()) , mCEnd(cat.end())
...@@ -1817,38 +1949,47 @@ conditional_iterator_proxy<RowType>::conditional_iterator_proxy(Category& cat, b ...@@ -1817,38 +1949,47 @@ conditional_iterator_proxy<RowType>::conditional_iterator_proxy(Category& cat, b
++mCBegin; ++mCBegin;
} }
template<typename RowType> template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType>& conditional_iterator_proxy<RowType>::operator=(conditional_iterator_proxy&& p) 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]);
}
template<typename RowType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>& conditional_iterator_proxy<RowType, Ts...>::operator=(conditional_iterator_proxy&& p)
{ {
swap(p); swap(p);
return *this; return *this;
} }
template<typename RowType> template<typename RowType, typename... Ts>
typename conditional_iterator_proxy<RowType>::iterator conditional_iterator_proxy<RowType>::begin() const typename conditional_iterator_proxy<RowType, Ts...>::iterator conditional_iterator_proxy<RowType, Ts...>::begin() const
{ {
return iterator(*mCat, mCBegin, mCondition); return iterator(*mCat, mCBegin, mCondition, mCix);
} }
template<typename RowType> template<typename RowType, typename... Ts>
typename conditional_iterator_proxy<RowType>::iterator conditional_iterator_proxy<RowType>::end() const typename conditional_iterator_proxy<RowType, Ts...>::iterator conditional_iterator_proxy<RowType, Ts...>::end() const
{ {
return iterator(*mCat, mCEnd, mCondition); return iterator(*mCat, mCEnd, mCondition, mCix);
} }
template<typename RowType> template<typename RowType, typename... Ts>
bool conditional_iterator_proxy<RowType>::empty() const bool conditional_iterator_proxy<RowType, Ts...>::empty() const
{ {
return mCBegin == mCEnd; return mCBegin == mCEnd;
} }
template<typename RowType> template<typename RowType, typename... Ts>
void conditional_iterator_proxy<RowType>::swap(conditional_iterator_proxy& rhs) void conditional_iterator_proxy<RowType, Ts...>::swap(conditional_iterator_proxy& rhs)
{ {
std::swap(mCat, rhs.mCat); std::swap(mCat, rhs.mCat);
mCondition.swap(rhs.mCondition); mCondition.swap(rhs.mCondition);
std::swap(mCBegin, rhs.mCBegin); std::swap(mCBegin, rhs.mCBegin);
std::swap(mCEnd, rhs.mCEnd); std::swap(mCEnd, rhs.mCEnd);
std::swap(mCix, rhs.mCix);
} }
} }
......
...@@ -443,6 +443,7 @@ class Structure ...@@ -443,6 +443,7 @@ class Structure
std::list<Polymer>& polymers() { return mPolymers; } std::list<Polymer>& polymers() { return mPolymers; }
const std::vector<Residue>& nonPolymers() const { return mNonPolymers; } const std::vector<Residue>& nonPolymers() const { return mNonPolymers; }
const std::vector<Residue>& branchResidues() const { return mBranchResidues; }
Atom getAtomByID(std::string id) const; Atom getAtomByID(std::string id) const;
// Atom getAtomByLocation(Point pt, float maxDistance) const; // Atom getAtomByLocation(Point pt, float maxDistance) const;
...@@ -450,10 +451,6 @@ class Structure ...@@ -450,10 +451,6 @@ class Structure
Atom getAtomByLabel(const std::string& atomID, const std::string& asymID, Atom getAtomByLabel(const std::string& atomID, const std::string& asymID,
const std::string& compID, int seqID, const std::string& altID = ""); const std::string& compID, int seqID, const std::string& altID = "");
// Atom getAtomByAuth(const std::string& atomID, const std::string& asymID,
// const std::string& compID, int seqID, const std::string& altID = "",
// const std::string& pdbxAuthInsCode = "");
const Residue& getResidue(const std::string& asymID, const std::string& compID, int seqID) const; const Residue& getResidue(const std::string& asymID, const std::string& compID, int seqID) const;
// map between auth and label locations // map between auth and label locations
...@@ -487,65 +484,65 @@ class Structure ...@@ -487,65 +484,65 @@ class Structure
/// Will asssign new atom_id's to all atoms. Be carefull /// Will asssign new atom_id's to all atoms. Be carefull
void sortAtoms(); void sortAtoms();
// iterator for all residues // // iterator for all residues
class residue_iterator : public std::iterator<std::forward_iterator_tag, const Residue> // class residue_iterator : public std::iterator<std::forward_iterator_tag, const Residue>
{ // {
public: // public:
typedef std::iterator<std::forward_iterator_tag, const Residue> baseType; // typedef std::iterator<std::forward_iterator_tag, const Residue> baseType;
typedef typename baseType::pointer pointer; // typedef typename baseType::pointer pointer;
typedef typename baseType::reference reference; // typedef typename baseType::reference reference;
typedef std::list<Polymer>::const_iterator poly_iterator; // typedef std::list<Polymer>::const_iterator poly_iterator;
residue_iterator(const Structure* s, poly_iterator polyIter, size_t polyResIndex, size_t nonPolyIndex); // residue_iterator(const Structure* s, poly_iterator polyIter, size_t polyResIndex, size_t nonPolyIndex);
reference operator*(); // reference operator*();
pointer operator->(); // pointer operator->();
residue_iterator& operator++(); // residue_iterator& operator++();
residue_iterator operator++(int); // residue_iterator operator++(int);
bool operator==(const residue_iterator& rhs) const; // bool operator==(const residue_iterator& rhs) const;
bool operator!=(const residue_iterator& rhs) const; // bool operator!=(const residue_iterator& rhs) const;
private: // private:
const Structure& mStructure; // const Structure& mStructure;
poly_iterator mPolyIter; // poly_iterator mPolyIter;
size_t mPolyResIndex; // size_t mPolyResIndex;
size_t mNonPolyIndex; // size_t mNonPolyIndex;
}; // };
class residue_view // class residue_view
{ // {
public: // public:
residue_view(const Structure* s) : mStructure(s) {} // residue_view(const Structure* s) : mStructure(s) {}
residue_view(const residue_view& rhs) : mStructure(rhs.mStructure) {} // residue_view(const residue_view& rhs) : mStructure(rhs.mStructure) {}
residue_view& operator=(residue_view& rhs) // residue_view& operator=(residue_view& rhs)
{ // {
mStructure = rhs.mStructure; // mStructure = rhs.mStructure;
return *this; // return *this;
} // }
residue_iterator begin() const { return residue_iterator(mStructure, mStructure->mPolymers.begin(), 0, 0); } // 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()); } // residue_iterator end() const { return residue_iterator(mStructure, mStructure->mPolymers.end(), 0, mStructure->mNonPolymers.size()); }
size_t size() const // 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(); }); // 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(); // return ps + mStructure->mNonPolymers.size();
} // }
private: // private:
const Structure* mStructure; // const Structure* mStructure;
}; // };
residue_view residues() const { return residue_view(this); } // residue_view residues() const { return residue_view(this); }
private: private:
friend Polymer; friend Polymer;
friend Residue; friend Residue;
friend residue_view; // friend residue_view;
friend residue_iterator; // friend residue_iterator;
cif::Category& category(const char* name) const; cif::Category& category(const char* name) const;
cif::Datablock& datablock() const; cif::Datablock& datablock() const;
...@@ -560,7 +557,7 @@ class Structure ...@@ -560,7 +557,7 @@ class Structure
AtomView mAtoms; AtomView mAtoms;
std::vector<size_t> mAtomIndex; std::vector<size_t> mAtomIndex;
std::list<Polymer> mPolymers; std::list<Polymer> mPolymers;
std::vector<Residue> mNonPolymers; std::vector<Residue> mNonPolymers, mBranchResidues;
}; };
} }
...@@ -1732,6 +1732,17 @@ void Structure::loadData() ...@@ -1732,6 +1732,17 @@ void Structure::loadData()
else if (mNonPolymers.empty() or mNonPolymers.back().asymID() != asymID) else if (mNonPolymers.empty() or mNonPolymers.back().asymID() != asymID)
mNonPolymers.emplace_back(*this, monID, asymID); mNonPolymers.emplace_back(*this, monID, asymID);
} }
auto& branchScheme = category("pdbx_branch_scheme");
for (auto& r: branchScheme)
{
std::string asymID, monID, num;
cif::tie(asymID, monID, num) =
r.get("asym_id", "mon_id", "num");
mBranchResidues.emplace_back(*this, monID, asymID, num);
}
} }
void Structure::updateAtomIndex() void Structure::updateAtomIndex()
...@@ -2038,64 +2049,64 @@ void Structure::insertCompound(const std::string& compoundID, bool isEntity) ...@@ -2038,64 +2049,64 @@ void Structure::insertCompound(const std::string& compoundID, bool isEntity)
} }
} }
// -------------------------------------------------------------------- // // --------------------------------------------------------------------
Structure::residue_iterator::residue_iterator(const Structure* s, poly_iterator polyIter, size_t polyResIndex, size_t nonPolyIndex) // Structure::residue_iterator::residue_iterator(const Structure* s, poly_iterator polyIter, size_t polyResIndex, size_t nonPolyIndex)
: mStructure(*s), mPolyIter(polyIter), mPolyResIndex(polyResIndex), mNonPolyIndex(nonPolyIndex) // : mStructure(*s), mPolyIter(polyIter), mPolyResIndex(polyResIndex), mNonPolyIndex(nonPolyIndex)
{ // {
while (mPolyIter != mStructure.mPolymers.end() and mPolyResIndex == mPolyIter->size()) // while (mPolyIter != mStructure.mPolymers.end() and mPolyResIndex == mPolyIter->size())
++mPolyIter; // ++mPolyIter;
} // }
auto Structure::residue_iterator::operator*() -> reference // auto Structure::residue_iterator::operator*() -> reference
{ // {
if (mPolyIter != mStructure.mPolymers.end()) // if (mPolyIter != mStructure.mPolymers.end())
return (*mPolyIter)[mPolyResIndex]; // return (*mPolyIter)[mPolyResIndex];
else // else
return mStructure.mNonPolymers[mNonPolyIndex]; // return mStructure.mNonPolymers[mNonPolyIndex];
} // }
auto Structure::residue_iterator::operator->() -> pointer // auto Structure::residue_iterator::operator->() -> pointer
{ // {
if (mPolyIter != mStructure.mPolymers.end()) // if (mPolyIter != mStructure.mPolymers.end())
return &(*mPolyIter)[mPolyResIndex]; // return &(*mPolyIter)[mPolyResIndex];
else // else
return &mStructure.mNonPolymers[mNonPolyIndex]; // return &mStructure.mNonPolymers[mNonPolyIndex];
} // }
Structure::residue_iterator& Structure::residue_iterator::operator++() // Structure::residue_iterator& Structure::residue_iterator::operator++()
{ // {
if (mPolyIter != mStructure.mPolymers.end()) // if (mPolyIter != mStructure.mPolymers.end())
{ // {
++mPolyResIndex; // ++mPolyResIndex;
if (mPolyResIndex >= mPolyIter->size()) // if (mPolyResIndex >= mPolyIter->size())
{ // {
++mPolyIter; // ++mPolyIter;
mPolyResIndex = 0; // mPolyResIndex = 0;
} // }
} // }
else // else
++mNonPolyIndex; // ++mNonPolyIndex;
return *this; // return *this;
} // }
Structure::residue_iterator Structure::residue_iterator::operator++(int) // Structure::residue_iterator Structure::residue_iterator::operator++(int)
{ // {
auto result = *this; // auto result = *this;
operator++(); // operator++();
return result; // return result;
} // }
bool Structure::residue_iterator::operator==(const Structure::residue_iterator& rhs) const // bool Structure::residue_iterator::operator==(const Structure::residue_iterator& rhs) const
{ // {
return mPolyIter == rhs.mPolyIter and mPolyResIndex == rhs.mPolyResIndex and mNonPolyIndex == rhs.mNonPolyIndex; // return mPolyIter == rhs.mPolyIter and mPolyResIndex == rhs.mPolyResIndex and mNonPolyIndex == rhs.mNonPolyIndex;
} // }
bool Structure::residue_iterator::operator!=(const Structure::residue_iterator& rhs) const // bool Structure::residue_iterator::operator!=(const Structure::residue_iterator& rhs) const
{ // {
return mPolyIter != rhs.mPolyIter or mPolyResIndex != rhs.mPolyResIndex or mNonPolyIndex != rhs.mNonPolyIndex; // return mPolyIter != rhs.mPolyIter or mPolyResIndex != rhs.mPolyResIndex or mNonPolyIndex != rhs.mNonPolyIndex;
} // }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -1074,3 +1074,97 @@ _cat_2.parent_id3 ...@@ -1074,3 +1074,97 @@ _cat_2.parent_id3
BOOST_CHECK(cat1.size() == 0); BOOST_CHECK(cat1.size() == 0);
BOOST_CHECK(cat2.size() == 0); BOOST_CHECK(cat2.size() == 0);
} }
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(c1)
{
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();
for (auto r: db["test"].find(cif::Key("id") == 1))
{
const auto& [id, name] = r.get<int, std::string>({"id", "name"});
BOOST_CHECK(id == 1);
BOOST_CHECK(name == "aap");
}
for (auto r: db["test"].find(cif::Key("id") == 4))
{
const auto& [id, name] = r.get<int, std::string>({"id", "name"});
BOOST_CHECK(id == 4);
BOOST_CHECK(name.empty());
}
for (auto r: db["test"].find(cif::Key("id") == 5))
{
const auto& [id, name] = r.get<int, std::string>({"id", "name"});
BOOST_CHECK(id == 5);
BOOST_CHECK(name.empty());
}
// optional
for (auto r: db["test"])
{
const auto& [id, name] = r.get<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(c2)
{
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)
{
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);
}
}
}
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