mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-06 15:28:04 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05cfa92182 | ||
|
|
e8031aeb49 | ||
|
|
19706559cb | ||
|
|
0a06a0a51d | ||
|
|
d3432ed87c | ||
|
|
72fd03a6b2 | ||
|
|
61f464ae4d | ||
|
|
19cdf66f10 | ||
|
|
0c036df6a8 | ||
|
|
4c1b9d83d1 | ||
|
|
b976b4657b | ||
|
|
eba04950d5 | ||
|
|
0c70df27ec | ||
|
|
d83f34722b | ||
|
|
652b6021d3 | ||
|
|
7fe9c87b6e | ||
|
|
9b2ae6d7fd | ||
|
|
8fd5b9a34b | ||
|
|
dffbf52d04 |
@@ -25,7 +25,7 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# set the project name
|
||||
project(cifpp VERSION 5.0.5 LANGUAGES CXX)
|
||||
project(cifpp VERSION 5.0.6 LANGUAGES CXX)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Version 5.0.6
|
||||
- Fix file::contains, using iequals
|
||||
- Fix is_cis
|
||||
|
||||
Version 5.0.5
|
||||
- Fix code to work on 32 bit machines
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ namespace detail
|
||||
virtual bool test(row_handle) const = 0;
|
||||
virtual void str(std::ostream &) const = 0;
|
||||
virtual std::optional<row_handle> single() const { return {}; };
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const { return false; }
|
||||
};
|
||||
|
||||
struct all_condition_impl : public condition_impl
|
||||
@@ -145,7 +147,6 @@ class condition
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void optimise(condition_impl *&impl);
|
||||
|
||||
condition_impl *m_impl;
|
||||
@@ -193,9 +194,7 @@ namespace detail
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return m_single_hit.has_value() ?
|
||||
*m_single_hit == r :
|
||||
r[m_item_ix].compare(m_value, m_icase) == 0;
|
||||
return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value, m_icase) == 0;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
@@ -208,6 +207,20 @@ namespace detail
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_condition_impl *>(rhs);
|
||||
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
|
||||
return m_single_hit == ri->m_single_hit;
|
||||
else
|
||||
// watch out, both m_item_ix might be the same while tags might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_tag == ri->m_item_tag;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_tag;
|
||||
uint16_t m_item_ix = 0;
|
||||
bool m_icase = false;
|
||||
@@ -244,7 +257,7 @@ namespace detail
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL";
|
||||
os << '(' << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL)";
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
@@ -252,12 +265,26 @@ namespace detail
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_or_empty_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_or_empty_condition_impl *>(rhs);
|
||||
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
|
||||
return m_single_hit == ri->m_single_hit;
|
||||
else
|
||||
// watch out, both m_item_ix might be the same while tags might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_tag == ri->m_item_tag;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_tag;
|
||||
uint16_t m_item_ix = 0;
|
||||
std::string m_value;
|
||||
bool m_icase = false;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
};
|
||||
|
||||
struct key_compare_condition_impl : public condition_impl
|
||||
{
|
||||
@@ -409,29 +436,53 @@ namespace detail
|
||||
// case they make up an indexed tuple.
|
||||
struct and_condition_impl : public condition_impl
|
||||
{
|
||||
and_condition_impl() = default;
|
||||
|
||||
and_condition_impl(condition &&a, condition &&b)
|
||||
{
|
||||
mSub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
mSub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
if (typeid(*a.m_impl) == typeid(*this))
|
||||
{
|
||||
and_condition_impl *ai = static_cast<and_condition_impl *>(a.m_impl);
|
||||
|
||||
std::swap(m_sub, ai->m_sub);
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(*this))
|
||||
{
|
||||
and_condition_impl *bi = static_cast<and_condition_impl *>(b.m_impl);
|
||||
|
||||
std::swap(m_sub, bi->m_sub);
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
~and_condition_impl()
|
||||
{
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
delete sub;
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
condition_impl *prepare(const category &c) override
|
||||
{
|
||||
for (auto &sub : m_sub)
|
||||
sub = sub->prepare(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (sub->test(r))
|
||||
continue;
|
||||
|
||||
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
@@ -444,7 +495,7 @@ namespace detail
|
||||
os << '(';
|
||||
|
||||
bool first = true;
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
@@ -461,7 +512,7 @@ namespace detail
|
||||
{
|
||||
std::optional<row_handle> result;
|
||||
|
||||
for (auto sub : mSub)
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
auto s = sub->single();
|
||||
|
||||
@@ -470,7 +521,7 @@ namespace detail
|
||||
result = s;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (s == result)
|
||||
continue;
|
||||
|
||||
@@ -481,56 +532,100 @@ namespace detail
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<condition_impl *> mSub;
|
||||
static condition_impl *combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc);
|
||||
|
||||
std::vector<condition_impl *> m_sub;
|
||||
};
|
||||
|
||||
struct or_condition_impl : public condition_impl
|
||||
{
|
||||
or_condition_impl(condition &&a, condition &&b)
|
||||
: mA(nullptr)
|
||||
, mB(nullptr)
|
||||
{
|
||||
std::swap(mA, a.m_impl);
|
||||
std::swap(mB, b.m_impl);
|
||||
if (typeid(*a.m_impl) == typeid(*this))
|
||||
{
|
||||
or_condition_impl *ai = static_cast<or_condition_impl *>(a.m_impl);
|
||||
|
||||
std::swap(m_sub, ai->m_sub);
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(*this))
|
||||
{
|
||||
or_condition_impl *bi = static_cast<or_condition_impl *>(b.m_impl);
|
||||
|
||||
std::swap(m_sub, bi->m_sub);
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
|
||||
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
~or_condition_impl()
|
||||
{
|
||||
delete mA;
|
||||
delete mB;
|
||||
for (auto sub : m_sub)
|
||||
delete sub;
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return mA->test(r) or mB->test(r);
|
||||
bool result = false;
|
||||
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (not sub->test(r))
|
||||
continue;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
os << '(';
|
||||
mA->str(os);
|
||||
os << ") OR (";
|
||||
mB->str(os);
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
os << " OR ";
|
||||
sub->str(os);
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
auto sa = mA->single();
|
||||
auto sb = mB->single();
|
||||
|
||||
if (sa.has_value() and sb.has_value() and sa != sb)
|
||||
sa.reset();
|
||||
else if (not sa.has_value())
|
||||
sa = sb;
|
||||
std::optional<row_handle> result;
|
||||
|
||||
return sa;
|
||||
for (auto sub : m_sub)
|
||||
{
|
||||
auto s = sub->single();
|
||||
|
||||
if (not result.has_value())
|
||||
{
|
||||
result = s;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s == result)
|
||||
continue;
|
||||
|
||||
result.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
condition_impl *mA;
|
||||
condition_impl *mB;
|
||||
std::vector<condition_impl *> m_sub;
|
||||
};
|
||||
|
||||
struct not_condition_impl : public condition_impl
|
||||
@@ -569,7 +664,7 @@ namespace detail
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline condition operator&&(condition &&a, condition &&b)
|
||||
inline condition operator and(condition &&a, condition &&b)
|
||||
{
|
||||
if (a.m_impl and b.m_impl)
|
||||
return condition(new detail::and_condition_impl(std::move(a), std::move(b)));
|
||||
@@ -578,12 +673,35 @@ inline condition operator&&(condition &&a, condition &&b)
|
||||
return condition(std::move(b));
|
||||
}
|
||||
|
||||
inline condition operator||(condition &&a, condition &&b)
|
||||
inline condition operator or(condition &&a, condition &&b)
|
||||
{
|
||||
if (a.m_impl and b.m_impl)
|
||||
{
|
||||
if (typeid(*a.m_impl) == typeid(detail::key_equals_condition_impl) and
|
||||
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_condition_impl *>(a.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
|
||||
|
||||
if (ci->m_item_tag == ce->m_item_tag)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(detail::key_equals_condition_impl) and
|
||||
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_condition_impl *>(b.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
|
||||
|
||||
if (ci->m_item_tag == ce->m_item_tag)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
|
||||
}
|
||||
|
||||
if (a.m_impl)
|
||||
return condition(std::move(a));
|
||||
|
||||
return condition(std::move(b));
|
||||
}
|
||||
|
||||
@@ -706,7 +824,7 @@ inline condition operator==(const key &key, const empty_type &)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_tag));
|
||||
}
|
||||
|
||||
inline condition operator !(condition &&rhs)
|
||||
inline condition operator not(condition &&rhs)
|
||||
{
|
||||
return condition(new detail::not_condition_impl(std::move(rhs)));
|
||||
}
|
||||
@@ -741,4 +859,4 @@ namespace literals
|
||||
}
|
||||
} // namespace literals
|
||||
|
||||
} // namespace cif
|
||||
} // namespace cif
|
||||
|
||||
@@ -259,8 +259,6 @@ struct item_value
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(item_value) == sizeof(void*) + 8, "sizeof(item_value) should be correct");
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Transient object to access stored data
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class atom
|
||||
private:
|
||||
struct atom_impl : public std::enable_shared_from_this<atom_impl>
|
||||
{
|
||||
atom_impl(datablock &db, std::string_view id)
|
||||
atom_impl(const datablock &db, std::string_view id)
|
||||
: m_db(db)
|
||||
, m_cat(db["atom_site"])
|
||||
, m_id(id)
|
||||
@@ -111,7 +111,7 @@ class atom
|
||||
}
|
||||
|
||||
const datablock &m_db;
|
||||
category &m_cat;
|
||||
const category &m_cat;
|
||||
std::string m_id;
|
||||
point m_location;
|
||||
std::string m_symop = "1_555";
|
||||
@@ -130,7 +130,7 @@ class atom
|
||||
{
|
||||
}
|
||||
|
||||
atom(datablock &db, row_handle &row)
|
||||
atom(const datablock &db, const row_handle &row)
|
||||
: atom(std::make_shared<atom_impl>(db, row["id"].as<std::string>()))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <regex>
|
||||
|
||||
#include <cif++/row.hpp>
|
||||
|
||||
@@ -93,23 +94,23 @@ class sac_parser
|
||||
|
||||
static bool is_unquoted_string(std::string_view text)
|
||||
{
|
||||
auto s = text.begin();
|
||||
bool result = is_ordinary(text.front());
|
||||
|
||||
bool result = is_ordinary(*s++);
|
||||
while (result and s != text.end())
|
||||
{
|
||||
result = is_non_blank(*s);
|
||||
++s;
|
||||
}
|
||||
|
||||
// but be careful it does not contain e.g. stop_
|
||||
if (result)
|
||||
{
|
||||
static const std::regex reservedRx(R"((^(?:data|save)|.*(?:loop|stop|global))_.+)", std::regex_constants::icase);
|
||||
result = not std::regex_match(text.begin(), text.end(), reservedRx);
|
||||
for (auto ch : text)
|
||||
{
|
||||
if (is_non_blank(ch))
|
||||
continue;
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
static const std::regex kReservedRx(R"(loop_|stop_|global_|data_\S+|save_\S+)", std::regex_constants::icase);
|
||||
|
||||
// but be careful it does not contain e.g. stop_
|
||||
return result and not std::regex_match(text.begin(), text.end(), kReservedRx);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1142,10 +1142,6 @@ category::iterator category::erase(iterator pos)
|
||||
row *r = rh.get_row();
|
||||
iterator result = ++pos;
|
||||
|
||||
iset keys;
|
||||
if (m_cat_validator)
|
||||
keys = iset(m_cat_validator->m_keys.begin(), m_cat_validator->m_keys.end());
|
||||
|
||||
if (m_head == nullptr)
|
||||
throw std::runtime_error("erase");
|
||||
|
||||
@@ -1174,7 +1170,7 @@ category::iterator category::erase(iterator pos)
|
||||
// in mmcif_pdbx.dic dictionary.
|
||||
//
|
||||
// For each link group in _pdbx_item_linked_group_list
|
||||
// a std::set of keys from one category is mapped to another.
|
||||
// a set of keys from one category is mapped to another.
|
||||
// If all values in a child are the same as the specified parent ones
|
||||
// the child is removed as well, recursively of course.
|
||||
|
||||
@@ -1198,25 +1194,29 @@ category::iterator category::erase(iterator pos)
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t category::erase(condition &&cond)
|
||||
template<typename T>
|
||||
class save_value
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
cond.prepare(*this);
|
||||
|
||||
auto ri = begin();
|
||||
while (ri != end())
|
||||
public:
|
||||
save_value(T &v, const T nv = {})
|
||||
: m_v(v)
|
||||
, m_sv(std::exchange(m_v, nv))
|
||||
{
|
||||
if (cond(*ri))
|
||||
{
|
||||
ri = erase(ri);
|
||||
++result;
|
||||
}
|
||||
else
|
||||
++ri;
|
||||
}
|
||||
|
||||
return result;
|
||||
~save_value()
|
||||
{
|
||||
m_v = m_sv;
|
||||
}
|
||||
|
||||
private:
|
||||
T &m_v;
|
||||
const T m_sv;
|
||||
};
|
||||
|
||||
size_t category::erase(condition &&cond)
|
||||
{
|
||||
return erase(std::move(cond), {});
|
||||
}
|
||||
|
||||
size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
|
||||
@@ -1225,12 +1225,26 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit
|
||||
|
||||
cond.prepare(*this);
|
||||
|
||||
std::map<category *, condition> potential_orphans;
|
||||
|
||||
auto ri = begin();
|
||||
while (ri != end())
|
||||
{
|
||||
if (cond(*ri))
|
||||
{
|
||||
visit(*ri);
|
||||
if (visit)
|
||||
visit(*ri);
|
||||
|
||||
for (auto &&[childCat, link] : m_child_links)
|
||||
{
|
||||
auto cond = get_children_condition(*ri, *childCat);
|
||||
if (not cond)
|
||||
continue;
|
||||
potential_orphans[childCat] = std::move(potential_orphans[childCat]) or std::move(cond);
|
||||
}
|
||||
|
||||
save_value sv(m_validator);
|
||||
|
||||
ri = erase(ri);
|
||||
++result;
|
||||
}
|
||||
@@ -1238,6 +1252,9 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit
|
||||
++ri;
|
||||
}
|
||||
|
||||
for (auto &&[childCat, condition] : potential_orphans)
|
||||
childCat->erase_orphans(std::move(condition), *this);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,53 +76,82 @@ namespace detail
|
||||
return this;
|
||||
}
|
||||
|
||||
condition_impl *and_condition_impl::prepare(const category &c)
|
||||
bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
|
||||
{
|
||||
for (auto &sub : mSub)
|
||||
sub = sub->prepare(c);
|
||||
bool result = true;
|
||||
|
||||
for (;;)
|
||||
for (auto s = b; s != e; ++s)
|
||||
{
|
||||
auto si = find_if(mSub.begin(), mSub.end(), [](condition_impl *sub) { return dynamic_cast<and_condition_impl *>(sub) != nullptr; });
|
||||
if (si == mSub.end())
|
||||
auto &cs = (*s)->m_sub;
|
||||
|
||||
if (find_if(cs.begin(), cs.end(), [c](const condition_impl *i) { return i->equals(c); }) == cs.end())
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
|
||||
and_condition_impl *sub_and = static_cast<and_condition_impl *>(*si);
|
||||
|
||||
mSub.erase(si);
|
||||
|
||||
mSub.insert(mSub.end(), sub_and->mSub.begin(), sub_and->mSub.end());
|
||||
sub_and->mSub.clear();
|
||||
delete sub_and;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
return result;
|
||||
}
|
||||
|
||||
condition_impl *and_condition_impl::combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc)
|
||||
{
|
||||
and_condition_impl *and_result = nullptr;
|
||||
|
||||
auto first = subs.front();
|
||||
auto &fc = first->m_sub;
|
||||
|
||||
for (auto c : fc)
|
||||
{
|
||||
if (not found_in_range(c, subs.begin() + 1, subs.end()))
|
||||
continue;
|
||||
|
||||
if (and_result == nullptr)
|
||||
and_result = new and_condition_impl();
|
||||
|
||||
and_result->m_sub.push_back(c);
|
||||
fc.erase(remove(fc.begin(), fc.end(), c), fc.end());
|
||||
|
||||
for (auto sub : subs)
|
||||
{
|
||||
auto &ssub = sub->m_sub;
|
||||
|
||||
for (auto sc : ssub)
|
||||
{
|
||||
if (not sc->equals(c))
|
||||
continue;
|
||||
|
||||
ssub.erase(remove(ssub.begin(), ssub.end(), sc), ssub.end());
|
||||
delete sc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (and_result != nullptr)
|
||||
{
|
||||
and_result->m_sub.push_back(oc);
|
||||
return and_result;
|
||||
}
|
||||
|
||||
return oc;
|
||||
}
|
||||
|
||||
condition_impl *or_condition_impl::prepare(const category &c)
|
||||
{
|
||||
condition_impl *result = this;
|
||||
std::vector<and_condition_impl *> and_conditions;
|
||||
|
||||
mA = mA->prepare(c);
|
||||
mB = mB->prepare(c);
|
||||
|
||||
key_equals_condition_impl *equals = dynamic_cast<key_equals_condition_impl*>(mA);
|
||||
key_is_empty_condition_impl *empty = dynamic_cast<key_is_empty_condition_impl*>(mB);
|
||||
|
||||
if (equals == nullptr and empty == nullptr)
|
||||
for (auto &sub : m_sub)
|
||||
{
|
||||
equals = dynamic_cast<key_equals_condition_impl*>(mB);
|
||||
empty = dynamic_cast<key_is_empty_condition_impl*>(mA);
|
||||
sub = sub->prepare(c);
|
||||
if (typeid(*sub) == typeid(and_condition_impl))
|
||||
and_conditions.push_back(static_cast<and_condition_impl *>(sub));
|
||||
}
|
||||
|
||||
if (equals != nullptr and empty != nullptr and equals->m_item_tag == empty->m_item_tag)
|
||||
{
|
||||
result = new detail::key_equals_or_empty_condition_impl(equals);
|
||||
result = result->prepare(c);
|
||||
delete this;
|
||||
}
|
||||
if (and_conditions.size() == m_sub.size())
|
||||
return and_condition_impl::combine_equal(and_conditions, this);
|
||||
|
||||
return result;
|
||||
return this;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -125,7 +125,7 @@ void file::load_dictionary(std::string_view name)
|
||||
|
||||
bool file::contains(std::string_view name) const
|
||||
{
|
||||
return std::find_if(begin(), end(), [name](const datablock &db) { return db.name() == name; }) != end();
|
||||
return std::find_if(begin(), end(), [name](const datablock &db) { return iequals(db.name(), name); }) != end();
|
||||
}
|
||||
|
||||
datablock &file::operator[](std::string_view name)
|
||||
|
||||
@@ -935,7 +935,7 @@ float monomer::omega(const monomer &a, const monomer &b)
|
||||
|
||||
bool monomer::is_cis(const monomer &a, const monomer &b)
|
||||
{
|
||||
return omega(a, b) < 30.0f;
|
||||
return std::abs(omega(a, b)) < 30.0f;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -1688,7 +1688,10 @@ atom &structure::emplace_atom(atom &&atom)
|
||||
R = i - 1;
|
||||
}
|
||||
|
||||
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size());
|
||||
if (R == -1) // msvc...
|
||||
m_atom_index.insert(m_atom_index.begin(), m_atoms.size());
|
||||
else
|
||||
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size());
|
||||
|
||||
// make sure the atom_type is known
|
||||
auto &atom_type = m_db["atom_type"];
|
||||
|
||||
@@ -380,18 +380,13 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
{
|
||||
std::string s = to_lower_copy(m_token_value);
|
||||
|
||||
if (s == "global_")
|
||||
result = CIFToken::GLOBAL;
|
||||
else if (s == "stop_")
|
||||
result = CIFToken::STOP;
|
||||
else if (s == "loop_")
|
||||
result = CIFToken::LOOP;
|
||||
else if (s == "data_")
|
||||
if (s == "data_")
|
||||
{
|
||||
state = State::DATA;
|
||||
continue;
|
||||
}
|
||||
else if (s == "save_")
|
||||
|
||||
if (s == "save_")
|
||||
{
|
||||
state = State::SAVE;
|
||||
continue;
|
||||
@@ -405,6 +400,12 @@ sac_parser::CIFToken sac_parser::get_next_token()
|
||||
|
||||
if (m_token_value == ".")
|
||||
mTokenType = CIFValue::Inapplicable;
|
||||
else if (iequals(m_token_value, "global_"))
|
||||
result = CIFToken::GLOBAL;
|
||||
else if (iequals(m_token_value, "stop_"))
|
||||
result = CIFToken::STOP;
|
||||
else if (iequals(m_token_value, "loop_"))
|
||||
result = CIFToken::LOOP;
|
||||
else if (m_token_value == "?")
|
||||
{
|
||||
mTokenType = CIFValue::Unknown;
|
||||
@@ -786,6 +787,9 @@ void sac_parser::parse_save_frame()
|
||||
|
||||
void parser::produce_datablock(const std::string &name)
|
||||
{
|
||||
if (VERBOSE >= 4)
|
||||
std::cerr << "producing data_" << name << std::endl;
|
||||
|
||||
const auto &[iter, ignore] = m_file.emplace(name);
|
||||
m_datablock = &(*iter);
|
||||
}
|
||||
@@ -801,7 +805,7 @@ void parser::produce_category(const std::string &name)
|
||||
|
||||
void parser::produce_row()
|
||||
{
|
||||
if (VERBOSE >= 4)
|
||||
if (VERBOSE >= 4 and m_category != nullptr)
|
||||
std::cerr << "producing row for category " << m_category->name() << std::endl;
|
||||
|
||||
if (m_category == nullptr)
|
||||
|
||||
@@ -6102,13 +6102,6 @@ int PDBFileParser::PDBChain::AlignResToSeqRes()
|
||||
switch (tb(x, y))
|
||||
{
|
||||
case -1:
|
||||
// if (cif::VERBOSE > 0)
|
||||
// std::cerr << "A residue found in the ATOM records "
|
||||
// << "(" << ry[y].mMonID << " @ " << mDbref.chainID << ":" << ry[y].mSeqNum
|
||||
// << ((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) << ")"
|
||||
// << " was not found in the SEQRES records" << std::endl;
|
||||
// --y;
|
||||
|
||||
throw std::runtime_error("A residue found in the ATOM records (" + ry[y].mMonID +
|
||||
" @ " + std::string{ mDbref.chainID } + ":" + std::to_string(ry[y].mSeqNum) +
|
||||
((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) +
|
||||
@@ -6123,10 +6116,11 @@ int PDBFileParser::PDBChain::AlignResToSeqRes()
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (cif::VERBOSE > 3 and rx[x].mMonID != ry[y].mMonID)
|
||||
std::cerr << "Warning, unaligned residues at " << x << "/" << y << "(" << rx[x].mMonID << '/' << ry[y].mMonID << ')' << std::endl;
|
||||
else if (cif::VERBOSE > 4)
|
||||
std::cerr << rx[x].mMonID << " -> " << ry[y].mMonID << " (" << ry[y].mSeqNum << ')' << std::endl;
|
||||
if (rx[x].mMonID != ry[y].mMonID)
|
||||
{
|
||||
std::cerr << "Warning, unaligned residues at " << x << "/" << y << "(" << rx[x].mMonID << '/' << ry[y].mMonID << ") SEQRES does not agree with ATOM records" << std::endl;
|
||||
rx[x].mMonID = ry[y].mMonID;
|
||||
}
|
||||
|
||||
rx[x].mSeqNum = ry[y].mSeqNum;
|
||||
rx[x].mIcode = ry[y].mIcode;
|
||||
|
||||
@@ -87,17 +87,17 @@ class Matrix : public MatrixExpression<Matrix>
|
||||
Matrix &operator=(Matrix &&m) = default;
|
||||
Matrix &operator=(const Matrix &m) = default;
|
||||
|
||||
uint32_t dim_m() const { return m_m; }
|
||||
uint32_t dim_n() const { return m_n; }
|
||||
size_t dim_m() const { return m_m; }
|
||||
size_t dim_n() const { return m_n; }
|
||||
|
||||
double operator()(uint32_t i, uint32_t j) const
|
||||
double operator()(size_t i, size_t j) const
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
return m_data[i * m_n + j];
|
||||
}
|
||||
|
||||
double &operator()(uint32_t i, uint32_t j)
|
||||
double &operator()(size_t i, size_t j)
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
@@ -105,7 +105,7 @@ class Matrix : public MatrixExpression<Matrix>
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_m = 0, m_n = 0;
|
||||
size_t m_m = 0, m_n = 0;
|
||||
std::vector<double> m_data;
|
||||
};
|
||||
|
||||
@@ -522,15 +522,17 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
|
||||
|
||||
point nudge(point p, float offset)
|
||||
{
|
||||
static const float kPI_f = static_cast<float>(kPI);
|
||||
|
||||
static std::random_device rd;
|
||||
static std::mt19937_64 rng(rd());
|
||||
|
||||
std::uniform_real_distribution<float> randomAngle(0, 2 * kPI);
|
||||
std::normal_distribution<> randomOffset(0, offset);
|
||||
std::uniform_real_distribution<float> randomAngle(0, 2 * kPI_f);
|
||||
std::normal_distribution<float> randomOffset(0, offset);
|
||||
|
||||
float theta = randomAngle(rng);
|
||||
float phi1 = randomAngle(rng) - kPI;
|
||||
float phi2 = randomAngle(rng) - kPI;
|
||||
float phi1 = randomAngle(rng) - kPI_f;
|
||||
float phi2 = randomAngle(rng) - kPI_f;
|
||||
|
||||
quaternion q = spherical(1.0f, theta, phi1, phi2);
|
||||
|
||||
|
||||
@@ -124,7 +124,8 @@ std::string get_executable_path()
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
char path[PATH_MAX] = "";
|
||||
// This used to be PATH_MAX, but lets simply assume 1024 is enough...
|
||||
char path[1024] = "";
|
||||
if (readlink("/proc/self/exe", path, sizeof(path)) == -1)
|
||||
throw std::runtime_error("could not get exe path "s + strerror(errno));
|
||||
return {path};
|
||||
|
||||
@@ -58,6 +58,12 @@ bool init_unit_test()
|
||||
// not a test, just initialize test dir
|
||||
if (boost::unit_test::framework::master_test_suite().argc == 2)
|
||||
gTestDir = boost::unit_test::framework::master_test_suite().argv[1];
|
||||
else
|
||||
{
|
||||
while (not gTestDir.empty() and not std::filesystem::exists(gTestDir / "test"))
|
||||
gTestDir = gTestDir.parent_path();
|
||||
gTestDir /= "test";
|
||||
}
|
||||
|
||||
// do this now, avoids the need for installing
|
||||
cif::add_file_resource("mmcif_pdbx.dic", gTestDir / ".." / "rsrc" / "mmcif_pdbx.dic");
|
||||
|
||||
@@ -39,6 +39,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (argc == 3)
|
||||
testdir = argv[2];
|
||||
else
|
||||
{
|
||||
while (not testdir.empty() and not std::filesystem::exists(testdir / "test"))
|
||||
testdir = testdir.parent_path();
|
||||
testdir /= "test";
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(testdir / ".." / "data" / "ccd-subset.cif"))
|
||||
cif::add_file_resource("components.cif", testdir / ".." / "data" / "ccd-subset.cif");
|
||||
|
||||
@@ -2322,15 +2322,22 @@ _test.text ??
|
||||
|
||||
BOOST_AUTO_TEST_CASE(output_test_1)
|
||||
{
|
||||
cif::VERBOSE = 5;
|
||||
|
||||
auto data1 = R"(
|
||||
data_Q
|
||||
loop_
|
||||
_test.text
|
||||
"stop_the_crap"
|
||||
stop_the_crap
|
||||
'and stop_ this too'
|
||||
'data_dinges'
|
||||
'blablaglobal_bla'
|
||||
blablaglobal_bla
|
||||
boo.data_.whatever
|
||||
'data_.whatever'
|
||||
'stop_'
|
||||
'loop_'
|
||||
'global_'
|
||||
'_with.leading_underscore'
|
||||
)"_cf;
|
||||
|
||||
auto &db1 = data1.front();
|
||||
@@ -2341,11 +2348,16 @@ boo.data_.whatever
|
||||
const char *s;
|
||||
bool q;
|
||||
} kS[] = {
|
||||
{ "stop_the_crap", false },
|
||||
{ "stop_the_crap", true },
|
||||
{ "and stop_ this too", false },
|
||||
{ "data_dinges", false },
|
||||
{ "blablaglobal_bla", false },
|
||||
{ "boo.data_.whatever", true }
|
||||
{ "blablaglobal_bla", true },
|
||||
{ "boo.data_.whatever", true },
|
||||
{ "data_.whatever", false },
|
||||
{ "stop_", false },
|
||||
{ "loop_", false },
|
||||
{ "global_", false },
|
||||
{ "_with.leading_underscore", false }
|
||||
};
|
||||
|
||||
BOOST_CHECK_EQUAL(test1.size(), sizeof(kS) / sizeof(T));
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$EUID" -ne 0 ]
|
||||
# Get the effective UID, but do so in a compatible way (we may be running dash)
|
||||
euid=${EUID:-$(id -u)}
|
||||
|
||||
if [ "${euid}" -ne 0 ] ; then
|
||||
then echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
@@ -46,10 +49,10 @@ fetch_dictionary () {
|
||||
fetch_dictionary "@CIFPP_CACHE_DIR@/mmcif_pdbx.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz"
|
||||
fetch_dictionary "@CIFPP_CACHE_DIR@/components.cif" "ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz"
|
||||
|
||||
wget -O"@CIFPP_CACHE_DIR@/mmcif_ma.dic" "https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic"
|
||||
|
||||
# notify subscribers, will fail on FreeBSD
|
||||
|
||||
if [ -d "@CIFPP_ETC_DIR@/libcifpp/cache-update.d" ] && [ -x /bin/run-parts ]; then
|
||||
run-parts --arg "@CIFPP_CACHE_DIR@" -- "@CIFPP_ETC_DIR@/libcifpp/cache-update.d"
|
||||
fi
|
||||
|
||||
wget -O"@CIFPP_CACHE_DIR@/mmcif_ma.dic" "https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic"
|
||||
|
||||
Reference in New Issue
Block a user