Commit 1f6b86d5 by Maarten L. Hekkelman

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

parents 31499b97 7f39d401
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <regex> #include <regex>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <shared_mutex>
#include "cif++/CifUtils.hpp" #include "cif++/CifUtils.hpp"
...@@ -142,13 +143,13 @@ class Item ...@@ -142,13 +143,13 @@ class Item
Item() {} Item() {}
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0> template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
Item(const std::string &name, const T &value) Item(const std::string_view name, const T &value)
: mName(name) : mName(name)
, mValue(std::to_string(value)) , mValue(std::to_string(value))
{ {
} }
Item(const std::string &name, const std::string &value) Item(const std::string_view name, const std::string_view value)
: mName(name) : mName(name)
, mValue(value) , mValue(value)
{ {
...@@ -221,7 +222,7 @@ class Datablock ...@@ -221,7 +222,7 @@ class Datablock
using iterator = CategoryList::iterator; using iterator = CategoryList::iterator;
using const_iterator = CategoryList::const_iterator; using const_iterator = CategoryList::const_iterator;
Datablock(const std::string &name); Datablock(const std::string_view name);
~Datablock(); ~Datablock();
Datablock(const Datablock &) = delete; Datablock(const Datablock &) = delete;
...@@ -230,8 +231,6 @@ class Datablock ...@@ -230,8 +231,6 @@ class Datablock
std::string getName() const { return mName; } std::string getName() const { return mName; }
void setName(const std::string &n) { mName = n; } void setName(const std::string &n) { mName = n; }
std::string firstItem(const std::string &tag) const;
iterator begin() { return mCategories.begin(); } iterator begin() { return mCategories.begin(); }
iterator end() { return mCategories.end(); } iterator end() { return mCategories.end(); }
...@@ -245,7 +244,7 @@ class Datablock ...@@ -245,7 +244,7 @@ class Datablock
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
void setValidator(Validator *v); void setValidator(const 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(std::string_view name) const; const Category *get(std::string_view name) const;
...@@ -256,7 +255,7 @@ class Datablock ...@@ -256,7 +255,7 @@ class Datablock
void write(std::ostream &os); void write(std::ostream &os);
// convenience function, add a line to the software category // convenience function, add a line to the software category
void add_software(const std::string &name, const std::string &classification, void add_software(const std::string_view name, const std::string &classification,
const std::string &versionNr, const std::string &versionDate); const std::string &versionNr, const std::string &versionDate);
friend bool operator==(const Datablock &lhs, const Datablock &rhs); friend bool operator==(const Datablock &lhs, const Datablock &rhs);
...@@ -264,9 +263,10 @@ class Datablock ...@@ -264,9 +263,10 @@ class Datablock
friend std::ostream& operator<<(std::ostream &os, const Datablock &data); friend std::ostream& operator<<(std::ostream &os, const Datablock &data);
private: private:
std::list<Category> mCategories; CategoryList mCategories; // LRU
mutable std::shared_mutex mLock;
std::string mName; std::string mName;
Validator *mValidator; const Validator *mValidator;
Datablock *mNext; Datablock *mNext;
}; };
...@@ -1816,12 +1816,12 @@ class Category ...@@ -1816,12 +1816,12 @@ class Category
friend class Row; friend class Row;
friend class detail::ItemReference; friend class detail::ItemReference;
Category(Datablock &db, const std::string &name, Validator *Validator); Category(Datablock &db, const std::string_view name, const Validator *Validator);
Category(const Category &) = delete; Category(const Category &) = delete;
Category &operator=(const Category &) = delete; Category &operator=(const Category &) = delete;
~Category(); ~Category();
const std::string name() const { return mName; } const std::string &name() const { return mName; }
using iterator = iterator_impl<Row>; using iterator = iterator_impl<Row>;
using const_iterator = iterator_impl<const Row>; using const_iterator = iterator_impl<const Row>;
...@@ -2064,7 +2064,7 @@ class Category ...@@ -2064,7 +2064,7 @@ class Category
Datablock &db() { return mDb; } Datablock &db() { return mDb; }
void setValidator(Validator *v); void setValidator(const Validator *v);
iset fields() const; iset fields() const;
iset mandatoryFields() const; iset mandatoryFields() const;
...@@ -2121,14 +2121,24 @@ class Category ...@@ -2121,14 +2121,24 @@ class Category
size_t addColumn(std::string_view name); size_t addColumn(std::string_view name);
struct Linked
{
Category *linked;
const ValidateLink *v;
};
void updateLinks();
Datablock &mDb; Datablock &mDb;
std::string mName; std::string mName;
Validator *mValidator; const Validator *mValidator;
const ValidateCategory *mCatValidator = nullptr; const ValidateCategory *mCatValidator = nullptr;
std::vector<ItemColumn> mColumns; std::vector<ItemColumn> mColumns;
ItemRow *mHead; ItemRow *mHead;
ItemRow *mTail; ItemRow *mTail;
class CatIndex *mIndex; class CatIndex *mIndex;
std::vector<Linked> mParentLinks, mChildLinks;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -2162,7 +2172,8 @@ class File ...@@ -2162,7 +2172,8 @@ class File
void loadDictionary(); // load the default dictionary, that is mmcifDdl in this case void loadDictionary(); // load the default dictionary, that is mmcifDdl in this case
void loadDictionary(const char *dict); // load one of the compiled in dictionaries void loadDictionary(const char *dict); // load one of the compiled in dictionaries
void loadDictionary(std::istream &is); // load dictionary from input stream
void setValidator(const Validator *v);
bool isValid(); bool isValid();
void validateLinks() const; void validateLinks() const;
...@@ -2226,10 +2237,8 @@ class File ...@@ -2226,10 +2237,8 @@ class File
void getTagOrder(std::vector<std::string> &tags) const; void getTagOrder(std::vector<std::string> &tags) const;
private: private:
void setValidator(Validator *v);
Datablock *mHead; Datablock *mHead;
Validator *mValidator; const Validator *mValidator;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include <stack>
#include <map> #include <map>
#include <stack>
namespace cif namespace cif
{ {
...@@ -39,7 +39,7 @@ namespace cif ...@@ -39,7 +39,7 @@ namespace cif
class CifParserError : public std::runtime_error class CifParserError : public std::runtime_error
{ {
public: public:
CifParserError(uint32_t lineNr, const std::string& message); CifParserError(uint32_t lineNr, const std::string &message);
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -48,7 +48,8 @@ extern const uint32_t kMaxLineLength; ...@@ -48,7 +48,8 @@ extern const uint32_t kMaxLineLength;
extern const uint8_t kCharTraitsTable[128]; extern const uint8_t kCharTraitsTable[128];
enum CharTraitsMask: uint8_t { enum CharTraitsMask : uint8_t
{
kOrdinaryMask = 1 << 0, kOrdinaryMask = 1 << 0,
kNonBlankMask = 1 << 1, kNonBlankMask = 1 << 1,
kTextLeadMask = 1 << 2, kTextLeadMask = 1 << 2,
...@@ -75,13 +76,13 @@ inline bool isTextLead(int ch) ...@@ -75,13 +76,13 @@ inline bool isTextLead(int ch)
return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0; return ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kTextLeadMask) != 0;
} }
inline bool isAnyPrint(int ch) inline bool isAnyPrint(int ch)
{ {
return ch == '\t' or return ch == '\t' or
(ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0); (ch >= 0x20 and ch <= 0x7f and (kCharTraitsTable[ch - 0x20] & kAnyPrintMask) != 0);
} }
inline bool isUnquotedString(const char* s) inline bool isUnquotedString(const char *s)
{ {
bool result = isOrdinary(*s++); bool result = isOrdinary(*s++);
while (result and *s != 0) while (result and *s != 0)
...@@ -94,7 +95,7 @@ inline bool isUnquotedString(const char* s) ...@@ -94,7 +95,7 @@ inline bool isUnquotedString(const char* s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
using DatablockIndex = std::map<std::string,std::size_t>; using DatablockIndex = std::map<std::string, std::size_t>;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// sac Parser, analogous to SAX Parser (simple api for xml) // sac Parser, analogous to SAX Parser (simple api for xml)
...@@ -102,15 +103,15 @@ using DatablockIndex = std::map<std::string,std::size_t>; ...@@ -102,15 +103,15 @@ using DatablockIndex = std::map<std::string,std::size_t>;
class SacParser class SacParser
{ {
public: public:
SacParser(std::istream& is, bool init = true); SacParser(std::istream &is, bool init = true);
virtual ~SacParser() {} virtual ~SacParser() {}
enum CIFToken enum CIFToken
{ {
eCIFTokenUnknown, eCIFTokenUnknown,
eCIFTokenEOF, eCIFTokenEOF,
eCIFTokenDATA, eCIFTokenDATA,
eCIFTokenLOOP, eCIFTokenLOOP,
eCIFTokenGLOBAL, eCIFTokenGLOBAL,
...@@ -120,7 +121,7 @@ class SacParser ...@@ -120,7 +121,7 @@ class SacParser
eCIFTokenValue, eCIFTokenValue,
}; };
static const char* kTokenName[]; static const char *kTokenName[];
enum CIFValueType enum CIFValueType
{ {
...@@ -133,40 +134,39 @@ class SacParser ...@@ -133,40 +134,39 @@ class SacParser
eCIFValueUnknown eCIFValueUnknown
}; };
static const char* kValueName[]; static const char *kValueName[];
int getNextChar(); int getNextChar();
void retract(); void retract();
void restart(); void restart();
CIFToken getNextToken(); CIFToken getNextToken();
void match(CIFToken token); void match(CIFToken token);
bool parseSingleDatablock(const std::string& datablock); bool parseSingleDatablock(const std::string &datablock);
DatablockIndex indexDatablocks(); DatablockIndex indexDatablocks();
bool parseSingleDatablock(const std::string& datablock, const DatablockIndex &index); bool parseSingleDatablock(const std::string &datablock, const DatablockIndex &index);
void parseFile(); void parseFile();
void parseGlobal(); void parseGlobal();
void parseDataBlock(); void parseDataBlock();
virtual void parseSaveFrame(); virtual void parseSaveFrame();
void parseDictionary(); void parseDictionary();
void error(const std::string& msg); void error(const std::string &msg);
// production methods, these are pure virtual here // production methods, these are pure virtual here
virtual void produceDatablock(const std::string& name) = 0; virtual void produceDatablock(const std::string &name) = 0;
virtual void produceCategory(const std::string& name) = 0; virtual void produceCategory(const std::string &name) = 0;
virtual void produceRow() = 0; virtual void produceRow() = 0;
virtual void produceItem(const std::string& category, const std::string& item, const std::string& value) = 0; virtual void produceItem(const std::string &category, const std::string &item, const std::string &value) = 0;
protected: protected:
enum State enum State
{ {
eStateStart, eStateStart,
...@@ -181,21 +181,21 @@ class SacParser ...@@ -181,21 +181,21 @@ class SacParser
eStateTextField, eStateTextField,
eStateFloat = 100, eStateFloat = 100,
eStateInt = 110, eStateInt = 110,
// eStateNumericSuffix = 200, // eStateNumericSuffix = 200,
eStateValue = 300 eStateValue = 300
}; };
std::istream& mData; std::istream &mData;
// Parser state // Parser state
bool mValidate; bool mValidate;
uint32_t mLineNr; uint32_t mLineNr;
bool mBol; bool mBol;
int mState, mStart; int mState, mStart;
CIFToken mLookahead; CIFToken mLookahead;
std::string mTokenValue; std::string mTokenValue;
CIFValueType mTokenType; CIFValueType mTokenType;
std::stack<int> mBuffer; std::stack<int> mBuffer;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -203,18 +203,18 @@ class SacParser ...@@ -203,18 +203,18 @@ class SacParser
class Parser : public SacParser class Parser : public SacParser
{ {
public: public:
Parser(std::istream& is, File& f, bool init = true); Parser(std::istream &is, File &f, bool init = true);
virtual void produceDatablock(const std::string& name); virtual void produceDatablock(const std::string &name);
virtual void produceCategory(const std::string& name); virtual void produceCategory(const std::string &name);
virtual void produceRow(); virtual void produceRow();
virtual void produceItem(const std::string& category, const std::string& item, const std::string& value); virtual void produceItem(const std::string &category, const std::string &item, const std::string &value);
protected: protected:
File& mFile; File &mFile;
Datablock* mDataBlock; Datablock *mDataBlock;
Datablock::iterator mCat; Datablock::iterator mCat;
Row mRow; Row mRow;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -222,23 +222,21 @@ class Parser : public SacParser ...@@ -222,23 +222,21 @@ class Parser : public SacParser
class DictParser : public Parser class DictParser : public Parser
{ {
public: public:
DictParser(Validator &validator, std::istream &is);
DictParser(Validator& validator, std::istream& is);
~DictParser(); ~DictParser();
void loadDictionary(); void loadDictionary();
private:
private:
virtual void parseSaveFrame(); virtual void parseSaveFrame();
bool collectItemTypes(); bool collectItemTypes();
void linkItems(); void linkItems();
Validator& mValidator; Validator &mValidator;
File mFile; File mFile;
struct DictParserDataImpl* mImpl; struct DictParserDataImpl *mImpl;
bool mCollectedItemTypes = false; bool mCollectedItemTypes = false;
}; };
} } // namespace cif
...@@ -67,9 +67,7 @@ std::string get_version_nr(); ...@@ -67,9 +67,7 @@ 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(std::string_view a, std::string_view 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); 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);
......
...@@ -38,6 +38,7 @@ namespace cif ...@@ -38,6 +38,7 @@ namespace cif
{ {
struct ValidateCategory; struct ValidateCategory;
class ValidatorFactory;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -154,9 +155,8 @@ struct ValidateLink ...@@ -154,9 +155,8 @@ struct ValidateLink
class Validator class Validator
{ {
public: public:
friend class DictParser;
Validator(); Validator(std::string_view name, std::istream &is);
~Validator(); ~Validator();
Validator(const Validator &rhs) = delete; Validator(const Validator &rhs) = delete;
...@@ -165,6 +165,9 @@ class Validator ...@@ -165,6 +165,9 @@ class Validator
Validator(Validator &&rhs); Validator(Validator &&rhs);
Validator &operator=(Validator &&rhs); Validator &operator=(Validator &&rhs);
friend class DictParser;
friend class ValidatorFactory;
void addTypeValidator(ValidateType &&v); void addTypeValidator(ValidateType &&v);
const ValidateType *getValidatorForType(std::string_view typeCode) const; const ValidateType *getValidatorForType(std::string_view typeCode) const;
...@@ -175,7 +178,7 @@ class Validator ...@@ -175,7 +178,7 @@ class Validator
std::vector<const ValidateLink *> getLinksForParent(std::string_view category) const; std::vector<const ValidateLink *> getLinksForParent(std::string_view category) const;
std::vector<const ValidateLink *> getLinksForChild(std::string_view category) const; std::vector<const ValidateLink *> getLinksForChild(std::string_view category) const;
void reportError(const std::string &msg, bool fatal); void reportError(const std::string &msg, bool fatal) const;
std::string dictName() const { return mName; } std::string dictName() const { return mName; }
void dictName(const std::string &name) { mName = name; } void dictName(const std::string &name) { mName = name; }
...@@ -184,6 +187,7 @@ class Validator ...@@ -184,6 +187,7 @@ class Validator
void dictVersion(const std::string &version) { mVersion = version; } void dictVersion(const std::string &version) { mVersion = version; }
private: private:
// name is fully qualified here: // name is fully qualified here:
ValidateItem *getValidatorForItem(std::string_view name) const; ValidateItem *getValidatorForItem(std::string_view name) const;
...@@ -196,4 +200,27 @@ class Validator ...@@ -196,4 +200,27 @@ class Validator
std::vector<ValidateLink> mLinkValidators; std::vector<ValidateLink> mLinkValidators;
}; };
// --------------------------------------------------------------------
class ValidatorFactory
{
public:
static ValidatorFactory &instance()
{
return sInstance;
}
const Validator &operator[](std::string_view dictionary);
private:
static ValidatorFactory sInstance;
ValidatorFactory();
std::mutex mMutex;
std::list<Validator> mValidators;
};
} // namespace cif } // namespace cif
...@@ -109,12 +109,12 @@ class Atom ...@@ -109,12 +109,12 @@ class Atom
float occupancy() const; float occupancy() const;
template <typename T> template <typename T>
T property(const std::string &name) const; T property(const std::string_view name) const;
void property(const std::string &name, const std::string &value); void property(const std::string_view name, const std::string &value);
template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0> template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
void property(const std::string &name, const T &value) void property(const std::string_view name, const T &value)
{ {
property(name, std::to_string(value)); property(name, std::to_string(value));
} }
...@@ -404,7 +404,7 @@ class File : public std::enable_shared_from_this<File> ...@@ -404,7 +404,7 @@ class File : public std::enable_shared_from_this<File>
File(const File &) = delete; File(const File &) = delete;
File &operator=(const File &) = delete; File &operator=(const File &) = delete;
cif::Datablock& createDatablock(const std::string &name); cif::Datablock& createDatablock(const std::string_view name);
void load(const std::filesystem::path &path); void load(const std::filesystem::path &path);
void save(const std::filesystem::path &path); void save(const std::filesystem::path &path);
......
...@@ -37,6 +37,11 @@ namespace mmcif ...@@ -37,6 +37,11 @@ namespace mmcif
// -------------------------------------------------------------------- // --------------------------------------------------------------------
enum class SpacegroupName
{
full, xHM, Hall
};
struct Spacegroup struct Spacegroup
{ {
const char* name; const char* name;
...@@ -133,6 +138,7 @@ CIFPP_EXPORT extern const std::size_t kSymopNrTableSize; ...@@ -133,6 +138,7 @@ CIFPP_EXPORT extern const std::size_t kSymopNrTableSize;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code int GetSpacegroupNumber(std::string spacegroup); // alternative for clipper's parsing code, using SpacegroupName::full
int GetSpacegroupNumber(std::string spacegroup, SpacegroupName type); // alternative for clipper's parsing code
} }
...@@ -123,19 +123,12 @@ const uint8_t kCharToLowerMap[256] = ...@@ -123,19 +123,12 @@ const uint8_t kCharToLowerMap[256] =
// -------------------------------------------------------------------- // --------------------------------------------------------------------
bool iequals(const std::string &a, const std::string &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(std::string_view a, std::string_view b) bool iequals(std::string_view a, std::string_view b)
{ {
bool result = a.length() == b.length(); 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) for (auto ai = a.begin(), bi = b.begin(); result and ai != a.end(); ++ai, ++bi)
result = tolower(*ai) == tolower(*bi); result = kCharToLowerMap[uint8_t(*ai)] == kCharToLowerMap[uint8_t(*bi)];
// result = tolower(*ai) == tolower(*bi);
return result; return result;
} }
...@@ -148,25 +141,6 @@ bool iequals(const char *a, const char *b) ...@@ -148,25 +141,6 @@ bool iequals(const char *a, const char *b)
return result and *a == *b; return result and *a == *b;
} }
int icompare(const std::string &a, const std::string &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(std::string_view a, std::string_view b) int icompare(std::string_view a, std::string_view b)
{ {
int d = 0; int d = 0;
......
...@@ -24,13 +24,20 @@ ...@@ -24,13 +24,20 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <fstream>
#include <filesystem>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include "cif++/CifParser.hpp" #include "cif++/CifParser.hpp"
#include "cif++/CifValidator.hpp" #include "cif++/CifValidator.hpp"
namespace ba = boost::algorithm; namespace ba = boost::algorithm;
namespace fs = std::filesystem;
namespace io = boost::iostreams;
extern int VERBOSE; extern int VERBOSE;
...@@ -219,8 +226,11 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag) ...@@ -219,8 +226,11 @@ const ValidateItem *ValidateCategory::getValidatorForItem(std::string_view tag)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
Validator::Validator() Validator::Validator(std::string_view name, std::istream &is)
: mName(name)
{ {
DictParser p(*this, is);
p.loadDictionary();
} }
Validator::~Validator() Validator::~Validator()
...@@ -340,7 +350,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c ...@@ -340,7 +350,7 @@ std::vector<const ValidateLink *> Validator::getLinksForChild(std::string_view c
return result; return result;
} }
void Validator::reportError(const std::string &msg, bool fatal) void Validator::reportError(const std::string &msg, bool fatal) const
{ {
if (mStrict or fatal) if (mStrict or fatal)
throw ValidationError(msg); throw ValidationError(msg);
...@@ -348,4 +358,78 @@ void Validator::reportError(const std::string &msg, bool fatal) ...@@ -348,4 +358,78 @@ void Validator::reportError(const std::string &msg, bool fatal)
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
} }
// --------------------------------------------------------------------
ValidatorFactory ValidatorFactory::sInstance;
ValidatorFactory::ValidatorFactory()
{
}
const Validator &ValidatorFactory::operator[](std::string_view dictionary)
{
std::lock_guard lock(mMutex);
for (auto &validator : mValidators)
{
if (iequals(validator.mName, dictionary))
return validator;
}
// not found, add it
fs::path dict_name(dictionary);
auto data = loadResource(dictionary);
if (not data and dict_name.extension().string() != ".dic")
data = loadResource(dict_name.parent_path() / (dict_name.filename().string() + ".dic"));
if (data)
mValidators.emplace_back(dictionary, *data);
else
{
// might be a compressed dictionary on disk
fs::path p = dictionary;
if (p.extension() == ".dic")
p = p.parent_path() / (p.filename().string() + ".gz");
else
p = p.parent_path() / (p.filename().string() + ".dic.gz");
#if defined(CACHE_DIR) and defined(DATA_DIR)
if (not fs::exists(p))
{
for (const char *dir : {CACHE_DIR, DATA_DIR})
{
auto p2 = fs::path(dir) / p;
if (fs::exists(p2))
{
swap(p, p2);
break;
}
}
}
#endif
if (fs::exists(p))
{
std::ifstream file(p, std::ios::binary);
if (not file.is_open())
throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
io::filtering_stream<io::input> in;
in.push(io::gzip_decompressor());
in.push(file);
mValidators.emplace_back(dictionary, in);
}
else
throw std::runtime_error("Dictionary not found or defined (" + dict_name.string() + ")");
}
assert(iequals(mValidators.back().mName, dictionary));
return mValidators.back();
}
} // namespace cif } // namespace cif
...@@ -468,14 +468,14 @@ Point CenterPoints(std::vector<Point>& Points) ...@@ -468,14 +468,14 @@ Point CenterPoints(std::vector<Point>& Points)
return t; return t;
} }
Point Centroid(std::vector<Point>& Points) Point Centroid(const std::vector<Point>& pts)
{ {
Point result; Point result;
for (Point& pt : Points) for (auto &pt : pts)
result += pt; result += pt;
result /= static_cast<float>(Points.size()); result /= static_cast<float>(pts.size());
return result; return result;
} }
......
...@@ -216,9 +216,9 @@ struct AtomImpl ...@@ -216,9 +216,9 @@ struct AtomImpl
, mLocation(i.mLocation) , mLocation(i.mLocation)
, mRefcount(1) , mRefcount(1)
, mRow(i.mRow) , mRow(i.mRow)
, mCachedRefs(i.mCachedRefs)
, mCompound(i.mCompound) , mCompound(i.mCompound)
, mRadius(i.mRadius) , mRadius(i.mRadius)
, mCachedProperties(i.mCachedProperties)
, mSymmetryCopy(i.mSymmetryCopy) , mSymmetryCopy(i.mSymmetryCopy)
, mClone(true) , mClone(true)
// , mRTop(i.mRTop), mD(i.mD) // , mRTop(i.mRTop), mD(i.mD)
...@@ -270,9 +270,9 @@ struct AtomImpl ...@@ -270,9 +270,9 @@ struct AtomImpl
, mLocation(loc) , mLocation(loc)
, mRefcount(1) , mRefcount(1)
, mRow(impl.mRow) , mRow(impl.mRow)
, mCachedRefs(impl.mCachedRefs)
, mCompound(impl.mCompound) , mCompound(impl.mCompound)
, mRadius(impl.mRadius) , mRadius(impl.mRadius)
, mCachedProperties(impl.mCachedProperties)
, mSymmetryCopy(true) , mSymmetryCopy(true)
, mSymmetryOperator(sym_op) , mSymmetryOperator(sym_op)
{ {
...@@ -317,13 +317,15 @@ struct AtomImpl ...@@ -317,13 +317,15 @@ struct AtomImpl
auto cat = mDb.get("atom_site_anisotrop"); auto cat = mDb.get("atom_site_anisotrop");
if (cat) if (cat)
{ {
auto r = cat->find1(cif::Key("id") == mID); try
if (not r.empty())
{ {
result = true; auto r = cat->find1(cif::Key("id") == mID);
cif::tie(anisou[0], anisou[1], anisou[2], anisou[3], anisou[4], anisou[5]) = 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]"); r.get("U[1][1]", "U[1][2]", "U[1][3]", "U[2][2]", "U[2][3]", "U[3][3]");
result = true;
}
catch(const std::exception& e)
{
} }
} }
...@@ -338,9 +340,9 @@ struct AtomImpl ...@@ -338,9 +340,9 @@ struct AtomImpl
if (not mClone) if (not mClone)
{ {
mRow["Cartn_x"] = p.getX(); property("Cartn_x", std::to_string(p.getX()));
mRow["Cartn_y"] = p.getY(); property("Cartn_y", std::to_string(p.getY()));
mRow["Cartn_z"] = p.getZ(); property("Cartn_z", std::to_string(p.getZ()));
} }
// boost::format kPosFmt("%.3f"); // boost::format kPosFmt("%.3f");
...@@ -382,26 +384,31 @@ struct AtomImpl ...@@ -382,26 +384,31 @@ struct AtomImpl
return mRadius; return mRadius;
} }
const std::string &property(const std::string &name) const const std::string property(const std::string_view name) const
{ {
static std::string kEmptyString; for (auto &&[tag, ref] : mCachedRefs)
auto i = mCachedProperties.find(name);
if (i == mCachedProperties.end())
{ {
auto v = mRow[name]; if (tag == name)
if (v.empty()) return ref.as<std::string>();
return kEmptyString;
return mCachedProperties[name] = v.as<std::string>();
} }
else
return i->second; mCachedRefs.emplace_back(name, mRow[name]);
return std::get<1>(mCachedRefs.back()).as<std::string>();
} }
void property(const std::string &name, const std::string &value) void property(const std::string_view name, const std::string &value)
{ {
mRow[name] = value; for (auto &&[tag, ref] : mCachedRefs)
{
if (tag != name)
continue;
ref = value;
return;
}
mCachedRefs.emplace_back(name, mRow[name]);
std::get<1>(mCachedRefs.back()) = value;
} }
int compare(const AtomImpl &b) const int compare(const AtomImpl &b) const
...@@ -432,9 +439,11 @@ struct AtomImpl ...@@ -432,9 +439,11 @@ struct AtomImpl
Point mLocation; Point mLocation;
int mRefcount; int mRefcount;
cif::Row mRow; cif::Row mRow;
mutable std::vector<std::tuple<std::string,cif::detail::ItemReference>> mCachedRefs;
mutable const Compound *mCompound = nullptr; mutable const Compound *mCompound = nullptr;
float mRadius = std::nanf("4"); float mRadius = std::nanf("4");
mutable std::map<std::string, std::string> mCachedProperties;
bool mSymmetryCopy = false; bool mSymmetryCopy = false;
bool mClone = false; bool mClone = false;
...@@ -533,25 +542,25 @@ const cif::Row Atom::getRowAniso() const ...@@ -533,25 +542,25 @@ const cif::Row Atom::getRowAniso() const
} }
template <> template <>
std::string Atom::property<std::string>(const std::string &name) const std::string Atom::property<std::string>(const std::string_view name) const
{ {
return impl()->property(name); return impl()->property(name);
} }
template <> template <>
int Atom::property<int>(const std::string &name) const int Atom::property<int>(const std::string_view name) const
{ {
auto v = impl()->property(name); auto v = impl()->property(name);
return v.empty() ? 0 : stoi(v); return v.empty() ? 0 : stoi(v);
} }
template <> template <>
float Atom::property<float>(const std::string &name) const float Atom::property<float>(const std::string_view name) const
{ {
return stof(impl()->property(name)); return stof(impl()->property(name));
} }
void Atom::property(const std::string &name, const std::string &value) void Atom::property(const std::string_view name, const std::string &value)
{ {
impl()->property(name, value); impl()->property(name, value);
} }
...@@ -1736,7 +1745,7 @@ File::~File() ...@@ -1736,7 +1745,7 @@ File::~File()
delete mImpl; delete mImpl;
} }
cif::Datablock& File::createDatablock(const std::string &name) cif::Datablock& File::createDatablock(const std::string_view name)
{ {
auto db = new cif::Datablock(name); auto db = new cif::Datablock(name);
...@@ -1807,9 +1816,9 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options) ...@@ -1807,9 +1816,9 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
} }
if (mAtoms.empty()) if (mAtoms.empty())
throw std::runtime_error("No atoms loaded, refuse to continue"); std::cerr << "Warning: no atoms loaded" << std::endl;
else
loadData(); loadData();
} }
void Structure::loadAtomsForModel(StructureOpenOptions options) void Structure::loadAtomsForModel(StructureOpenOptions options)
......
...@@ -90,4 +90,66 @@ int GetSpacegroupNumber(std::string spacegroup) ...@@ -90,4 +90,66 @@ int GetSpacegroupNumber(std::string spacegroup)
return result; return result;
} }
// --------------------------------------------------------------------
int GetSpacegroupNumber(std::string spacegroup, SpacegroupName type)
{
if (spacegroup == "P 21 21 2 A")
spacegroup = "P 21 21 2 (a)";
else if (spacegroup.empty())
throw std::runtime_error("No spacegroup, cannot continue");
int result = 0;
if (type == SpacegroupName::full)
{
const size_t N = kNrOfSpaceGroups;
int32_t L = 0, R = static_cast<int32_t>(N - 1);
while (L <= R)
{
int32_t i = (L + R) / 2;
int d = spacegroup.compare(kSpaceGroups[i].name);
if (d > 0)
L = i + 1;
else if (d < 0)
R = i - 1;
else
{
result = kSpaceGroups[i].nr;
break;
}
}
}
else if (type == SpacegroupName::xHM)
{
for (auto &sg : kSpaceGroups)
{
if (sg.xHM == spacegroup)
{
result = sg.nr;
break;
}
}
}
else
{
for (auto &sg : kSpaceGroups)
{
if (sg.Hall == spacegroup)
{
result = sg.nr;
break;
}
}
}
// not found, see if we can find a match based on xHM name
if (result == 0)
throw std::runtime_error("Spacegroup name " + spacegroup + " was not found in table");
return result;
}
} }
...@@ -18,7 +18,6 @@ int main(int argc, char* argv[]) ...@@ -18,7 +18,6 @@ int main(int argc, char* argv[])
desc.add_options() desc.add_options()
("input,i", po::value<std::string>(), "Input file") ("input,i", po::value<std::string>(), "Input file")
("help,h", "Display help message") ("help,h", "Display help message")
("version", "Print version")
("verbose,v", "Verbose output") ("verbose,v", "Verbose output")
("debug,d", po::value<int>(), "Debug level (for even more verbose output)"); ("debug,d", po::value<int>(), "Debug level (for even more verbose output)");
...@@ -29,12 +28,6 @@ int main(int argc, char* argv[]) ...@@ -29,12 +28,6 @@ int main(int argc, char* argv[])
po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
po::notify(vm); po::notify(vm);
if (vm.count("version"))
{
std::cout << argv[0] << " version " PACKAGE_VERSION << std::endl;
exit(0);
}
if (vm.count("help") or vm.count("input") == 0) if (vm.count("help") or vm.count("input") == 0)
{ {
std::cerr << desc << std::endl; std::cerr << desc << std::endl;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
// #include "cif++/DistanceMap.hpp" // #include "cif++/DistanceMap.hpp"
#include "cif++/Cif++.hpp" #include "cif++/Cif++.hpp"
#include "cif++/BondMap.hpp" #include "cif++/BondMap.hpp"
#include "cif++/CifValidator.hpp"
std::filesystem::path gTestDir = std::filesystem::current_path(); // filled in first test std::filesystem::path gTestDir = std::filesystem::current_path(); // filled in first test
...@@ -259,8 +260,10 @@ save__cat_2.desc ...@@ -259,8 +260,10 @@ save__cat_2.desc
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -387,8 +390,10 @@ save__cat_1.c ...@@ -387,8 +390,10 @@ save__cat_1.c
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -535,8 +540,10 @@ save__cat_2.desc ...@@ -535,8 +540,10 @@ save__cat_2.desc
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -741,8 +748,10 @@ save__cat_2.parent_id3 ...@@ -741,8 +748,10 @@ save__cat_2.parent_id3
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -963,8 +972,10 @@ cat_2 3 cat_2:cat_1:3 ...@@ -963,8 +972,10 @@ cat_2 3 cat_2:cat_1:3
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -1389,9 +1400,10 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3 ...@@ -1389,9 +1400,10 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
} buffer(const_cast<char*>(dict), sizeof(dict) - 1); } buffer(const_cast<char*>(dict), sizeof(dict) - 1);
std::istream is_dict(&buffer); std::istream is_dict(&buffer);
cif::Validator validator("test", is_dict);
cif::File f; cif::File f;
f.loadDictionary(is_dict); f.setValidator(&validator);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
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