Commit 3965840b by Maarten L. Hekkelman

New way of locating resources

parent a88c6f3d
...@@ -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 4.1.1 LANGUAGES CXX) project(cifpp VERSION 4.2.0 LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
......
Version 4.2.0
- Yet another rewrite of resource loading
Version 4.1.1 Version 4.1.1
- Fall back to zero charge for scattering factors if the atom - Fall back to zero charge for scattering factors if the atom
was not found in the table. was not found in the table.
......
...@@ -1199,92 +1199,97 @@ namespace cif ...@@ -1199,92 +1199,97 @@ namespace cif
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::map<std::string,std::filesystem::path> gLocalResources; class ResourcePool
std::filesystem::path gDataDir;
void addDataDirectory(std::filesystem::path dataDir)
{ {
std::error_code ec; public:
if (fs::exists(dataDir, ec)) static ResourcePool &instance()
gDataDir = dataDir; {
else if (VERBOSE > 0) static std::unique_ptr<ResourcePool> sInstance(new ResourcePool);
std::cerr << "The specified data directory " << dataDir << " cannot be used: " << ec.message() << std::endl; return *sInstance;
} }
void addFileResource(const std::string &name, std::filesystem::path dataFile) void pushDir(fs::path dir)
{ {
std::error_code ec; std::error_code ec;
if (not fs::exists(dataFile, ec) or ec)
throw std::runtime_error("Attempt to add a file resource for " + name + " that cannot be used (" + dataFile.string() + ") :" + ec.message());
gLocalResources[name] = dataFile; if (fs::exists(dir, ec) and not ec)
} mDirs.push_front(dir);
}
std::unique_ptr<std::istream> loadResource(std::filesystem::path name) void pushDir(const char *path)
{ {
std::unique_ptr<std::istream> result; if (path != nullptr)
std::error_code ec; pushDir(fs::path(path));
}
fs::path p = name; void pushAlias(const std::string &name, std::filesystem::path dataFile)
{
std::error_code ec;
if (not fs::exists(dataFile, ec) or ec)
throw std::runtime_error("Attempt to add a file resource for " + name + " that cannot be used (" + dataFile.string() + ") :" + ec.message());
mLocalResources[name] = dataFile;
}
std::unique_ptr<std::istream> load(fs::path name);
if (gLocalResources.count(name.string())) private:
ResourcePool();
std::unique_ptr<std::ifstream> open(fs::path &p)
{ {
std::unique_ptr<std::ifstream> result;
try try
{ {
std::unique_ptr<std::ifstream> file(new std::ifstream(gLocalResources[name.string()], std::ios::binary)); if (fs::exists(p))
if (file->is_open()) {
result.reset(file.release()); std::unique_ptr<std::ifstream> file(new std::ifstream(p, std::ios::binary));
if (file->is_open())
result.reset(file.release());
}
} }
catch (...) {} catch (...) {}
}
if (not result and (not fs::exists(p, ec) or ec) and not gDataDir.empty()) return result;
{
auto p2 = gDataDir / p;
if (fs::exists(p2, ec) and not ec)
swap(p, p2);
} }
#if defined(CACHE_DIR) std::map<std::string,std::filesystem::path> mLocalResources;
if (not result and (not fs::exists(p, ec) or ec)) std::deque<fs::path> mDirs;
{ };
auto p2 = fs::path(CACHE_DIR) / p;
if (fs::exists(p2, ec) and not ec) ResourcePool::ResourcePool()
swap(p, p2); {
} pushDir(getenv("LIBCIFPP_DATA_DIR"));
#endif
#if defined(DATA_DIR) #if defined(DATA_DIR)
if (not result and (not fs::exists(p, ec) or ec)) pushDir(DATA_DIR);
{
auto p2 = fs::path(DATA_DIR) / p;
if (fs::exists(p2, ec) and not ec)
swap(p, p2);
}
#endif #endif
#if defined(CCP4) and CCP4 #if defined(CACHE_DIR)
if (not result and (not fs::exists(p, ec) or ec)) pushDir(CACHE_DIR);
{
const char* CCP4_DIR = getenv("CCP4");
if (CCP4_DIR != nullptr and fs::exists(CCP4_DIR, ec) and not ec)
{
auto p2 = fs::path(DATA_DIR) / p;
if (fs::exists(p2))
swap(p, p2);
}
}
#endif #endif
if (not result and fs::exists(p, ec) and not ec) auto ccp4 = getenv("CCP4");
if (ccp4 != nullptr)
pushDir(fs::path(ccp4) / "share" / "libcifpp");
}
std::unique_ptr<std::istream> ResourcePool::load(fs::path name)
{
std::unique_ptr<std::istream> result;
std::error_code ec;
fs::path p = name;
if (mLocalResources.count(name.string()))
result = open(mLocalResources[name.string()]);
for (auto di = mDirs.begin(); not result and di != mDirs.end(); ++di)
{ {
try auto p2 = *di / p;
{ if (fs::exists(p2, ec) and not ec)
std::unique_ptr<std::ifstream> file(new std::ifstream(p, std::ios::binary)); result = open(p2);
if (file->is_open())
result.reset(file.release());
}
catch (...) {}
} }
if (not result and gResourceData) if (not result and gResourceData)
...@@ -1294,7 +1299,24 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name) ...@@ -1294,7 +1299,24 @@ std::unique_ptr<std::istream> loadResource(std::filesystem::path name)
result.reset(new mrsrc::istream(rsrc)); result.reset(new mrsrc::istream(rsrc));
} }
return result; return result;
}
// --------------------------------------------------------------------
void addDataDirectory(std::filesystem::path dataDir)
{
ResourcePool::instance().pushDir(dataDir);
}
void addFileResource(const std::string &name, std::filesystem::path dataFile)
{
ResourcePool::instance().pushAlias(name, dataFile);
}
std::unique_ptr<std::istream> loadResource(std::filesystem::path name)
{
return ResourcePool::instance().load(name);
} }
} // namespace cif } // namespace cif
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