Commit 697028b7 by Maarten L. Hekkelman

- remove mrc usage entirely

- added example as a simple test case
parent c260fccd
......@@ -47,6 +47,8 @@ CLIBD = $(CCP4DIR:%=%/lib/data)
CACHE_DIR = /var/cache/libcifpp
DEFINES += CACHE_DIR='"$(CACHE_DIR)"'
GNUmakefile: config.status GNUmakefile.in
$(SHELL) ./config.status
......@@ -237,32 +239,22 @@ HEADERS = \
Secondary.hpp \
TlsParser.hpp
.PHONY: install-lib
install-lib: lib
.PHONY: install
install: lib
install -d $(libdir)
$(LIBTOOL) --mode=install install $(LIB_TARGET) $(libdir)
rm -f $(libdir)/$(LIB_NAME).so $(libdir)/$(LIB_NAME).a $(libdir)/$(LIB_NAME).la
install -d $(CACHE_DIR)/dictionaries
for d in mmcif_ddl.dic mmcif_pdbx.dic; do \
install -m644 rsrc/dictionaries/$$d $(CACHE_DIR)/dictionaries/$$d; \
install -d $(CACHE_DIR)
for d in isomers.txt dictionaries/mmcif_ddl.dic dictionaries/mmcif_pdbx_v50.dic; do \
install -m644 rsrc/$$d $(CACHE_DIR)/; \
done
if [ -d /etc/cron.weekly ]; then \
install -m755 tools/update-dictionaries-script /etc/cron.weekly/libcifpp; \
fi
.PHONY: install-dev
install-dev:
install -d $(libdir)
$(LIBTOOL) --mode=install install $(LIB_TARGET) $(libdir)
rm -f $(libdir)/$(LIB_NAME).so.$(subst :,.,$(LIB_VERSION)) $(libdir)/$(LIB_NAME).so.$(LIB_CURRENT)
install -d $(includedir)/cif++
for f in $(HEADERS); do install include/cif++/$$f $(includedir)/cif++/$$f; done
install -d $(pkgconfigdir)
install -m 644 $(LIB_NAME).pc $(pkgconfigdir)/$(LIB_NAME).pc
.PHONY: install
install: install-lib install-dev
dist-clean: clean
.PHONY: dist
......
#include <iostream>
#include <filesystem>
#include <cif++/Cif++.hpp>
namespace fs = std::filesystem;
int main()
{
fs::path in("1cbs.cif.gz");
cif::File file;
file.loadDictionary("mmcif_pdbx_v50");
file.load("1cbs.cif.gz");
auto& db = file.firstDatablock()["atom_site"];
auto n = db.find(cif::Key("label_atom_id") == "OXT").size();
std::cout << "File contains " << db.size() << " atoms of which " << n << (n == 1 ? " is" : " are") << " OXT" << std::endl
<< "residues with an OXT are:" << std::endl;
for (const auto& [asym, comp, seqnr]: db.find<std::string,std::string,int>(
cif::Key("label_atom_id") == "OXT",
{ "label_asym_id", "label_comp_id", "label_seq_id" }
))
{
std::cout << asym << ' ' << comp << ' ' << seqnr << std::endl;
}
return 0;
}
CXX = c++ -std=c++17
CXXFLAGS = $(shell pkg-config --cflags libcifpp)
LIBS = $(shell pkg-config --libs libcifpp)
all: example
example: example.cpp
$(CXX) -o $@ $? $(CXXFLAGS) $(LIBS)
......@@ -36,21 +36,6 @@
#include <unistd.h>
struct rsrc_imp
{
unsigned int m_next;
unsigned int m_child;
unsigned int m_name;
unsigned int m_size;
unsigned int m_data;
};
#if USE_RSRC
extern const rsrc_imp gResourceIndex[];
extern const char gResourceData[];
extern const char gResourceName[];
#endif
namespace cif
{
......@@ -205,91 +190,6 @@ class Progress
struct ProgressImpl* mImpl;
};
// --------------------------------------------------------------------
// The new default is to load 'resource' files from the file system
// since not everyone likes mrc. But if you do want to use mrc to load
// resources, specify the compile time flag USE_RSRC.
/// \brief Simple class containing the data for a resource
class rsrc
{
public:
rsrc()
: m_data(nullptr), m_size(0) {}
rsrc(const char* data, size_t size)
: m_data(data), m_size(size) {}
rsrc(const rsrc& rhs)
: m_data(rhs.m_data), m_size(rhs.m_size) {}
rsrc& operator=(const rsrc& rhs)
{
m_data = rhs.m_data;
m_size = rhs.m_size;
return *this;
}
explicit operator bool()
{
return m_data != nullptr and m_size > 0;
}
const char* data() const { return m_data; }
size_t size() const { return m_size; }
private:
const char* m_data;
size_t m_size;
};
/// \brief loader types
enum class rsrc_loader_type { mrsrc, file };
/// \brief loader info
struct rsrc_loader_info
{
rsrc_loader_type type;
std::string info;
const void* ptrs[3];
};
class rsrc_loader
{
public:
static void init(std::initializer_list<rsrc_loader_info> loaders =
{
{ rsrc_loader_type::file, "." },
#if USE_RSRC
{ rsrc_loader_type::mrsrc, "", { gResourceIndex, gResourceData, gResourceName } }
#endif
})
{
assert(not s_instance);
s_instance.reset(new rsrc_loader(loaders));
}
static rsrc load(const std::string& name)
{
assert(s_instance);
if (not s_instance)
init();
return s_instance->do_load(name);
}
~rsrc_loader();
private:
rsrc_loader(const std::initializer_list<rsrc_loader_info>& loaders);
rsrc do_load(const std::string& name);
static std::unique_ptr<rsrc_loader> s_instance;
std::list<struct rsrc_loader_impl*> m_loaders;
};
}
......@@ -6,5 +6,5 @@ includedir=@includedir@
Name: libcifpp
Description: C++ library for the manipulation of mmCIF files.
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lcif++
Libs: -L${libdir} -lcifpp
Cflags: -I${includedir}
......@@ -1686,7 +1686,7 @@ auto Category::erase(iterator pos) -> iterator
}
// links are created based on the _pdbx_item_linked_group_list entries
// in mmcif_pdbx.dic dictionary.
// in mmcif_pdbx_v50.dic dictionary.
//
// For each link group in _pdbx_item_linked_group_list
// a std::set of keys from one category is mapped to another.
......@@ -3107,34 +3107,19 @@ void File::loadDictionary(const char* dict)
}
}
catch (...) {}
fs::path dictFile = std::string("dictionaries/") + dict + ".dic";
try
{
if (fs::exists(dictFile))
{
std::ifstream is(dictFile);
loadDictionary(is);
break;
}
}
catch (...) {}
fs::path datadir = CACHE_DIR;
auto dictData = rsrc_loader::load(dictFile.string());
if (not fs::is_directory(datadir))
throw std::runtime_error("Could not find dictionary " + name.string() + " and " CACHE_DIR " also does not exist");
if (dictData)
name = datadir / name;
if (not fs::exists(name) and name.extension().string() != ".dic")
name = datadir / (name.string() + ".dic");
if (fs::exists(name))
{
struct membuf : public std::streambuf
{
membuf(char* dict, size_t length)
{
this->setg(dict, dict, dict + length);
}
} buffer(const_cast<char*>(dictData.data()), dictData.size());
std::istream is(&buffer);
std::ifstream is(name);
loadDictionary(is);
break;
}
......
......@@ -54,6 +54,8 @@
namespace ba = boost::algorithm;
namespace fs = std::filesystem;
// --------------------------------------------------------------------
namespace cif
{
......@@ -745,173 +747,4 @@ void Progress::message(const std::string& inMessage)
}
}
// --------------------------------------------------------------------
std::unique_ptr<rsrc_loader> rsrc_loader::s_instance;
struct rsrc_loader_impl
{
virtual ~rsrc_loader_impl() {}
virtual rsrc load(const std::string& path) const = 0;
};
class rsrc_not_found_exception : public std::exception
{
public:
virtual const char* what() const throw() { return "resource not found"; }
};
struct mrsrc_rsrc_loader_impl : public rsrc_loader_impl
{
mrsrc_rsrc_loader_impl(const rsrc_loader_info& info);
virtual rsrc load(const std::string& path) const;
const rsrc_imp* m_index;
const char* m_data;
const char* m_name;
};
mrsrc_rsrc_loader_impl::mrsrc_rsrc_loader_impl(const rsrc_loader_info& info)
{
m_index = static_cast<const rsrc_imp*>(info.ptrs[0]);
m_data = reinterpret_cast<const char*>(info.ptrs[1]);
m_name = reinterpret_cast<const char*>(info.ptrs[2]);
}
rsrc mrsrc_rsrc_loader_impl::load(const std::string& path) const
{
auto node = m_index;
std::string p(path);
while (not p.empty())
{
if (node->m_child == 0) // no children, this is an error
return {};
node = m_index + node->m_child;
std::string::size_type s = p.find('/');
std::string name;
if (s != std::string::npos)
{
name = p.substr(0, s);
p.erase(0, s + 1);
}
else
std::swap(name, p);
while (name != m_name + node->m_name)
{
if (node->m_next == 0)
return {};
node = m_index + node->m_next;
}
}
return { m_data + node->m_data, node->m_size };
}
struct mrsrc_file_loader_impl : public rsrc_loader_impl
{
mrsrc_file_loader_impl(const rsrc_loader_info& info);
virtual rsrc load(const std::string& path) const;
fs::path m_rsrc_dir;
mutable std::mutex m_mutex;
mutable std::map<fs::path,std::string> m_cache;
};
mrsrc_file_loader_impl::mrsrc_file_loader_impl(const rsrc_loader_info& info)
: m_rsrc_dir(info.info)
{
if (not fs::is_directory(m_rsrc_dir))
{
std::cerr << "The directory " << info.info << " does not exist" << std::endl
<< "Loading dictionaries will most likely fail" << std::endl;
}
}
rsrc mrsrc_file_loader_impl::load(const std::string& path) const
{
std::unique_lock lock(m_mutex);
fs::path p = m_rsrc_dir / path;
if (fs::exists(p))
{
auto i = m_cache.find(p);
if (i == m_cache.end())
{
std::ostringstream s;
std::ifstream f(p);
if (not f.is_open())
throw std::runtime_error("Could not open " + p.string());
std::string line;
while (std::getline(f, line))
s << line << std::endl;
std::string data = s.str();
std::tie(i, std::ignore) = m_cache.emplace(p, data);
}
return { i->second.c_str(), i->second.length() };
}
return {};
}
rsrc_loader::rsrc_loader(const std::initializer_list<rsrc_loader_info>& loaders)
{
for (auto& l: loaders)
{
try
{
switch (l.type)
{
case rsrc_loader_type::file:
m_loaders.push_back(new mrsrc_file_loader_impl(l));
break;
case rsrc_loader_type::mrsrc:
m_loaders.push_back(new mrsrc_rsrc_loader_impl(l));
break;
default:
break;
}
}
catch (const std::exception& e)
{
if (VERBOSE)
std::cerr << e.what() << std::endl;
}
}
}
rsrc_loader::~rsrc_loader()
{
for (auto l: m_loaders)
delete l;
}
rsrc rsrc_loader::do_load(const std::string& name)
{
rsrc result;
for (auto loader: m_loaders)
{
result = loader->load(name);
if (result)
break;
}
return result;
}
}
......@@ -33,6 +33,7 @@
#include <boost/algorithm/string.hpp>
#include <filesystem>
#include <fstream>
#include "cif++/Cif++.hpp"
#include "cif++/Point.hpp"
......@@ -103,36 +104,24 @@ class IsomerDB
IsomerDB::IsomerDB()
{
auto isomers = cif::rsrc_loader::load("isomers.txt");
if (not isomers)
throw std::runtime_error("Missing isomers.txt resource");
struct membuf : public std::streambuf
{
membuf(char* data, size_t length) { this->setg(data, data, data + length); }
} buffer(const_cast<char*>(isomers.data()), isomers.size());
std::istream is(&buffer);
// #else
// cerr << "resource support was not compiled in, falling back to a local file" << endl;
// fs::path isomersFile = "isomers.txt";
// if (not fs::exists(isomersFile))
// isomersFile = fs::path(cif::get_executable_path()).parent_path() / "isomers.txt";
fs::path isomersFile = fs::path(CACHE_DIR) / "isomers.txt";
// fs::ifstream is(isomersFile);
// if (not is.is_open())
// throw std::runtime_error("Could not open the file isomers.txt");
// #endif
if (not fs::exists(isomersFile))
std::cerr << "Could not locate isomers.txt in " CACHE_DIR << std::endl;
else
{
std::ifstream is(isomersFile);
std::string line;
std::string line;
while (std::getline(is, line))
{
IsomerSet compounds;
ba::split(compounds.compounds, line, ba::is_any_of(":"));
while (std::getline(is, line))
{
IsomerSet compounds;
ba::split(compounds.compounds, line, ba::is_any_of(":"));
if (not compounds.compounds.empty())
mData.isomers.emplace_back(std::move(compounds));
if (not compounds.compounds.empty())
mData.isomers.emplace_back(std::move(compounds));
}
}
}
......
......@@ -6038,7 +6038,7 @@ void ReadPDBFile(std::istream& pdbFile, cif::File& cifFile)
{
PDBFileParser p;
cifFile.loadDictionary("mmcif_pdbx");
cifFile.loadDictionary("mmcif_pdbx_v50");
p.Parse(pdbFile, cifFile);
......
......@@ -138,7 +138,7 @@ void FileImpl::load(const std::string& p)
// And validate, otherwise lots of functionality won't work
// if (mData.getValidator() == nullptr)
mData.loadDictionary("mmcif_pdbx");
mData.loadDictionary("mmcif_pdbx_v50");
if (not mData.isValid())
std::cerr << "Invalid mmCIF file" << (cif::VERBOSE ? "." : " use --verbose option to see errors") << std::endl;
}
......
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