Commit cb3443ff by Maarten L. Hekkelman

Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop

parents 6b2c9dc3 8bbcba76
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
# set the project name # set the project name
project(cifpp VERSION 2.0.2 LANGUAGES CXX) project(cifpp VERSION 3.0.0 LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
......
Version 3.0.0
- Replaced many strings in the API with string_view for
performance reasons.
- Upgraded mmcif::Structure
Version 2.0.2 Version 2.0.2
- Added configuration flag to disable downloading CCD data during build - Added configuration flag to disable downloading CCD data during build
Note that there are now two flags for CCD data: Note that there are now two flags for CCD data:
......
...@@ -238,9 +238,9 @@ class Datablock ...@@ -238,9 +238,9 @@ class Datablock
const_iterator begin() const { return mCategories.begin(); } const_iterator begin() const { return mCategories.begin(); }
const_iterator end() const { return mCategories.end(); } const_iterator end() const { return mCategories.end(); }
Category &operator[](const std::string &name); Category &operator[](std::string_view name);
std::tuple<iterator, bool> emplace(const std::string &name); std::tuple<iterator, bool> emplace(std::string_view name);
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
...@@ -248,8 +248,8 @@ class Datablock ...@@ -248,8 +248,8 @@ class Datablock
void setValidator(Validator *v); void setValidator(Validator *v);
// this one only looks up a Category, returns nullptr if it does not exist // this one only looks up a Category, returns nullptr if it does not exist
const Category *get(const std::string &name) const; const Category *get(std::string_view name) const;
Category *get(const std::string &name); Category *get(std::string_view name);
void getTagOrder(std::vector<std::string> &tags) const; void getTagOrder(std::vector<std::string> &tags) const;
void write(std::ostream &os, const std::vector<std::string> &order); void write(std::ostream &os, const std::vector<std::string> &order);
...@@ -350,14 +350,14 @@ namespace detail ...@@ -350,14 +350,14 @@ namespace detail
private: private:
friend class ::cif::Row; friend class ::cif::Row;
ItemReference(const char *name, size_t column, Row &row) ItemReference(std::string_view name, size_t column, Row &row)
: mName(name) : mName(name)
, mColumn(column) , mColumn(column)
, mRow(row) , mRow(row)
{ {
} }
ItemReference(const char *name, size_t column, const Row &row) ItemReference(std::string_view name, size_t column, const Row &row)
: mName(name) : mName(name)
, mColumn(column) , mColumn(column)
, mRow(const_cast<Row &>(row)) , mRow(const_cast<Row &>(row))
...@@ -365,7 +365,7 @@ namespace detail ...@@ -365,7 +365,7 @@ namespace detail
{ {
} }
const char *mName; std::string_view mName;
size_t mColumn; size_t mColumn;
Row &mRow; Row &mRow;
bool mConst = false; bool mConst = false;
...@@ -746,16 +746,16 @@ class Row ...@@ -746,16 +746,16 @@ class Row
return detail::ItemReference(itemTag, column, *this); return detail::ItemReference(itemTag, column, *this);
} }
const detail::ItemReference operator[](const std::string &itemTag) const const detail::ItemReference operator[](std::string_view itemTag) const
{ {
size_t column = ColumnForItemTag(itemTag.c_str()); size_t column = ColumnForItemTag(itemTag);
return detail::ItemReference(itemTag.c_str(), column, *this); return detail::ItemReference(itemTag, column, *this);
} }
detail::ItemReference operator[](const std::string &itemTag) detail::ItemReference operator[](std::string_view itemTag)
{ {
size_t column = ColumnForItemTag(itemTag.c_str()); size_t column = ColumnForItemTag(itemTag);
return detail::ItemReference(itemTag.c_str(), column, *this); return detail::ItemReference(itemTag, column, *this);
} }
template <typename... Ts, size_t N> template <typename... Ts, size_t N>
...@@ -776,7 +776,7 @@ class Row ...@@ -776,7 +776,7 @@ class Row
} }
void assign(const std::vector<Item> &values); void assign(const std::vector<Item> &values);
void assign(const std::string &name, const std::string &value, bool updateLinked); void assign(std::string_view name, const std::string &value, bool updateLinked);
bool operator==(const Row &rhs) const bool operator==(const Row &rhs) const
{ {
...@@ -803,7 +803,7 @@ class Row ...@@ -803,7 +803,7 @@ class Row
static void swap(size_t column, ItemRow *a, ItemRow *b); static void swap(size_t column, ItemRow *a, ItemRow *b);
size_t ColumnForItemTag(const char *itemTag) const; size_t ColumnForItemTag(std::string_view itemTag) const;
mutable ItemRow *mData; mutable ItemRow *mData;
uint32_t mLineNr = 0; uint32_t mLineNr = 0;
...@@ -2077,8 +2077,8 @@ class Category ...@@ -2077,8 +2077,8 @@ class Category
void getTagOrder(std::vector<std::string> &tags) const; void getTagOrder(std::vector<std::string> &tags) const;
// return index for known column, or the next available column index // return index for known column, or the next available column index
size_t getColumnIndex(const std::string &name) const; size_t getColumnIndex(std::string_view name) const;
bool hasColumn(const std::string &name) const; bool hasColumn(std::string_view name) const;
const std::string &getColumnName(size_t columnIndex) const; const std::string &getColumnName(size_t columnIndex) const;
std::vector<std::string> getColumnNames() const; std::vector<std::string> getColumnNames() const;
...@@ -2119,7 +2119,7 @@ class Category ...@@ -2119,7 +2119,7 @@ class Category
void write(std::ostream &os, const std::vector<std::string> &order); void write(std::ostream &os, const std::vector<std::string> &order);
void write(std::ostream &os, const std::vector<size_t> &order, bool includeEmptyColumns); void write(std::ostream &os, const std::vector<size_t> &order, bool includeEmptyColumns);
size_t addColumn(const std::string &name); size_t addColumn(std::string_view name);
Datablock &mDb; Datablock &mDb;
std::string mName; std::string mName;
...@@ -2183,8 +2183,8 @@ class File ...@@ -2183,8 +2183,8 @@ class File
void append(Datablock *e); void append(Datablock *e);
Datablock *get(const std::string &name) const; Datablock *get(std::string_view name) const;
Datablock &operator[](const std::string &name); Datablock &operator[](std::string_view name);
struct iterator struct iterator
{ {
......
...@@ -94,10 +94,6 @@ inline bool isUnquotedString(const char* s) ...@@ -94,10 +94,6 @@ inline bool isUnquotedString(const char* s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string,std::string> splitTagName(const std::string& tag);
// --------------------------------------------------------------------
using DatablockIndex = std::map<std::string,std::size_t>; using DatablockIndex = std::map<std::string,std::size_t>;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -67,8 +67,10 @@ std::string get_version_nr(); ...@@ -67,8 +67,10 @@ std::string get_version_nr();
// some basic utilities: Since we're using ASCII input only, we define for optimisation // some basic utilities: Since we're using ASCII input only, we define for optimisation
// our own case conversion routines. // our own case conversion routines.
bool iequals(const std::string &a, const std::string &b); // bool iequals(const std::string &a, const std::string &b);
int icompare(const std::string &a, const std::string &b); bool iequals(std::string_view a, std::string_view b);
// int icompare(const std::string &a, const std::string &b);
int icompare(std::string_view a, std::string_view b);
bool iequals(const char *a, const char *b); bool iequals(const char *a, const char *b);
int icompare(const char *a, const char *b); int icompare(const char *a, const char *b);
...@@ -100,7 +102,7 @@ inline char tolower(int ch) ...@@ -100,7 +102,7 @@ inline char tolower(int ch)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string, std::string> splitTagName(const std::string &tag); std::tuple<std::string, std::string> splitTagName(std::string_view tag);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// generate a cif name, mainly used to generate asym_id's // generate a cif name, mainly used to generate asym_id's
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
namespace cif namespace cif
{ {
struct ValidateCategory; struct ValidateCategory;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -44,10 +44,10 @@ struct ValidateCategory; ...@@ -44,10 +44,10 @@ struct ValidateCategory;
class ValidationError : public std::exception class ValidationError : public std::exception
{ {
public: public:
ValidationError(const std::string& msg); ValidationError(const std::string &msg);
ValidationError(const std::string& cat, const std::string& item, ValidationError(const std::string &cat, const std::string &item,
const std::string& msg); const std::string &msg);
const char* what() const noexcept { return mMsg.c_str(); } const char *what() const noexcept { return mMsg.c_str(); }
std::string mMsg; std::string mMsg;
}; };
...@@ -55,58 +55,60 @@ class ValidationError : public std::exception ...@@ -55,58 +55,60 @@ class ValidationError : public std::exception
enum class DDL_PrimitiveType enum class DDL_PrimitiveType
{ {
Char, UChar, Numb Char,
UChar,
Numb
}; };
DDL_PrimitiveType mapToPrimitiveType(const std::string& s); DDL_PrimitiveType mapToPrimitiveType(std::string_view s);
struct ValidateType struct ValidateType
{ {
std::string mName; std::string mName;
DDL_PrimitiveType mPrimitiveType; DDL_PrimitiveType mPrimitiveType;
// std::regex mRx; // std::regex mRx;
boost::regex mRx; boost::regex mRx;
bool operator<(const ValidateType& rhs) const bool operator<(const ValidateType &rhs) const
{ {
return icompare(mName, rhs.mName) < 0; return icompare(mName, rhs.mName) < 0;
} }
// compare values based on type // compare values based on type
// int compare(const std::string& a, const std::string& b) const // int compare(const std::string& a, const std::string& b) const
// { // {
// return compare(a.c_str(), b.c_str()); // return compare(a.c_str(), b.c_str());
// } // }
int compare(const char* a, const char* b) const; int compare(const char *a, const char *b) const;
}; };
struct ValidateItem struct ValidateItem
{ {
std::string mTag; std::string mTag;
bool mMandatory; bool mMandatory;
const ValidateType* mType; const ValidateType *mType;
cif::iset mEnums; cif::iset mEnums;
std::string mDefault; std::string mDefault;
bool mDefaultIsNull; bool mDefaultIsNull;
ValidateCategory* mCategory = nullptr; ValidateCategory *mCategory = nullptr;
// ItemLinked is used for non-key links // ItemLinked is used for non-key links
struct ItemLinked struct ItemLinked
{ {
ValidateItem* mParent; ValidateItem *mParent;
std::string mParentItem; std::string mParentItem;
std::string mChildItem; std::string mChildItem;
}; };
std::vector<ItemLinked> mLinked; std::vector<ItemLinked> mLinked;
bool operator<(const ValidateItem& rhs) const bool operator<(const ValidateItem &rhs) const
{ {
return icompare(mTag, rhs.mTag) < 0; return icompare(mTag, rhs.mTag) < 0;
} }
bool operator==(const ValidateItem& rhs) const bool operator==(const ValidateItem &rhs) const
{ {
return iequals(mTag, rhs.mTag); return iequals(mTag, rhs.mTag);
} }
...@@ -116,22 +118,22 @@ struct ValidateItem ...@@ -116,22 +118,22 @@ struct ValidateItem
struct ValidateCategory struct ValidateCategory
{ {
std::string mName; std::string mName;
std::vector<std::string> mKeys; std::vector<std::string> mKeys;
cif::iset mGroups; cif::iset mGroups;
cif::iset mMandatoryFields; cif::iset mMandatoryFields;
std::set<ValidateItem> mItemValidators; std::set<ValidateItem> mItemValidators;
bool operator<(const ValidateCategory& rhs) const bool operator<(const ValidateCategory &rhs) const
{ {
return icompare(mName, rhs.mName) < 0; return icompare(mName, rhs.mName) < 0;
} }
void addItemValidator(ValidateItem&& v); void addItemValidator(ValidateItem &&v);
const ValidateItem* getValidatorForItem(std::string tag) const; const ValidateItem *getValidatorForItem(std::string_view tag) const;
const std::set<ValidateItem>& itemValidators() const const std::set<ValidateItem> &itemValidators() const
{ {
return mItemValidators; return mItemValidators;
} }
...@@ -139,12 +141,12 @@ struct ValidateCategory ...@@ -139,12 +141,12 @@ struct ValidateCategory
struct ValidateLink struct ValidateLink
{ {
int mLinkGroupID; int mLinkGroupID;
std::string mParentCategory; std::string mParentCategory;
std::vector<std::string> mParentKeys; std::vector<std::string> mParentKeys;
std::string mChildCategory; std::string mChildCategory;
std::vector<std::string> mChildKeys; std::vector<std::string> mChildKeys;
std::string mLinkGroupLabel; std::string mLinkGroupLabel;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -157,42 +159,41 @@ class Validator ...@@ -157,42 +159,41 @@ class Validator
Validator(); Validator();
~Validator(); ~Validator();
Validator(const Validator& rhs) = delete; Validator(const Validator &rhs) = delete;
Validator& operator=(const Validator& rhs) = delete; Validator &operator=(const Validator &rhs) = delete;
Validator(Validator&& rhs);
Validator& operator=(Validator&& rhs);
void addTypeValidator(ValidateType&& v);
const ValidateType* getValidatorForType(std::string typeCode) const;
void addCategoryValidator(ValidateCategory&& v); Validator(Validator &&rhs);
const ValidateCategory* getValidatorForCategory(std::string category) const; Validator &operator=(Validator &&rhs);
void addLinkValidator(ValidateLink&& v); void addTypeValidator(ValidateType &&v);
std::vector<const ValidateLink*> getLinksForParent(const std::string& category) const; const ValidateType *getValidatorForType(std::string_view typeCode) const;
std::vector<const ValidateLink*> getLinksForChild(const std::string& category) const;
void reportError(const std::string& msg, bool fatal); void addCategoryValidator(ValidateCategory &&v);
const ValidateCategory *getValidatorForCategory(std::string_view category) const;
std::string dictName() const { return mName; }
void dictName(const std::string& name) { mName = name; }
std::string dictVersion() const { return mVersion; } void addLinkValidator(ValidateLink &&v);
void dictVersion(const std::string& version) { mVersion = version; } std::vector<const ValidateLink *> getLinksForParent(std::string_view category) const;
std::vector<const ValidateLink *> getLinksForChild(std::string_view category) const;
private: void reportError(const std::string &msg, bool fatal);
std::string dictName() const { return mName; }
void dictName(const std::string &name) { mName = name; }
std::string dictVersion() const { return mVersion; }
void dictVersion(const std::string &version) { mVersion = version; }
private:
// name is fully qualified here: // name is fully qualified here:
ValidateItem* getValidatorForItem(std::string name) const; ValidateItem *getValidatorForItem(std::string_view name) const;
std::string mName; std::string mName;
std::string mVersion; std::string mVersion;
bool mStrict = false; bool mStrict = false;
// std::set<uint32_t> mSubCategories; // std::set<uint32_t> mSubCategories;
std::set<ValidateType> mTypeValidators; std::set<ValidateType> mTypeValidators;
std::set<ValidateCategory> mCategoryValidators; std::set<ValidateCategory> mCategoryValidators;
std::vector<ValidateLink> mLinkValidators; std::vector<ValidateLink> mLinkValidators;
}; };
} } // namespace cif
...@@ -461,9 +461,18 @@ class Structure ...@@ -461,9 +461,18 @@ 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 = "");
/// \brief Return the atom closest to point \a p
Atom getAtomByPosition(Point p) const;
/// \brief Return the atom closest to point \a p with atom type \a type in a residue of type \a res_type
Atom getAtomByPositionAndType(Point p, std::string_view type, std::string_view res_type) const;
/// \brief Get a residue, if \a seqID is zero, the non-polymers are searched /// \brief Get a residue, if \a seqID is zero, the non-polymers are searched
const Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID = 0) const; const Residue &getResidue(const std::string &asymID, const std::string &compID, int seqID = 0) const;
/// \brief Get a the single residue for an asym with id \a asymID
const Residue &getResidue(const std::string &asymID) const;
// map between auth and label locations // map between auth and label locations
std::tuple<std::string, int, std::string> MapAuthToLabel(const std::string &asymID, std::tuple<std::string, int, std::string> MapAuthToLabel(const std::string &asymID,
...@@ -519,15 +528,16 @@ class Structure ...@@ -519,15 +528,16 @@ class Structure
void cleanupEmptyCategories(); void cleanupEmptyCategories();
/// \brief Direct access to underlying data
cif::Category &category(std::string_view name) const;
cif::Datablock &datablock() const;
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::Datablock &datablock() const;
std::string insertCompound(const std::string &compoundID, bool isEntity); std::string insertCompound(const std::string &compoundID, bool isEntity);
void loadData(); void loadData();
......
...@@ -387,7 +387,7 @@ std::string Datablock::firstItem(const std::string &tag) const ...@@ -387,7 +387,7 @@ std::string Datablock::firstItem(const std::string &tag) const
return result; return result;
} }
auto Datablock::emplace(const std::string &name) -> std::tuple<iterator, bool> auto Datablock::emplace(std::string_view name) -> std::tuple<iterator, bool>
{ {
bool isNew = false; bool isNew = false;
iterator i = find_if(begin(), end(), [name](const Category &cat) -> bool iterator i = find_if(begin(), end(), [name](const Category &cat) -> bool
...@@ -396,20 +396,20 @@ auto Datablock::emplace(const std::string &name) -> std::tuple<iterator, bool> ...@@ -396,20 +396,20 @@ auto Datablock::emplace(const std::string &name) -> std::tuple<iterator, bool>
if (i == end()) if (i == end())
{ {
isNew = true; isNew = true;
i = mCategories.emplace(end(), *this, name, mValidator); i = mCategories.emplace(end(), *this, std::string(name), mValidator);
} }
return std::make_tuple(i, isNew); return std::make_tuple(i, isNew);
} }
Category &Datablock::operator[](const std::string &name) Category &Datablock::operator[](std::string_view name)
{ {
iterator i; iterator i;
std::tie(i, std::ignore) = emplace(name); std::tie(i, std::ignore) = emplace(name);
return *i; return *i;
} }
Category *Datablock::get(const std::string &name) Category *Datablock::get(std::string_view name)
{ {
auto i = find_if(begin(), end(), [name](const Category &cat) -> bool auto i = find_if(begin(), end(), [name](const Category &cat) -> bool
{ return iequals(cat.name(), name); }); { return iequals(cat.name(), name); });
...@@ -417,7 +417,7 @@ Category *Datablock::get(const std::string &name) ...@@ -417,7 +417,7 @@ Category *Datablock::get(const std::string &name)
return i == end() ? nullptr : &*i; return i == end() ? nullptr : &*i;
} }
const Category *Datablock::get(const std::string &name) const const Category *Datablock::get(std::string_view name) const
{ {
auto i = find_if(begin(), end(), [name](const Category &cat) -> bool auto i = find_if(begin(), end(), [name](const Category &cat) -> bool
{ return iequals(cat.name(), name); }); { return iequals(cat.name(), name); });
...@@ -1373,12 +1373,12 @@ void Category::setValidator(Validator *v) ...@@ -1373,12 +1373,12 @@ void Category::setValidator(Validator *v)
mCatValidator = nullptr; mCatValidator = nullptr;
} }
bool Category::hasColumn(const std::string &name) const bool Category::hasColumn(std::string_view name) const
{ {
return getColumnIndex(name) < mColumns.size(); return getColumnIndex(name) < mColumns.size();
} }
size_t Category::getColumnIndex(const std::string &name) const size_t Category::getColumnIndex(std::string_view name) const
{ {
size_t result; size_t result;
...@@ -1392,7 +1392,7 @@ size_t Category::getColumnIndex(const std::string &name) const ...@@ -1392,7 +1392,7 @@ size_t Category::getColumnIndex(const std::string &name) const
{ {
auto iv = mCatValidator->getValidatorForItem(name); auto iv = mCatValidator->getValidatorForItem(name);
if (iv == nullptr) if (iv == nullptr)
std::cerr << "Invalid name used '" + name + "' is not a known column in " + mName << std::endl; std::cerr << "Invalid name used '" << name << "' is not a known column in " + mName << std::endl;
} }
return result; return result;
...@@ -1411,8 +1411,10 @@ std::vector<std::string> Category::getColumnNames() const ...@@ -1411,8 +1411,10 @@ std::vector<std::string> Category::getColumnNames() const
return result; return result;
} }
size_t Category::addColumn(const std::string &name) size_t Category::addColumn(std::string_view name)
{ {
using namespace std::literals;
size_t result = getColumnIndex(name); size_t result = getColumnIndex(name);
if (result == mColumns.size()) if (result == mColumns.size())
...@@ -1423,10 +1425,10 @@ size_t Category::addColumn(const std::string &name) ...@@ -1423,10 +1425,10 @@ size_t Category::addColumn(const std::string &name)
{ {
itemValidator = mCatValidator->getValidatorForItem(name); itemValidator = mCatValidator->getValidatorForItem(name);
if (itemValidator == nullptr) if (itemValidator == nullptr)
mValidator->reportError("tag " + name + " not allowed in Category " + mName, false); mValidator->reportError("tag " + std::string(name) + " not allowed in Category " + mName, false);
} }
mColumns.push_back({name, itemValidator}); mColumns.push_back(ItemColumn{std::string(name), itemValidator});
} }
return result; return result;
...@@ -2909,7 +2911,7 @@ void Row::assign(const Item &value, bool skipUpdateLinked) ...@@ -2909,7 +2911,7 @@ void Row::assign(const Item &value, bool skipUpdateLinked)
assign(value.name(), value.value(), skipUpdateLinked); assign(value.name(), value.value(), skipUpdateLinked);
} }
void Row::assign(const std::string &name, const std::string &value, bool skipUpdateLinked) void Row::assign(std::string_view name, const std::string &value, bool skipUpdateLinked)
{ {
try try
{ {
...@@ -3309,7 +3311,7 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b) ...@@ -3309,7 +3311,7 @@ void Row::swap(size_t cix, ItemRow *a, ItemRow *b)
} }
} }
size_t Row::ColumnForItemTag(const char *itemTag) const size_t Row::ColumnForItemTag(std::string_view itemTag) const
{ {
size_t result = 0; size_t result = 0;
if (mData != nullptr) if (mData != nullptr)
...@@ -3549,7 +3551,7 @@ void File::write(std::ostream &os, const std::vector<std::string> &order) ...@@ -3549,7 +3551,7 @@ void File::write(std::ostream &os, const std::vector<std::string> &order)
} }
} }
Datablock *File::get(const std::string &name) const Datablock *File::get(std::string_view name) const
{ {
const Datablock *result = mHead; const Datablock *result = mHead;
while (result != nullptr and not iequals(result->mName, name)) while (result != nullptr and not iequals(result->mName, name))
...@@ -3557,13 +3559,15 @@ Datablock *File::get(const std::string &name) const ...@@ -3557,13 +3559,15 @@ Datablock *File::get(const std::string &name) const
return const_cast<Datablock *>(result); return const_cast<Datablock *>(result);
} }
Datablock &File::operator[](const std::string &name) Datablock &File::operator[](std::string_view name)
{ {
using namespace std::literals;
Datablock *result = mHead; Datablock *result = mHead;
while (result != nullptr and not iequals(result->mName, name)) while (result != nullptr and not iequals(result->mName, name))
result = result->mNext; result = result->mNext;
if (result == nullptr) if (result == nullptr)
throw std::runtime_error("Datablock " + name + " does not exist"); throw std::runtime_error("Datablock " + std::string(name) + " does not exist");
return *result; return *result;
} }
......
...@@ -811,7 +811,7 @@ typedef RM<3> RM3; ...@@ -811,7 +811,7 @@ typedef RM<3> RM3;
template<int N> template<int N>
std::ostream& operator<<(std::ostream& os, RM<N>&& rm) std::ostream& operator<<(std::ostream& os, RM<N>&& rm)
{ {
os << "REMARK " << std::setw(3) << std::right << N << " " << rm.mDesc << (rm.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(abs(rm.mWidth)) << std::setprecision(rm.mPrecision); os << "REMARK " << std::setw(3) << std::right << N << " " << rm.mDesc << (rm.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(std::abs(rm.mWidth)) << std::setprecision(rm.mPrecision);
return os; return os;
} }
...@@ -824,7 +824,7 @@ struct SEP ...@@ -824,7 +824,7 @@ struct SEP
std::ostream& operator<<(std::ostream& os, SEP&& sep) std::ostream& operator<<(std::ostream& os, SEP&& sep)
{ {
os << sep.mText << (sep.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(abs(sep.mWidth)) << std::setprecision(sep.mPrecision); os << sep.mText << (sep.mWidth > 0 ? std::left : std::right) << std::fixed << std::setw(std::abs(sep.mWidth)) << std::setprecision(sep.mPrecision);
return os; return os;
} }
......
...@@ -131,6 +131,14 @@ bool iequals(const std::string &a, const std::string &b) ...@@ -131,6 +131,14 @@ bool iequals(const std::string &a, const std::string &b)
return result; return result;
} }
bool iequals(std::string_view a, std::string_view b)
{
bool result = a.length() == b.length();
for (auto ai = a.begin(), bi = b.begin(); result and ai != a.end() and bi != b.end(); ++ai, ++bi)
result = tolower(*ai) == tolower(*bi);
return result;
}
bool iequals(const char *a, const char *b) bool iequals(const char *a, const char *b)
{ {
bool result = true; bool result = true;
...@@ -159,6 +167,25 @@ int icompare(const std::string &a, const std::string &b) ...@@ -159,6 +167,25 @@ int icompare(const std::string &a, const std::string &b)
return d; return d;
} }
int icompare(std::string_view a, std::string_view b)
{
int d = 0;
auto ai = a.begin(), bi = b.begin();
for (; d == 0 and ai != a.end() and bi != b.end(); ++ai, ++bi)
d = tolower(*ai) - tolower(*bi);
if (d == 0)
{
if (ai != a.end())
d = 1;
else if (bi != b.end())
d = -1;
}
return d;
}
int icompare(const char *a, const char *b) int icompare(const char *a, const char *b)
{ {
int d = 0; int d = 0;
...@@ -193,7 +220,7 @@ std::string toLowerCopy(const std::string &s) ...@@ -193,7 +220,7 @@ std::string toLowerCopy(const std::string &s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::tuple<std::string, std::string> splitTagName(const std::string &tag) std::tuple<std::string, std::string> splitTagName(std::string_view tag)
{ {
if (tag.empty()) if (tag.empty())
throw std::runtime_error("empty tag"); throw std::runtime_error("empty tag");
......
...@@ -37,19 +37,19 @@ extern int VERBOSE; ...@@ -37,19 +37,19 @@ extern int VERBOSE;
namespace cif namespace cif
{ {
ValidationError::ValidationError(const std::string& msg) ValidationError::ValidationError(const std::string &msg)
: mMsg(msg) : mMsg(msg)
{ {
} }
ValidationError::ValidationError(const std::string& cat, const std::string& item, const std::string& msg) ValidationError::ValidationError(const std::string &cat, const std::string &item, const std::string &msg)
: mMsg("When validating _" + cat + '.' + item + ": " + msg) : mMsg("When validating _" + cat + '.' + item + ": " + msg)
{ {
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
DDL_PrimitiveType mapToPrimitiveType(const std::string& s) DDL_PrimitiveType mapToPrimitiveType(std::string_view s)
{ {
DDL_PrimitiveType result; DDL_PrimitiveType result;
if (iequals(s, "char")) if (iequals(s, "char"))
...@@ -65,10 +65,10 @@ DDL_PrimitiveType mapToPrimitiveType(const std::string& s) ...@@ -65,10 +65,10 @@ DDL_PrimitiveType mapToPrimitiveType(const std::string& s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
int ValidateType::compare(const char* a, const char* b) const int ValidateType::compare(const char *a, const char *b) const
{ {
int result = 0; int result = 0;
if (*a == 0) if (*a == 0)
result = *b == 0 ? 0 : -1; result = *b == 0 ? 0 : -1;
else if (*b == 0) else if (*b == 0)
...@@ -83,7 +83,7 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -83,7 +83,7 @@ int ValidateType::compare(const char* a, const char* b) const
{ {
double da = strtod(a, nullptr); double da = strtod(a, nullptr);
double db = strtod(b, nullptr); double db = strtod(b, nullptr);
auto d = da - db; auto d = da - db;
if (std::abs(d) > std::numeric_limits<double>::epsilon()) if (std::abs(d) > std::numeric_limits<double>::epsilon())
{ {
...@@ -94,13 +94,13 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -94,13 +94,13 @@ int ValidateType::compare(const char* a, const char* b) const
} }
break; break;
} }
case DDL_PrimitiveType::UChar: case DDL_PrimitiveType::UChar:
case DDL_PrimitiveType::Char: case DDL_PrimitiveType::Char:
{ {
// CIF is guaranteed to have ascii only, therefore this primitive code will do // CIF is guaranteed to have ascii only, therefore this primitive code will do
// also, we're collapsing spaces // also, we're collapsing spaces
auto ai = a, bi = b; auto ai = a, bi = b;
for (;;) for (;;)
{ {
...@@ -115,7 +115,7 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -115,7 +115,7 @@ int ValidateType::compare(const char* a, const char* b) const
result = 1; result = 1;
break; break;
} }
char ca = *ai; char ca = *ai;
char cb = *bi; char cb = *bi;
...@@ -124,12 +124,12 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -124,12 +124,12 @@ int ValidateType::compare(const char* a, const char* b) const
ca = tolower(ca); ca = tolower(ca);
cb = tolower(cb); cb = tolower(cb);
} }
result = ca - cb; result = ca - cb;
if (result != 0) if (result != 0)
break; break;
if (ca == ' ') if (ca == ' ')
{ {
while (ai[1] == ' ') while (ai[1] == ' ')
...@@ -137,21 +137,21 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -137,21 +137,21 @@ int ValidateType::compare(const char* a, const char* b) const
while (bi[1] == ' ') while (bi[1] == ' ')
++bi; ++bi;
} }
++ai; ++ai;
++bi; ++bi;
} }
break; break;
} }
} }
} }
catch (const std::invalid_argument& ex) catch (const std::invalid_argument &ex)
{ {
result = 1; result = 1;
} }
} }
return result; return result;
} }
...@@ -165,13 +165,13 @@ int ValidateType::compare(const char* a, const char* b) const ...@@ -165,13 +165,13 @@ int ValidateType::compare(const char* a, const char* b) const
// //
// if (mType == nullptr and parent != nullptr) // if (mType == nullptr and parent != nullptr)
// mType = parent->mType; // mType = parent->mType;
// //
// if (parent != nullptr) // if (parent != nullptr)
// { // {
// mLinked.push_back({parent, parentItem, childItem}); // mLinked.push_back({parent, parentItem, childItem});
// //
// parent->mChildren.insert(this); // parent->mChildren.insert(this);
//// ////
//// if (mCategory->mKeys == std::vector<std::string>{mTag}) //// if (mCategory->mKeys == std::vector<std::string>{mTag})
//// parent->mForeignKeys.insert(this); //// parent->mForeignKeys.insert(this);
// } // }
...@@ -194,7 +194,7 @@ void ValidateItem::operator()(std::string value) const ...@@ -194,7 +194,7 @@ void ValidateItem::operator()(std::string value) const
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void ValidateCategory::addItemValidator(ValidateItem&& v) void ValidateCategory::addItemValidator(ValidateItem &&v)
{ {
if (v.mMandatory) if (v.mMandatory)
mMandatoryFields.insert(v.mTag); mMandatoryFields.insert(v.mTag);
...@@ -206,10 +206,10 @@ void ValidateCategory::addItemValidator(ValidateItem&& v) ...@@ -206,10 +206,10 @@ void ValidateCategory::addItemValidator(ValidateItem&& v)
std::cout << "Could not add validator for item " << v.mTag << " to category " << mName << std::endl; std::cout << "Could not add validator for item " << v.mTag << " to category " << mName << std::endl;
} }
const ValidateItem* ValidateCategory::getValidatorForItem(std::string tag) const const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) const
{ {
const ValidateItem* result = nullptr; const ValidateItem *result = nullptr;
auto i = mItemValidators.find(ValidateItem{tag}); auto i = mItemValidators.find(ValidateItem{std::string(tag)});
if (i != mItemValidators.end()) if (i != mItemValidators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -227,18 +227,18 @@ Validator::~Validator() ...@@ -227,18 +227,18 @@ Validator::~Validator()
{ {
} }
void Validator::addTypeValidator(ValidateType&& v) void Validator::addTypeValidator(ValidateType &&v)
{ {
auto r = mTypeValidators.insert(std::move(v)); auto r = mTypeValidators.insert(std::move(v));
if (not r.second and VERBOSE > 4) if (not r.second and VERBOSE > 4)
std::cout << "Could not add validator for type " << v.mName << std::endl; std::cout << "Could not add validator for type " << v.mName << std::endl;
} }
const ValidateType* Validator::getValidatorForType(std::string typeCode) const const ValidateType *Validator::getValidatorForType(std::string_view typeCode) const
{ {
const ValidateType* result = nullptr; const ValidateType *result = nullptr;
auto i = mTypeValidators.find(ValidateType{ typeCode, DDL_PrimitiveType::Char, boost::regex() }); auto i = mTypeValidators.find(ValidateType{std::string(typeCode), DDL_PrimitiveType::Char, boost::regex()});
if (i != mTypeValidators.end()) if (i != mTypeValidators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -246,17 +246,17 @@ const ValidateType* Validator::getValidatorForType(std::string typeCode) const ...@@ -246,17 +246,17 @@ const ValidateType* Validator::getValidatorForType(std::string typeCode) const
return result; return result;
} }
void Validator::addCategoryValidator(ValidateCategory&& v) void Validator::addCategoryValidator(ValidateCategory &&v)
{ {
auto r = mCategoryValidators.insert(std::move(v)); auto r = mCategoryValidators.insert(std::move(v));
if (not r.second and VERBOSE > 4) if (not r.second and VERBOSE > 4)
std::cout << "Could not add validator for category " << v.mName << std::endl; std::cout << "Could not add validator for category " << v.mName << std::endl;
} }
const ValidateCategory* Validator::getValidatorForCategory(std::string category) const const ValidateCategory *Validator::getValidatorForCategory(std::string_view category) const
{ {
const ValidateCategory* result = nullptr; const ValidateCategory *result = nullptr;
auto i = mCategoryValidators.find(ValidateCategory{category}); auto i = mCategoryValidators.find(ValidateCategory{std::string(category)});
if (i != mCategoryValidators.end()) if (i != mCategoryValidators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -264,16 +264,16 @@ const ValidateCategory* Validator::getValidatorForCategory(std::string category) ...@@ -264,16 +264,16 @@ const ValidateCategory* Validator::getValidatorForCategory(std::string category)
return result; return result;
} }
ValidateItem* Validator::getValidatorForItem(std::string tag) const ValidateItem *Validator::getValidatorForItem(std::string_view tag) const
{ {
ValidateItem* result = nullptr; ValidateItem *result = nullptr;
std::string cat, item; std::string cat, item;
std::tie(cat, item) = splitTagName(tag); std::tie(cat, item) = splitTagName(tag);
auto* cv = getValidatorForCategory(cat); auto *cv = getValidatorForCategory(cat);
if (cv != nullptr) if (cv != nullptr)
result = const_cast<ValidateItem*>(cv->getValidatorForItem(item)); result = const_cast<ValidateItem *>(cv->getValidatorForItem(item));
if (result == nullptr and VERBOSE > 4) if (result == nullptr and VERBOSE > 4)
std::cout << "No validator for item " << tag << std::endl; std::cout << "No validator for item " << tag << std::endl;
...@@ -281,15 +281,15 @@ ValidateItem* Validator::getValidatorForItem(std::string tag) const ...@@ -281,15 +281,15 @@ ValidateItem* Validator::getValidatorForItem(std::string tag) const
return result; return result;
} }
void Validator::addLinkValidator(ValidateLink&& v) void Validator::addLinkValidator(ValidateLink &&v)
{ {
assert(v.mParentKeys.size() == v.mChildKeys.size()); assert(v.mParentKeys.size() == v.mChildKeys.size());
if (v.mParentKeys.size() != v.mChildKeys.size()) if (v.mParentKeys.size() != v.mChildKeys.size())
throw std::runtime_error("unequal number of keys for parent and child in link"); throw std::runtime_error("unequal number of keys for parent and child in link");
auto pcv = getValidatorForCategory(v.mParentCategory); auto pcv = getValidatorForCategory(v.mParentCategory);
auto ccv = getValidatorForCategory(v.mChildCategory); auto ccv = getValidatorForCategory(v.mChildCategory);
if (pcv == nullptr) if (pcv == nullptr)
throw std::runtime_error("unknown parent category " + v.mParentCategory); throw std::runtime_error("unknown parent category " + v.mParentCategory);
...@@ -299,48 +299,48 @@ void Validator::addLinkValidator(ValidateLink&& v) ...@@ -299,48 +299,48 @@ void Validator::addLinkValidator(ValidateLink&& v)
for (size_t i = 0; i < v.mParentKeys.size(); ++i) for (size_t i = 0; i < v.mParentKeys.size(); ++i)
{ {
auto piv = pcv->getValidatorForItem(v.mParentKeys[i]); auto piv = pcv->getValidatorForItem(v.mParentKeys[i]);
if (piv == nullptr) if (piv == nullptr)
throw std::runtime_error("unknown parent tag _" + v.mParentCategory + '.' + v.mParentKeys[i]); throw std::runtime_error("unknown parent tag _" + v.mParentCategory + '.' + v.mParentKeys[i]);
auto civ = ccv->getValidatorForItem(v.mChildKeys[i]); auto civ = ccv->getValidatorForItem(v.mChildKeys[i]);
if (civ == nullptr) if (civ == nullptr)
throw std::runtime_error("unknown child tag _" + v.mChildCategory + '.' + v.mChildKeys[i]); throw std::runtime_error("unknown child tag _" + v.mChildCategory + '.' + v.mChildKeys[i]);
if (civ->mType == nullptr and piv->mType != nullptr) if (civ->mType == nullptr and piv->mType != nullptr)
const_cast<ValidateItem*>(civ)->mType = piv->mType; const_cast<ValidateItem *>(civ)->mType = piv->mType;
} }
mLinkValidators.emplace_back(std::move(v)); mLinkValidators.emplace_back(std::move(v));
} }
std::vector<const ValidateLink*> Validator::getLinksForParent(const std::string& category) const std::vector<const ValidateLink *> Validator::getLinksForParent(std::string_view category) const
{ {
std::vector<const ValidateLink*> result; std::vector<const ValidateLink *> result;
for (auto& l: mLinkValidators) for (auto &l : mLinkValidators)
{ {
if (l.mParentCategory == category) if (l.mParentCategory == category)
result.push_back(&l); result.push_back(&l);
} }
return result; return result;
} }
std::vector<const ValidateLink*> Validator::getLinksForChild(const std::string& category) const std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view category) const
{ {
std::vector<const ValidateLink*> result; std::vector<const ValidateLink *> result;
for (auto& l: mLinkValidators) for (auto &l : mLinkValidators)
{ {
if (l.mChildCategory == category) if (l.mChildCategory == category)
result.push_back(&l); result.push_back(&l);
} }
return result; return result;
} }
void Validator::reportError(const std::string& msg, bool fatal) void Validator::reportError(const std::string &msg, bool fatal)
{ {
if (mStrict or fatal) if (mStrict or fatal)
throw ValidationError(msg); throw ValidationError(msg);
...@@ -348,4 +348,4 @@ void Validator::reportError(const std::string& msg, bool fatal) ...@@ -348,4 +348,4 @@ void Validator::reportError(const std::string& msg, bool fatal)
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
} }
} } // namespace cif
...@@ -1952,6 +1952,58 @@ Atom Structure::getAtomByLabel(const std::string &atomID, const std::string &asy ...@@ -1952,6 +1952,58 @@ Atom Structure::getAtomByLabel(const std::string &atomID, const std::string &asy
throw std::out_of_range("Could not find atom with specified label"); throw std::out_of_range("Could not find atom with specified label");
} }
Atom Structure::getAtomByPosition(Point p) const
{
double distance = std::numeric_limits<double>::max();
size_t index = std::numeric_limits<size_t>::max();
for (size_t i = 0; i < mAtoms.size(); ++i)
{
auto &a = mAtoms.at(i);
auto d = Distance(a.location(), p);
if (d < distance)
{
distance = d;
index = i;
}
}
if (index < mAtoms.size())
return mAtoms.at(index);
return {};
}
Atom Structure::getAtomByPositionAndType(Point p, std::string_view type, std::string_view res_type) const
{
double distance = std::numeric_limits<double>::max();
size_t index = std::numeric_limits<size_t>::max();
for (size_t i = 0; i < mAtoms.size(); ++i)
{
auto &a = mAtoms.at(i);
if (a.labelCompID() != res_type)
continue;
if (a.labelAtomID() != type)
continue;
auto d = Distance(a.location(), p);
if (d < distance)
{
distance = d;
index = i;
}
}
if (index < mAtoms.size())
return mAtoms.at(index);
return {};
}
const Residue &Structure::getResidue(const std::string &asymID, const std::string &compID, int seqID) const const Residue &Structure::getResidue(const std::string &asymID, const std::string &compID, int seqID) const
{ {
for (auto &poly : mPolymers) for (auto &poly : mPolymers)
...@@ -1988,12 +2040,25 @@ const Residue &Structure::getResidue(const std::string &asymID, const std::strin ...@@ -1988,12 +2040,25 @@ const Residue &Structure::getResidue(const std::string &asymID, const std::strin
throw std::out_of_range("Could not find residue " + asymID + '/' + std::to_string(seqID)); throw std::out_of_range("Could not find residue " + asymID + '/' + std::to_string(seqID));
} }
const Residue &Structure::getResidue(const std::string &asymID) const
{
for (auto &res : mNonPolymers)
{
if (res.asymID() != asymID)
continue;
return res;
}
throw std::out_of_range("Could not find residue " + asymID);
}
File &Structure::getFile() const File &Structure::getFile() const
{ {
return mFile; return mFile;
} }
cif::Category &Structure::category(const char *name) const cif::Category &Structure::category(std::string_view name) const
{ {
auto &db = datablock(); auto &db = datablock();
return db[name]; return db[name];
...@@ -2411,8 +2476,15 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound ...@@ -2411,8 +2476,15 @@ void Structure::changeResidue(const Residue &res, const std::string &newCompound
if (r.size() != 1) if (r.size() != 1)
continue; continue;
if (a1 != a2) if (a2.empty() or a2 == ".")
r.front()["label_atom_id"] = a2; atomSites.erase(cif::Key("id") == i->id());
else if (a1 != a2)
{
auto ra = r.front();
ra["label_atom_id"] = a2;
ra["auth_atom_id"] = a2;
ra["type_symbol"] = AtomTypeTraits(compound->getAtomByID(a2).typeSymbol).symbol();
}
} }
for (auto a : atoms) for (auto a : atoms)
......
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