Commit 4c99710f by Maarten L. Hekkelman

Refactored iterators (Category, Row)

const versions of find
parent 59865cdb
...@@ -680,7 +680,7 @@ class Row ...@@ -680,7 +680,7 @@ class Row
mCascade = cascade; mCascade = cascade;
} }
void next(); ///< make this row point to the next ItemRow void next() const;
struct const_iterator struct const_iterator
{ {
...@@ -805,7 +805,7 @@ class Row ...@@ -805,7 +805,7 @@ class Row
size_t ColumnForItemTag(const char *itemTag) const; size_t ColumnForItemTag(const char *itemTag) const;
ItemRow *mData; mutable ItemRow *mData;
uint32_t mLineNr = 0; uint32_t mLineNr = 0;
bool mCascade = true; bool mCascade = true;
}; };
...@@ -1338,7 +1338,7 @@ namespace literals ...@@ -1338,7 +1338,7 @@ namespace literals
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// iterators // iterators
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
class iterator_impl class iterator_impl
{ {
public: public:
...@@ -1347,8 +1347,10 @@ class iterator_impl ...@@ -1347,8 +1347,10 @@ class iterator_impl
static constexpr size_t N = sizeof...(Ts); static constexpr size_t N = sizeof...(Ts);
using row_type = std::conditional_t<std::is_const_v<CategoryType>, const Row, Row>;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
using value_type = std::conditional_t<N == 0, RowType, std::tuple<Ts...>>; using value_type = std::conditional_t<N == 0, row_type, std::tuple<Ts...>>;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using pointer = value_type *; using pointer = value_type *;
using reference = value_type &; using reference = value_type &;
...@@ -1424,7 +1426,7 @@ class iterator_impl ...@@ -1424,7 +1426,7 @@ class iterator_impl
return &mValue; return &mValue;
} }
RowType row() const row_type row() const
{ {
return mCurrent; return mCurrent;
} }
...@@ -1463,14 +1465,14 @@ class iterator_impl ...@@ -1463,14 +1465,14 @@ class iterator_impl
private: private:
template <std::size_t... Is> template <std::size_t... Is>
std::tuple<Ts...> get(Row row, std::index_sequence<Is...>) const std::tuple<Ts...> get(row_type row, std::index_sequence<Is...>) const
{ {
if (row) if (row)
return std::tuple<Ts...>{row[mCix[Is]].template as<Ts>()...}; return std::tuple<Ts...>{row[mCix[Is]].template as<Ts>()...};
return {}; return {};
} }
Row mCurrent; row_type mCurrent;
value_type mValue; value_type mValue;
std::array<size_t, N> mCix; std::array<size_t, N> mCix;
}; };
...@@ -1478,17 +1480,19 @@ class iterator_impl ...@@ -1478,17 +1480,19 @@ class iterator_impl
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// iterator proxy // iterator proxy
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
class iterator_proxy class iterator_proxy
{ {
public: public:
static constexpr const size_t N = sizeof...(Ts); static constexpr const size_t N = sizeof...(Ts);
using iterator = iterator_impl<RowType, Ts...>; using row_type = std::conditional_t<std::is_const_v<CategoryType>, const Row, Row>;
using row_iterator = iterator_impl<RowType>;
using iterator = iterator_impl<row_type, Ts...>;
using row_iterator = iterator_impl<row_type>;
iterator_proxy(Category &cat, row_iterator pos, char const *const columns[N]); iterator_proxy(CategoryType &cat, row_iterator pos, char const *const columns[N]);
iterator_proxy(Category &cat, row_iterator pos, std::initializer_list<char const *> columns); iterator_proxy(CategoryType &cat, row_iterator pos, std::initializer_list<char const *> columns);
iterator_proxy(iterator_proxy &&p); iterator_proxy(iterator_proxy &&p);
iterator_proxy &operator=(iterator_proxy &&p); iterator_proxy &operator=(iterator_proxy &&p);
...@@ -1505,10 +1509,10 @@ class iterator_proxy ...@@ -1505,10 +1509,10 @@ class iterator_proxy
size_t size() const { return std::distance(begin(), end()); } size_t size() const { return std::distance(begin(), end()); }
RowType front() { return *begin(); } row_type front() { return *begin(); }
RowType back() { return *(std::prev(end())); } row_type back() { return *(std::prev(end())); }
Category &category() const { return *mCat; } CategoryType &category() const { return *mCat; }
void swap(iterator_proxy &rhs) void swap(iterator_proxy &rhs)
{ {
...@@ -1519,7 +1523,7 @@ class iterator_proxy ...@@ -1519,7 +1523,7 @@ class iterator_proxy
} }
private: private:
Category *mCat; CategoryType *mCat;
row_iterator mCBegin, mCEnd; row_iterator mCBegin, mCEnd;
std::array<size_t, N> mCix; std::array<size_t, N> mCix;
}; };
...@@ -1527,16 +1531,15 @@ class iterator_proxy ...@@ -1527,16 +1531,15 @@ class iterator_proxy
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// conditional iterator proxy // conditional iterator proxy
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
class conditional_iterator_proxy class conditional_iterator_proxy
{ {
public: public:
static constexpr const size_t N = sizeof...(Ts); static constexpr const size_t N = sizeof...(Ts);
using base_iterator = iterator_impl<RowType, Ts...>; using base_iterator = iterator_impl<CategoryType, Ts...>;
using value_type = typename base_iterator::value_type; using value_type = typename base_iterator::value_type;
using row_type = typename base_iterator::row_type;
using row_type = std::remove_cv_t<RowType>;
using row_iterator = iterator_impl<row_type>; using row_iterator = iterator_impl<row_type>;
class conditional_iterator_impl class conditional_iterator_impl
...@@ -1548,7 +1551,7 @@ class conditional_iterator_proxy ...@@ -1548,7 +1551,7 @@ class conditional_iterator_proxy
using pointer = value_type *; using pointer = value_type *;
using reference = value_type &; using reference = value_type &;
conditional_iterator_impl(Category &cat, row_iterator pos, const Condition &cond, const std::array<size_t, N> &cix); conditional_iterator_impl(CategoryType &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(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;
...@@ -1595,7 +1598,7 @@ class conditional_iterator_proxy ...@@ -1595,7 +1598,7 @@ class conditional_iterator_proxy
bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin != rhs; } bool operator!=(const iterator_impl<IRowType, ITs...> &rhs) const { return mBegin != rhs; }
private: private:
Category *mCat; CategoryType *mCat;
base_iterator mBegin, mEnd; base_iterator mBegin, mEnd;
const Condition *mCondition; const Condition *mCondition;
}; };
...@@ -1603,10 +1606,8 @@ class conditional_iterator_proxy ...@@ -1603,10 +1606,8 @@ class conditional_iterator_proxy
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, row_iterator pos, Condition &&cond); template<typename... Ns>
conditional_iterator_proxy(CategoryType &cat, row_iterator pos, Condition &&cond, Ns... names);
template <std::size_t TN = N, std::enable_if_t<TN != 0, bool> = true>
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(conditional_iterator_proxy &&p);
conditional_iterator_proxy &operator=(conditional_iterator_proxy &&p); conditional_iterator_proxy &operator=(conditional_iterator_proxy &&p);
...@@ -1623,14 +1624,14 @@ class conditional_iterator_proxy ...@@ -1623,14 +1624,14 @@ class conditional_iterator_proxy
size_t size() const { return std::distance(begin(), end()); } size_t size() const { return std::distance(begin(), end()); }
RowType front() { return *begin(); } row_type front() { return *begin(); }
Category &category() const { return *mCat; } CategoryType &category() const { return *mCat; }
void swap(conditional_iterator_proxy &rhs); void swap(conditional_iterator_proxy &rhs);
private: private:
Category *mCat; CategoryType *mCat;
Condition mCondition; Condition mCondition;
row_iterator mCBegin, mCEnd; row_iterator mCBegin, mCEnd;
std::array<size_t, N> mCix; std::array<size_t, N> mCix;
...@@ -1843,43 +1844,68 @@ class Category ...@@ -1843,43 +1844,68 @@ class Category
Row back() { return Row(mTail); } Row back() { return Row(mTail); }
Row operator[](Condition &&cond); Row operator[](Condition &&cond);
const Row operator[](Condition &&cond) const;
template <typename... Ts, size_t N> template <typename... Ts, typename... Ns>
iterator_proxy<Row, Ts...> rows(char const *const (&columns)[N]) iterator_proxy<const Row, Ts...> rows(Ns... names) const
{ {
static_assert(sizeof...(Ts) == N, "The number of column titles should be equal to the number of types to return"); static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return iterator_proxy<Row, Ts...>(*this, begin(), columns); return iterator_proxy<const Row, Ts...>(*this, begin(), {names...});
} }
template <typename... Ts, typename... Ns> template <typename... Ts, typename... Ns>
iterator_proxy<Row, Ts...> rows(Ns... names) iterator_proxy<Category, Ts...> rows(Ns... names)
{ {
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return"); static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return iterator_proxy<Row, Ts...>(*this, begin(), {names...}); return iterator_proxy<Category, Ts...>(*this, begin(), {names...});
} }
conditional_iterator_proxy<Row> find(Condition &&cond) conditional_iterator_proxy<Category> find(Condition &&cond)
{ {
return find(cbegin(), std::forward<Condition>(cond)); return find(cbegin(), std::forward<Condition>(cond));
} }
conditional_iterator_proxy<Row> find(const_iterator pos, Condition &&cond) conditional_iterator_proxy<Category> 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> conditional_iterator_proxy<const Category> find(Condition &&cond) const
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 find(cbegin(), std::forward<Condition>(cond));
return find<Ts...>(cbegin(), std::forward<Condition>(cond), std::forward<char const *const[N]>(columns));
} }
template <typename... Ts, size_t N> conditional_iterator_proxy<const Category> find(const_iterator pos, Condition &&cond) const
conditional_iterator_proxy<Row, Ts...> find(const_iterator pos, Condition &&cond, char const *const (&columns)[N]) {
return conditional_iterator_proxy<const Category>{const_cast<Category&>(*this), pos, std::forward<Condition>(cond)};
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<Category, Ts...> find(Condition &&cond, Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return find<Ts...>(cbegin(), std::forward<Condition>(cond), std::forward<Ns>(names)...);
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<const Category, Ts...> find(Condition &&cond, Ns... names) const
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return find<Ts...>(cbegin(), std::forward<Condition>(cond), std::forward<Ns>(names)...);
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<Category, Ts...> find(const_iterator pos, Condition &&cond, Ns... names)
{
static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return {*this, pos, std::forward<Condition>(cond), std::forward<Ns>(names)... };
}
template <typename... Ts, typename... Ns>
conditional_iterator_proxy<const Category, Ts...> find(const_iterator pos, Condition &&cond, Ns... names) const
{ {
static_assert(sizeof...(Ts) == N, "The number of column titles should be equal to the number of types to return"); static_assert(sizeof...(Ts) == sizeof...(Ns), "The number of column titles should be equal to the number of types to return");
return {*this, pos, std::forward<Condition>(cond), columns}; return {*this, pos, std::forward<Condition>(cond), std::forward<Ns>(names)... };
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -1903,16 +1929,34 @@ class Category ...@@ -1903,16 +1929,34 @@ class Category
return *h.begin(); return *h.begin();
} }
const Row find1(Condition &&cond) const
{
return find1(cbegin(), std::forward<Condition>(cond));
}
const Row find1(const_iterator pos, Condition &&cond) const
{
auto h = find(pos, std::forward<Condition>(cond));
if (h.empty())
throw std::runtime_error("No hits found");
if (h.size() != 1)
throw std::runtime_error("Hit not unique");
return *h.begin();
}
template <typename T> template <typename T>
T find1(Condition &&cond, const char* column) T find1(Condition &&cond, const char* column) const
{ {
return find1<T>(cbegin(), std::forward<Condition>(cond), column); return find1<T>(cbegin(), std::forward<Condition>(cond), column);
} }
template <typename T> template <typename T>
T find1(const_iterator pos, Condition &&cond, const char* column) T find1(const_iterator pos, Condition &&cond, const char* column) const
{ {
auto h = find<T>(pos, std::forward<Condition>(cond), { column }); auto h = find<T>(pos, std::forward<Condition>(cond), column);
if (h.empty()) if (h.empty())
throw std::runtime_error("No hits found"); throw std::runtime_error("No hits found");
...@@ -1924,7 +1968,7 @@ class Category ...@@ -1924,7 +1968,7 @@ class Category
} }
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>> template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(Condition &&cond, Cs... columns) std::tuple<Ts...> find1(Condition &&cond, Cs... columns) const
{ {
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return"); static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
// static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char"); // static_assert(std::is_same_v<Cs, const char*>..., "The column names should be const char");
...@@ -1932,10 +1976,10 @@ class Category ...@@ -1932,10 +1976,10 @@ class Category
} }
template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>> template <typename... Ts, typename... Cs, typename U = std::enable_if_t<sizeof...(Ts) != 1>>
std::tuple<Ts...> find1(const_iterator pos, Condition &&cond, Cs... columns) std::tuple<Ts...> find1(const_iterator pos, Condition &&cond, Cs... columns) const
{ {
static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return"); static_assert(sizeof...(Ts) == sizeof...(Cs), "The number of column titles should be equal to the number of types to return");
auto h = find<Ts...>(pos, std::forward<Condition>(cond), { columns... }); auto h = find<Ts...>(pos, std::forward<Condition>(cond), std::forward<Cs>(columns)...);
if (h.empty()) if (h.empty())
throw std::runtime_error("No hits found"); throw std::runtime_error("No hits found");
...@@ -2253,8 +2297,8 @@ inline void swap(cif::detail::ItemReference &a, cif::detail::ItemReference &b) ...@@ -2253,8 +2297,8 @@ inline void swap(cif::detail::ItemReference &a, cif::detail::ItemReference &b)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
iterator_proxy<RowType, Ts...>::iterator_proxy(Category &cat, row_iterator pos, char const *const columns[N]) iterator_proxy<CategoryType, Ts...>::iterator_proxy(CategoryType &cat, row_iterator pos, char const *const columns[N])
: mCat(&cat) : mCat(&cat)
, mCBegin(pos) , mCBegin(pos)
, mCEnd(cat.end()) , mCEnd(cat.end())
...@@ -2263,8 +2307,8 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category &cat, row_iterator pos, ...@@ -2263,8 +2307,8 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category &cat, row_iterator pos,
mCix[i] = mCat->getColumnIndex(columns[i]); mCix[i] = mCat->getColumnIndex(columns[i]);
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
iterator_proxy<RowType, Ts...>::iterator_proxy(Category &cat, row_iterator pos, std::initializer_list<char const *> columns) iterator_proxy<CategoryType, Ts...>::iterator_proxy(CategoryType &cat, row_iterator pos, std::initializer_list<char const *> columns)
: mCat(&cat) : mCat(&cat)
, mCBegin(pos) , mCBegin(pos)
, mCEnd(cat.end()) , mCEnd(cat.end())
...@@ -2278,9 +2322,9 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category &cat, row_iterator pos, ...@@ -2278,9 +2322,9 @@ iterator_proxy<RowType, Ts...>::iterator_proxy(Category &cat, row_iterator pos,
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_impl::conditional_iterator_impl( conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_impl::conditional_iterator_impl(
Category &cat, row_iterator pos, const Condition &cond, const std::array<size_t, N> &cix) CategoryType &cat, row_iterator pos, const Condition &cond, const std::array<size_t, N> &cix)
: mCat(&cat) : mCat(&cat)
, mBegin(pos, cix) , mBegin(pos, cix)
, mEnd(cat.end(), cix) , mEnd(cat.end(), cix)
...@@ -2288,8 +2332,8 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_impl::condition ...@@ -2288,8 +2332,8 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_impl::condition
{ {
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(conditional_iterator_proxy &&p) conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_proxy(conditional_iterator_proxy &&p)
: mCat(nullptr) : mCat(nullptr)
, mCBegin(p.mCBegin) , mCBegin(p.mCBegin)
, mCEnd(p.mCEnd) , mCEnd(p.mCEnd)
...@@ -2300,63 +2344,54 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(condition ...@@ -2300,63 +2344,54 @@ conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(condition
mCondition.swap(p.mCondition); mCondition.swap(p.mCondition);
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...>::conditional_iterator_proxy(Category &cat, row_iterator pos, Condition &&cond) template <typename... Ns>
conditional_iterator_proxy<CategoryType, Ts...>::conditional_iterator_proxy(CategoryType &cat, row_iterator pos, Condition &&cond, Ns... names)
: mCat(&cat) : mCat(&cat)
, mCondition(std::move(cond)) , mCondition(std::move(cond))
, mCBegin(pos) , mCBegin(pos)
, mCEnd(cat.end()) , mCEnd(cat.end())
{ {
mCondition.prepare(cat); static_assert(sizeof...(Ts) == sizeof...(Ns), "Number of column names should be equal to number of requested value types");
while (mCBegin != mCEnd and not mCondition(*mCat, mCBegin.row())) size_t N = sizeof...(Ns);
++mCBegin;
}
template <typename RowType, typename... Ts>
template <std::size_t TN, std::enable_if_t<TN != 0, bool>>
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); mCondition.prepare(cat);
while (mCBegin != mCEnd and not mCondition(*mCat, mCBegin.row())) while (mCBegin != mCEnd and not mCondition(*mCat, mCBegin.row()))
++mCBegin; ++mCBegin;
for (size_t i = 0; i < N; ++i) size_t i = 0;
mCix[i] = mCat->getColumnIndex(columns[i]); ((mCix[i++] = mCat->getColumnIndex(names)), ...);
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
conditional_iterator_proxy<RowType, Ts...> &conditional_iterator_proxy<RowType, Ts...>::operator=(conditional_iterator_proxy &&p) conditional_iterator_proxy<CategoryType, Ts...> &conditional_iterator_proxy<CategoryType, Ts...>::operator=(conditional_iterator_proxy &&p)
{ {
swap(p); swap(p);
return *this; return *this;
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
typename conditional_iterator_proxy<RowType, Ts...>::iterator conditional_iterator_proxy<RowType, Ts...>::begin() const typename conditional_iterator_proxy<CategoryType, Ts...>::iterator conditional_iterator_proxy<CategoryType, Ts...>::begin() const
{ {
return iterator(*mCat, mCBegin, mCondition, mCix); return iterator(*mCat, mCBegin, mCondition, mCix);
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
typename conditional_iterator_proxy<RowType, Ts...>::iterator conditional_iterator_proxy<RowType, Ts...>::end() const typename conditional_iterator_proxy<CategoryType, Ts...>::iterator conditional_iterator_proxy<CategoryType, Ts...>::end() const
{ {
return iterator(*mCat, mCEnd, mCondition, mCix); return iterator(*mCat, mCEnd, mCondition, mCix);
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
bool conditional_iterator_proxy<RowType, Ts...>::empty() const bool conditional_iterator_proxy<CategoryType, Ts...>::empty() const
{ {
return mCBegin == mCEnd; return mCBegin == mCEnd;
} }
template <typename RowType, typename... Ts> template <typename CategoryType, typename... Ts>
void conditional_iterator_proxy<RowType, Ts...>::swap(conditional_iterator_proxy &rhs) void conditional_iterator_proxy<CategoryType, Ts...>::swap(conditional_iterator_proxy &rhs)
{ {
std::swap(mCat, rhs.mCat); std::swap(mCat, rhs.mCat);
mCondition.swap(rhs.mCondition); mCondition.swap(rhs.mCondition);
......
...@@ -61,11 +61,12 @@ class File; ...@@ -61,11 +61,12 @@ class File;
class Atom class Atom
{ {
public: public:
// Atom(const structure& s, const std::string& id);
Atom(); Atom();
Atom(struct AtomImpl *impl); Atom(struct AtomImpl *impl);
Atom(const Atom &rhs); Atom(const Atom &rhs);
Atom(cif::Datablock &db, cif::Row &row);
// a special constructor to create symmetry copies // a special constructor to create symmetry copies
Atom(const Atom &rhs, const Point &symmmetry_location, const std::string &symmetry_operation); Atom(const Atom &rhs, const Point &symmmetry_location, const std::string &symmetry_operation);
...@@ -495,13 +496,13 @@ class Structure ...@@ -495,13 +496,13 @@ class Structure
/// \return The ID of the created entity /// \return The ID of the created entity
std::string createNonPolyEntity(const std::string &mon_id); std::string createNonPolyEntity(const std::string &mon_id);
/// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atom_data, returns asym_id. /// \brief Create a new NonPolymer struct_asym with atoms constructed from \a atoms, returns asym_id.
/// This method assumes you are copying data from one cif file to another. /// This method assumes you are copying data from one cif file to another.
/// ///
/// \param entity_id The entity ID of the new nonpoly /// \param entity_id The entity ID of the new nonpoly
/// \param atoms The array of atom_site rows containing the data. /// \param atoms The array of atom_site rows containing the data.
/// \return The newly create asym ID /// \return The newly create asym ID
std::string createNonpoly(const std::string &entity_id, const std::vector<cif::Row> &atoms); std::string createNonpoly(const std::string &entity_id, const std::vector<mmcif::Atom> &atoms);
/// \brief To sort the atoms in order of model > asym-id > res-id > atom-id /// \brief To sort the atoms in order of model > asym-id > res-id > atom-id
/// Will asssign new atom_id's to all atoms. Be carefull /// Will asssign new atom_id's to all atoms. Be carefull
......
...@@ -2821,7 +2821,7 @@ Row::~Row() ...@@ -2821,7 +2821,7 @@ Row::~Row()
{ {
} }
void Row::next() void Row::next() const
{ {
if (mData != nullptr) if (mData != nullptr)
mData = mData->mNext; mData = mData->mNext;
...@@ -3263,7 +3263,7 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b) ...@@ -3263,7 +3263,7 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b)
} }
} }
std::vector<conditional_iterator_proxy<Row>> rs; std::vector<conditional_iterator_proxy<Category>> rs;
// first find the respective rows, then flip values, otherwise you won't find them anymore! // first find the respective rows, then flip values, otherwise you won't find them anymore!
for (size_t ab = 0; ab < 2; ++ab) for (size_t ab = 0; ab < 2; ++ab)
......
...@@ -368,7 +368,7 @@ CompoundFactoryImpl::CompoundFactoryImpl(const std::string &file, std::shared_pt ...@@ -368,7 +368,7 @@ CompoundFactoryImpl::CompoundFactoryImpl(const std::string &file, std::shared_pt
{ {
auto &chemComp = (*compList)["chem_comp"]; auto &chemComp = (*compList)["chem_comp"];
for (const auto &[id, name, group] : chemComp.rows<std::string, std::string, std::string>({"id", "name", "group"})) for (const auto &[id, name, group] : chemComp.rows<std::string, std::string, std::string>("id", "name", "group"))
{ {
std::string type; std::string type;
......
...@@ -230,7 +230,7 @@ void FileImpl::save(const std::string &p) ...@@ -230,7 +230,7 @@ void FileImpl::save(const std::string &p)
struct AtomImpl struct AtomImpl
{ {
AtomImpl(const AtomImpl &i) AtomImpl(const AtomImpl &i)
: mFile(i.mFile) : mDb(i.mDb)
, mID(i.mID) , mID(i.mID)
, mType(i.mType) , mType(i.mType)
, mAtomID(i.mAtomID) , mAtomID(i.mAtomID)
...@@ -250,13 +250,12 @@ struct AtomImpl ...@@ -250,13 +250,12 @@ struct AtomImpl
{ {
} }
AtomImpl(const File &f, const std::string &id) AtomImpl(cif::Datablock &db, const std::string &id)
: mFile(f) : mDb(db)
, mID(id) , mID(id)
, mRefcount(1) , mRefcount(1)
, mCompound(nullptr) , mCompound(nullptr)
{ {
auto &db = *mFile.impl().mDb;
auto &cat = db["atom_site"]; auto &cat = db["atom_site"];
mRow = cat[cif::Key("id") == mID]; mRow = cat[cif::Key("id") == mID];
...@@ -264,8 +263,18 @@ struct AtomImpl ...@@ -264,8 +263,18 @@ struct AtomImpl
prefetch(); prefetch();
} }
AtomImpl(const File &f, const std::string &id, cif::Row row) AtomImpl(cif::Datablock &db, cif::Row &row)
: mFile(f) : mDb(db)
, mID(row["id"].as<std::string>())
, mRow(row)
, mRefcount(1)
, mCompound(nullptr)
{
prefetch();
}
AtomImpl(cif::Datablock &db, const std::string &id, cif::Row row)
: mDb(db)
, mID(id) , mID(id)
, mRefcount(1) , mRefcount(1)
, mRow(row) , mRow(row)
...@@ -274,21 +283,8 @@ struct AtomImpl ...@@ -274,21 +283,8 @@ struct AtomImpl
prefetch(); prefetch();
} }
// AtomImpl(const AtomImpl& impl, const Point& d, const clipper::RTop_orth& rt)
// : mFile(impl.mFile), mID(impl.mID), mType(impl.mType), mAtomID(impl.mAtomID)
// , mCompID(impl.mCompID), mAsymID(impl.mAsymID), mSeqID(impl.mSeqID)
// , mAltID(impl.mAltID), mLocation(impl.mLocation), mRefcount(1)
// , mRow(impl.mRow), mCompound(impl.mCompound), mRadius(impl.mRadius)
// , mCachedProperties(impl.mCachedProperties)
// , mSymmetryCopy(true), mRTop(rt), mD(d)
// {
// mLocation += d;
// mLocation = ((clipper::Coord_orth)mLocation).transform(rt);
// mLocation -= d;
// }
AtomImpl(const AtomImpl &impl, const Point &loc, const std::string &sym_op) AtomImpl(const AtomImpl &impl, const Point &loc, const std::string &sym_op)
: mFile(impl.mFile) : mDb(impl.mDb)
, mID(impl.mID) , mID(impl.mID)
, mType(impl.mType) , mType(impl.mType)
, mAtomID(impl.mAtomID) , mAtomID(impl.mAtomID)
...@@ -341,16 +337,19 @@ struct AtomImpl ...@@ -341,16 +337,19 @@ struct AtomImpl
bool getAnisoU(float anisou[6]) const bool getAnisoU(float anisou[6]) const
{ {
auto &db = *mFile.impl().mDb;
auto &cat = db["atom_site_anisotrop"];
auto r = cat[cif::Key("id") == mID];
bool result = false; bool result = false;
if (not r.empty()) auto cat = mDb.get("atom_site_anisotrop");
if (cat)
{ {
result = true; auto r = cat->find1(cif::Key("id") == mID);
cif::tie(anisou[0], anisou[1], anisou[2], anisou[3], anisou[4], anisou[5]) =
r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]"); if (not r.empty())
{
result = true;
cif::tie(anisou[0], anisou[1], anisou[2], anisou[3], anisou[4], anisou[5]) =
r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]");
}
} }
return result; return result;
...@@ -445,7 +444,7 @@ struct AtomImpl ...@@ -445,7 +444,7 @@ struct AtomImpl
std::swap(mAtomID, b.mAtomID); std::swap(mAtomID, b.mAtomID);
} }
const File &mFile; const cif::Datablock &mDb;
std::string mID; std::string mID;
AtomType mType; AtomType mType;
...@@ -487,6 +486,11 @@ Atom::Atom(AtomImpl *impl) ...@@ -487,6 +486,11 @@ Atom::Atom(AtomImpl *impl)
{ {
} }
Atom::Atom(cif::Datablock &db, cif::Row &row)
: mImpl_(new AtomImpl(db, row))
{
}
AtomImpl *Atom::impl() AtomImpl *Atom::impl()
{ {
if (mImpl_ == nullptr) if (mImpl_ == nullptr)
...@@ -545,9 +549,12 @@ const cif::Row Atom::getRow() const ...@@ -545,9 +549,12 @@ const cif::Row Atom::getRow() const
const cif::Row Atom::getRowAniso() const const cif::Row Atom::getRowAniso() const
{ {
auto &db = *mImpl_->mFile.impl().mDb; auto &db = mImpl_->mDb;
auto &cat = db["atom_site_anisotrop"]; auto cat = db.get("atom_site_anisotrop");
return cat[cif::Key("id") == mImpl_->mID]; if (not cat)
return {};
else
return cat->find1(cif::Key("id") == mImpl_->mID);
} }
template <> template <>
...@@ -758,7 +765,7 @@ bool Atom::isWater() const ...@@ -758,7 +765,7 @@ bool Atom::isWater() const
bool Atom::operator==(const Atom &rhs) const bool Atom::operator==(const Atom &rhs) const
{ {
return impl() == rhs.impl() or return impl() == rhs.impl() or
(&impl()->mFile == &rhs.impl()->mFile and impl()->mID == rhs.impl()->mID); (&impl()->mDb == &rhs.impl()->mDb and impl()->mID == rhs.impl()->mID);
} }
// clipper::Atom Atom::toClipper() const // clipper::Atom Atom::toClipper() const
...@@ -1821,7 +1828,7 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options) ...@@ -1821,7 +1828,7 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
if ((options bitand StructureOpenOptions::SkipHydrogen) and type_symbol == "H") if ((options bitand StructureOpenOptions::SkipHydrogen) and type_symbol == "H")
continue; continue;
mAtoms.emplace_back(new AtomImpl(f, id, a)); mAtoms.emplace_back(new AtomImpl(*db, id, a));
} }
loadData(); loadData();
...@@ -2445,7 +2452,7 @@ std::string Structure::createNonPolyEntity(const std::string &comp_id) ...@@ -2445,7 +2452,7 @@ std::string Structure::createNonPolyEntity(const std::string &comp_id)
return insertCompound(comp_id, true); return insertCompound(comp_id, true);
} }
std::string Structure::createNonpoly(const std::string &entity_id, const std::vector<cif::Row> &atoms) std::string Structure::createNonpoly(const std::string &entity_id, const std::vector<mmcif::Atom> &atoms)
{ {
using namespace cif::literals; using namespace cif::literals;
...@@ -2468,26 +2475,26 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve ...@@ -2468,26 +2475,26 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve
for (auto& atom: atoms) for (auto& atom: atoms)
{ {
atom_site.emplace({ atom_site.emplace({
{ "group_PDB", atom["group_PDB"].as<std::string>() }, { "group_PDB", atom.property<std::string>("group_PDB") },
{ "id", atom_site.getUniqueID("") }, { "id", atom_site.getUniqueID("") },
{ "type_symbol", atom["type_symbol"].as<std::string>() }, { "type_symbol", atom.property<std::string>("type_symbol") },
{ "label_atom_id", atom["label_atom_id"].as<std::string>() }, { "label_atom_id", atom.property<std::string>("label_atom_id") },
{ "label_alt_id", atom["label_alt_id"].as<std::string>() }, { "label_alt_id", atom.property<std::string>("label_alt_id") },
{ "label_comp_id", comp_id }, { "label_comp_id", comp_id },
{ "label_asym_id", asym_id }, { "label_asym_id", asym_id },
{ "label_entity_id", entity_id }, { "label_entity_id", entity_id },
{ "label_seq_id", "." }, { "label_seq_id", "." },
{ "pdbx_PDB_ins_code", "" }, { "pdbx_PDB_ins_code", "" },
{ "Cartn_x", atom["Cartn_x"].as<std::string>() }, { "Cartn_x", atom.property<std::string>("Cartn_x") },
{ "Cartn_y", atom["Cartn_y"].as<std::string>() }, { "Cartn_y", atom.property<std::string>("Cartn_y") },
{ "Cartn_z", atom["Cartn_z"].as<std::string>() }, { "Cartn_z", atom.property<std::string>("Cartn_z") },
{ "occupancy", atom["occupancy"].as<std::string>() }, { "occupancy", atom.property<std::string>("occupancy") },
{ "B_iso_or_equiv", atom["B_iso_or_equiv"].as<std::string>() }, { "B_iso_or_equiv", atom.property<std::string>("B_iso_or_equiv") },
{ "pdbx_formal_charge", atom["pdbx_formal_charge"].as<std::string>() }, { "pdbx_formal_charge", atom.property<std::string>("pdbx_formal_charge") },
{ "auth_seq_id", "" }, { "auth_seq_id", "" },
{ "auth_comp_id", comp_id }, { "auth_comp_id", comp_id },
{ "auth_asym_id", asym_id }, { "auth_asym_id", asym_id },
{ "auth_atom_id", atom["label_atom_id"].as<std::string>() }, { "auth_atom_id", atom.property<std::string>("label_atom_id") },
{ "pdbx_PDB_model_num", 1 } { "pdbx_PDB_model_num", 1 }
}); });
} }
...@@ -2568,7 +2575,7 @@ void Structure::cleanupEmptyCategories() ...@@ -2568,7 +2575,7 @@ void Structure::cleanupEmptyCategories()
{ {
// is this correct? // is this correct?
std::set<std::string> asym_ids; std::set<std::string> asym_ids;
for (const auto &[asym_id] : db["pdbx_branch_scheme"].find<std::string>("entity_id"_key == id, {"asym_id"})) for (const auto &[ asym_id ] : db["pdbx_branch_scheme"].find<std::string>("entity_id"_key == id, "asym_id"))
asym_ids.insert(asym_id); asym_ids.insert(asym_id);
count = asym_ids.size(); count = asym_ids.size();
} }
......
...@@ -86,10 +86,13 @@ HETATM C CHD . ? -4.342 36.262 -3.536 1.00 8.00 ? ...@@ -86,10 +86,13 @@ HETATM C CHD . ? -4.342 36.262 -3.536 1.00 8.00 ?
# that's enough to test with # that's enough to test with
)"_cf; )"_cf;
auto &atom_site = atoms["HEM"]["atom_site"]; auto &hem_data = atoms["HEM"];
auto &atom_site = hem_data["atom_site"];
auto hem_atoms = atom_site.rows(); auto hem_atoms = atom_site.rows();
std::vector<cif::Row> atom_data(hem_atoms.begin(), hem_atoms.end()); std::vector<mmcif::Atom> atom_data;
for (auto &hem_atom: hem_atoms)
atom_data.emplace_back(hem_data, hem_atom);
structure.createNonpoly(entity_id, atom_data); structure.createNonpoly(entity_id, atom_data);
......
...@@ -1158,7 +1158,7 @@ _test.name ...@@ -1158,7 +1158,7 @@ _test.name
// query tests // query tests
for (const auto& [id, name]: db["test"].rows<int, std::optional<std::string>>({ "id", "name" })) for (const auto& [id, name]: db["test"].rows<int, std::optional<std::string>>("id", "name"))
{ {
switch (id) switch (id)
{ {
...@@ -1193,7 +1193,7 @@ _test.name ...@@ -1193,7 +1193,7 @@ _test.name
auto& db = f.firstDatablock(); auto& db = f.firstDatablock();
// query tests // query tests
for (const auto& [id, name]: db["test"].find<int, std::optional<std::string>>(cif::All(), { "id", "name" })) for (const auto& [id, name]: db["test"].find<int, std::optional<std::string>>(cif::All(), "id", "name"))
{ {
switch (id) switch (id)
{ {
...@@ -1441,7 +1441,7 @@ _cat_3.num ...@@ -1441,7 +1441,7 @@ _cat_3.num
} }
int i = 0; int i = 0;
for (const auto &[id, name, num, desc]: cat2.rows<int,std::string,int,std::string>({"id", "name", "num", "desc"})) for (const auto &[id, name, num, desc]: cat2.rows<int,std::string,int,std::string>("id", "name", "num", "desc"))
{ {
switch (++i) switch (++i)
{ {
...@@ -1473,7 +1473,7 @@ _cat_3.num ...@@ -1473,7 +1473,7 @@ _cat_3.num
BOOST_CHECK(cat1.size() == 4); BOOST_CHECK(cat1.size() == 4);
i = 0; i = 0;
for (const auto &[id, name, desc]: cat1.rows<int,std::string,std::string>({"id", "name", "desc"})) for (const auto &[id, name, desc]: cat1.rows<int,std::string,std::string>("id", "name", "desc"))
{ {
switch (++i) switch (++i)
{ {
...@@ -1627,7 +1627,7 @@ PRO OXT HXT SING N N 17 ...@@ -1627,7 +1627,7 @@ PRO OXT HXT SING N N 17
std::set<std::tuple<std::string,std::string>> bonded; std::set<std::tuple<std::string,std::string>> bonded;
for (const auto& [atom_id_1, atom_id_2]: cc->rows<std::string,std::string>({ "atom_id_1", "atom_id_2" })) for (const auto& [atom_id_1, atom_id_2]: cc->rows<std::string,std::string>("atom_id_1", "atom_id_2"))
{ {
if (atom_id_1 > atom_id_2) if (atom_id_1 > atom_id_2)
bonded.insert({ atom_id_2, atom_id_1 }); bonded.insert({ atom_id_2, atom_id_1 });
......
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