Commit 7c5f1ba8 by Maarten L. Hekkelman

Merge branch 'trunk' into develop

parents e7c34cc1 72fd03a6
[submodule "gxrio"]
path = gxrio
url = https://github.com/mhekkel/gxrio.git
...@@ -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 5.0.2 LANGUAGES CXX) project(cifpp VERSION 5.0.6 LANGUAGES CXX)
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
...@@ -299,18 +299,16 @@ if(CIFPP_DOWNLOAD_CCD) ...@@ -299,18 +299,16 @@ if(CIFPP_DOWNLOAD_CCD)
add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF}) add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF})
endif() endif()
# Installation directories
set(CIFPP_DATA_DIR "${CMAKE_INSTALL_FULL_DATADIR}/libcifpp")
target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}")
if(UNIX) if(UNIX)
set(CIFPP_CACHE_DIR "/var/cache/libcifpp" CACHE STRING "The cache directory to use") set(CIFPP_CACHE_DIR "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/cache/libcifpp")
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}") target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
endif()
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
set(SHARE_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/libcifpp)
set(CIFPP_DATA_DIR "${CMAKE_INSTALL_PREFIX}/${SHARE_INSTALL_DIR}" CACHE STRING "The directory containing the provided data files")
target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}") set(CIFPP_ETC_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
endif()
# Install rules # Install rules
install(TARGETS cifpp install(TARGETS cifpp
...@@ -359,7 +357,7 @@ configure_package_config_file( ...@@ -359,7 +357,7 @@ configure_package_config_file(
${CONFIG_TEMPLATE_FILE} ${CONFIG_TEMPLATE_FILE}
${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR SHARE_INSTALL_DIR PATH_VARS CIFPP_DATA_DIR
) )
install(FILES install(FILES
...@@ -429,11 +427,15 @@ if(ENABLE_TESTING) ...@@ -429,11 +427,15 @@ if(ENABLE_TESTING)
endforeach() endforeach()
endif() endif()
message("Will install in ${CMAKE_INSTALL_PREFIX}")
# Optionally install the update scripts for CCD and dictionary files # Optionally install the update scripts for CCD and dictionary files
if(CIFPP_INSTALL_UPDATE_SCRIPT) if(CIFPP_INSTALL_UPDATE_SCRIPT)
set(CIFPP_CRON_DIR "$ENV{DESTDIR}/etc/cron.weekly") if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(CIFPP_CRON_DIR "${CIFPP_ETC_DIR}/cron.weekly")
elseif(UNIX) # assume all others are like FreeBSD...
set(CIFPP_CRON_DIR "${CIFPP_ETC_DIR}/periodic/weekly")
else()
message(FATAL_ERROR "Don't know where to install the update script")
endif()
configure_file(${PROJECT_SOURCE_DIR}/tools/update-libcifpp-data.in update-libcifpp-data @ONLY) configure_file(${PROJECT_SOURCE_DIR}/tools/update-libcifpp-data.in update-libcifpp-data @ONLY)
install( install(
...@@ -443,15 +445,15 @@ if(CIFPP_INSTALL_UPDATE_SCRIPT) ...@@ -443,15 +445,15 @@ if(CIFPP_INSTALL_UPDATE_SCRIPT)
) )
install(DIRECTORY DESTINATION ${CIFPP_CACHE_DIR}) install(DIRECTORY DESTINATION ${CIFPP_CACHE_DIR})
install(DIRECTORY DESTINATION "$ENV{DESTDIR}/etc/libcifpp/cache-update.d") install(DIRECTORY DESTINATION "${CIFPP_ETC_DIR}/libcifpp/cache-update.d")
# a config to, to make it complete # a config to, to make it complete
if(NOT EXISTS "$ENV{DESTDIR}/etc/libcifpp.conf") if(NOT EXISTS "${CIFPP_ETC_DIR}/libcifpp.conf")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf [[# Uncomment the next line to enable automatic updates file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf [[# Uncomment the next line to enable automatic updates
# update=true # update=true
]]) ]])
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf DESTINATION "$ENV{DESTDIR}/etc") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf DESTINATION "${CIFPP_ETC_DIR}")
install(CODE "message(\"A configuration file has been written to $ENV{DESTDIR}/etc/libcifpp.conf, please edit this file to enable automatic updates\")") install(CODE "message(\"A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")")
endif() endif()
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}") target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
...@@ -462,7 +464,7 @@ set(CPACK_SOURCE_TGZ ON) ...@@ -462,7 +464,7 @@ set(CPACK_SOURCE_TGZ ON)
set(CPACK_SOURCE_TBZ2 OFF) set(CPACK_SOURCE_TBZ2 OFF)
set(CPACK_SOURCE_TXZ OFF) set(CPACK_SOURCE_TXZ OFF)
set(CPACK_SOURCE_TZ OFF) set(CPACK_SOURCE_TZ OFF)
set(CPACK_SOURCE_IGNORE_FILES "/data/components.cif;/build;/.vscode;/.git;/regex") set(CPACK_SOURCE_IGNORE_FILES "/data/components.cif;/build;/.vscode;/.git")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME}) set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
include(CPack) include(CPack)
Version 5.0.6
- Fix file::contains, using iequals
Version 5.0.5
- Fix code to work on 32 bit machines
Version 5.0.4
- Revert removal of CIFPP_SHARE_DIR export
Version 5.0.3
- Fix installation of libcifpp into the correct locations
Version 5.0.2 Version 5.0.2
- Fix export of CISPEP records in PDB format - Fix export of CISPEP records in PDB format
- Better support for exporting package_source - Better support for exporting package_source
......
...@@ -4,12 +4,9 @@ include(CMakeFindDependencyMacro) ...@@ -4,12 +4,9 @@ include(CMakeFindDependencyMacro)
find_dependency(Threads) find_dependency(Threads)
find_dependency(ZLIB REQUIRED) find_dependency(ZLIB REQUIRED)
find_dependency(LibLZMA REQUIRED)
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake") INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
set_and_check(CIFPP_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(CIFPP_SHARE_DIR "@PACKAGE_CIFPP_DATA_DIR@")
set_and_check(CIFPP_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@")
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_SHARE_INSTALL_DIR@")
check_required_components(cifpp) check_required_components(cifpp)
...@@ -38,3 +38,4 @@ ...@@ -38,3 +38,4 @@
#include <cif++/model.hpp> #include <cif++/model.hpp>
#include <cif++/pdb/io.hpp> #include <cif++/pdb/io.hpp>
#include <cif++/gzio.hpp>
\ No newline at end of file
...@@ -57,6 +57,8 @@ namespace detail ...@@ -57,6 +57,8 @@ namespace detail
virtual bool test(row_handle) const = 0; virtual bool test(row_handle) const = 0;
virtual void str(std::ostream &) const = 0; virtual void str(std::ostream &) const = 0;
virtual std::optional<row_handle> single() const { return {}; }; virtual std::optional<row_handle> single() const { return {}; };
virtual bool equals(const condition_impl *rhs) const { return false; }
}; };
struct all_condition_impl : public condition_impl struct all_condition_impl : public condition_impl
...@@ -145,7 +147,6 @@ class condition ...@@ -145,7 +147,6 @@ class condition
} }
private: private:
void optimise(condition_impl *&impl); void optimise(condition_impl *&impl);
condition_impl *m_impl; condition_impl *m_impl;
...@@ -193,9 +194,7 @@ namespace detail ...@@ -193,9 +194,7 @@ namespace detail
bool test(row_handle r) const override bool test(row_handle r) const override
{ {
return m_single_hit.has_value() ? return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value, m_icase) == 0;
*m_single_hit == r :
r[m_item_ix].compare(m_value, m_icase) == 0;
} }
void str(std::ostream &os) const override void str(std::ostream &os) const override
...@@ -208,6 +207,19 @@ namespace detail ...@@ -208,6 +207,19 @@ namespace detail
return m_single_hit; return m_single_hit;
} }
virtual bool equals(const condition_impl *rhs) const override
{
if (typeid(*rhs) == typeid(key_equals_condition_impl))
{
auto ri = static_cast<const key_equals_condition_impl *>(rhs);
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
return m_single_hit == ri->m_single_hit;
else
return m_item_ix == ri->m_item_ix and m_value == ri->m_value;
}
return this == rhs;
}
std::string m_item_tag; std::string m_item_tag;
uint16_t m_item_ix = 0; uint16_t m_item_ix = 0;
bool m_icase = false; bool m_icase = false;
...@@ -244,7 +256,7 @@ namespace detail ...@@ -244,7 +256,7 @@ namespace detail
void str(std::ostream &os) const override void str(std::ostream &os) const override
{ {
os << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL"; os << '(' << m_item_tag << (m_icase ? "^ " : " ") << " == " << m_value << " OR " << m_item_tag << " IS NULL)";
} }
virtual std::optional<row_handle> single() const override virtual std::optional<row_handle> single() const override
...@@ -252,12 +264,25 @@ namespace detail ...@@ -252,12 +264,25 @@ namespace detail
return m_single_hit; return m_single_hit;
} }
virtual bool equals(const condition_impl *rhs) const override
{
if (typeid(*rhs) == typeid(key_equals_or_empty_condition_impl))
{
auto ri = static_cast<const key_equals_or_empty_condition_impl *>(rhs);
if (m_single_hit.has_value() or ri->m_single_hit.has_value())
return m_single_hit == ri->m_single_hit;
else
return m_item_ix == ri->m_item_ix and m_value == ri->m_value;
}
return this == rhs;
}
std::string m_item_tag; std::string m_item_tag;
uint16_t m_item_ix = 0; uint16_t m_item_ix = 0;
std::string m_value; std::string m_value;
bool m_icase = false; bool m_icase = false;
std::optional<row_handle> m_single_hit; std::optional<row_handle> m_single_hit;
}; };
struct key_compare_condition_impl : public condition_impl struct key_compare_condition_impl : public condition_impl
{ {
...@@ -409,29 +434,53 @@ namespace detail ...@@ -409,29 +434,53 @@ namespace detail
// case they make up an indexed tuple. // case they make up an indexed tuple.
struct and_condition_impl : public condition_impl struct and_condition_impl : public condition_impl
{ {
and_condition_impl() = default;
and_condition_impl(condition &&a, condition &&b) and_condition_impl(condition &&a, condition &&b)
{ {
mSub.emplace_back(std::exchange(a.m_impl, nullptr)); if (typeid(*a.m_impl) == typeid(*this))
mSub.emplace_back(std::exchange(b.m_impl, nullptr)); {
and_condition_impl *ai = static_cast<and_condition_impl *>(a.m_impl);
std::swap(m_sub, ai->m_sub);
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
else if (typeid(*b.m_impl) == typeid(*this))
{
and_condition_impl *bi = static_cast<and_condition_impl *>(b.m_impl);
std::swap(m_sub, bi->m_sub);
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
}
else
{
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
} }
~and_condition_impl() ~and_condition_impl()
{ {
for (auto sub : mSub) for (auto sub : m_sub)
delete sub; delete sub;
} }
condition_impl *prepare(const category &c) override; condition_impl *prepare(const category &c) override
{
for (auto &sub : m_sub)
sub = sub->prepare(c);
return this;
}
bool test(row_handle r) const override bool test(row_handle r) const override
{ {
bool result = true; bool result = true;
for (auto sub : mSub) for (auto sub : m_sub)
{ {
if (sub->test(r)) if (sub->test(r))
continue; continue;
result = false; result = false;
break; break;
} }
...@@ -444,7 +493,7 @@ namespace detail ...@@ -444,7 +493,7 @@ namespace detail
os << '('; os << '(';
bool first = true; bool first = true;
for (auto sub : mSub) for (auto sub : m_sub)
{ {
if (first) if (first)
first = false; first = false;
...@@ -461,7 +510,7 @@ namespace detail ...@@ -461,7 +510,7 @@ namespace detail
{ {
std::optional<row_handle> result; std::optional<row_handle> result;
for (auto sub : mSub) for (auto sub : m_sub)
{ {
auto s = sub->single(); auto s = sub->single();
...@@ -470,7 +519,7 @@ namespace detail ...@@ -470,7 +519,7 @@ namespace detail
result = s; result = s;
continue; continue;
} }
if (s == result) if (s == result)
continue; continue;
...@@ -481,56 +530,100 @@ namespace detail ...@@ -481,56 +530,100 @@ namespace detail
return result; return result;
} }
std::vector<condition_impl *> mSub; static condition_impl *combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc);
std::vector<condition_impl *> m_sub;
}; };
struct or_condition_impl : public condition_impl struct or_condition_impl : public condition_impl
{ {
or_condition_impl(condition &&a, condition &&b) or_condition_impl(condition &&a, condition &&b)
: mA(nullptr)
, mB(nullptr)
{ {
std::swap(mA, a.m_impl); if (typeid(*a.m_impl) == typeid(*this))
std::swap(mB, b.m_impl); {
or_condition_impl *ai = static_cast<or_condition_impl *>(a.m_impl);
std::swap(m_sub, ai->m_sub);
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
else if (typeid(*b.m_impl) == typeid(*this))
{
or_condition_impl *bi = static_cast<or_condition_impl *>(b.m_impl);
std::swap(m_sub, bi->m_sub);
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
}
else
{
m_sub.emplace_back(std::exchange(a.m_impl, nullptr));
m_sub.emplace_back(std::exchange(b.m_impl, nullptr));
}
} }
~or_condition_impl() ~or_condition_impl()
{ {
delete mA; for (auto sub : m_sub)
delete mB; delete sub;
} }
condition_impl *prepare(const category &c) override; condition_impl *prepare(const category &c) override;
bool test(row_handle r) const override bool test(row_handle r) const override
{ {
return mA->test(r) or mB->test(r); bool result = false;
for (auto sub : m_sub)
{
if (not sub->test(r))
continue;
result = true;
break;
}
return result;
} }
void str(std::ostream &os) const override void str(std::ostream &os) const override
{ {
bool first = true;
os << '('; os << '(';
mA->str(os); for (auto sub : m_sub)
os << ") OR ("; {
mB->str(os); if (first)
first = false;
else
os << " OR ";
sub->str(os);
}
os << ')'; os << ')';
} }
virtual std::optional<row_handle> single() const override virtual std::optional<row_handle> single() const override
{ {
auto sa = mA->single(); std::optional<row_handle> result;
auto sb = mB->single();
for (auto sub : m_sub)
if (sa.has_value() and sb.has_value() and sa != sb) {
sa.reset(); auto s = sub->single();
else if (not sa.has_value())
sa = sb; if (not result.has_value())
{
result = s;
continue;
}
if (s == result)
continue;
return sa; result.reset();
break;
}
return result;
} }
condition_impl *mA; std::vector<condition_impl *> m_sub;
condition_impl *mB;
}; };
struct not_condition_impl : public condition_impl struct not_condition_impl : public condition_impl
...@@ -569,7 +662,7 @@ namespace detail ...@@ -569,7 +662,7 @@ namespace detail
} // namespace detail } // namespace detail
inline condition operator&&(condition &&a, condition &&b) inline condition operator and(condition &&a, condition &&b)
{ {
if (a.m_impl and b.m_impl) if (a.m_impl and b.m_impl)
return condition(new detail::and_condition_impl(std::move(a), std::move(b))); return condition(new detail::and_condition_impl(std::move(a), std::move(b)));
...@@ -578,12 +671,35 @@ inline condition operator&&(condition &&a, condition &&b) ...@@ -578,12 +671,35 @@ inline condition operator&&(condition &&a, condition &&b)
return condition(std::move(b)); return condition(std::move(b));
} }
inline condition operator||(condition &&a, condition &&b) inline condition operator or(condition &&a, condition &&b)
{ {
if (a.m_impl and b.m_impl) if (a.m_impl and b.m_impl)
{
if (typeid(*a.m_impl) == typeid(detail::key_equals_condition_impl) and
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
{
auto ci = static_cast<detail::key_equals_condition_impl *>(a.m_impl);
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
if (ci->m_item_tag == ce->m_item_tag)
return condition(new detail::key_equals_or_empty_condition_impl(ci));
}
else if (typeid(*b.m_impl) == typeid(detail::key_equals_condition_impl) and
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
{
auto ci = static_cast<detail::key_equals_condition_impl *>(b.m_impl);
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
if (ci->m_item_tag == ce->m_item_tag)
return condition(new detail::key_equals_or_empty_condition_impl(ci));
}
return condition(new detail::or_condition_impl(std::move(a), std::move(b))); return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
}
if (a.m_impl) if (a.m_impl)
return condition(std::move(a)); return condition(std::move(a));
return condition(std::move(b)); return condition(std::move(b));
} }
...@@ -706,7 +822,7 @@ inline condition operator==(const key &key, const empty_type &) ...@@ -706,7 +822,7 @@ inline condition operator==(const key &key, const empty_type &)
return condition(new detail::key_is_empty_condition_impl(key.m_item_tag)); return condition(new detail::key_is_empty_condition_impl(key.m_item_tag));
} }
inline condition operator !(condition &&rhs) inline condition operator not(condition &&rhs)
{ {
return condition(new detail::not_condition_impl(std::move(rhs))); return condition(new detail::not_condition_impl(std::move(rhs)));
} }
......
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
/// whether to use a compressions/decompression algorithm is /// whether to use a compressions/decompression algorithm is
/// based on the extension of the \a filename argument. /// based on the extension of the \a filename argument.
// This is a stripped down version of the gzio library from // This is a stripped down version of the gxrio library from
// https://github.com/mhekkel/gzio.git // https://github.com/mhekkel/gxrio.git
// Most notably, the lzma support has been removed since getting // Most notably, the lzma support has been removed since getting
// that to work in Windows proved to be too much work. // that to work in Windows proved to be too much work.
...@@ -128,15 +128,15 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits> ...@@ -128,15 +128,15 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
std::swap(m_zstream, rhs.m_zstream); std::swap(m_zstream, rhs.m_zstream);
std::swap(m_gzheader, rhs.m_gzheader); std::swap(m_gzheader, rhs.m_gzheader);
auto p = std::copy(rhs.gptr(), rhs.egptr(), m_out_buffer.begin()); auto p = std::copy(rhs.gptr(), rhs.egptr(), m_out_buffer.data());
this->setg(m_out_buffer.data(), m_out_buffer.data() + m_out_buffer.size(), p); this->setg(m_out_buffer.data(), m_out_buffer.data(), p);
if (m_zstream and m_zstream->avail_in > 0) if (m_zstream and m_zstream->avail_in > 0)
{ {
auto next_in_offset = m_zstream->next_in - rhs.m_in_buffer.data(); auto next_in_offset = m_zstream->next_in - rhs.m_in_buffer.data();
std::copy(rhs.m_in_buffer.begin() + next_in_offset, std::copy(rhs.m_in_buffer.data() + next_in_offset,
rhs.m_in_buffer.begin() + next_in_offset + m_zstream->avail_in, rhs.m_in_buffer.data() + next_in_offset + m_zstream->avail_in,
m_in_buffer.begin()); m_in_buffer.data());
m_zstream->next_in = m_in_buffer.data(); m_zstream->next_in = m_in_buffer.data();
} }
} }
...@@ -151,15 +151,15 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits> ...@@ -151,15 +151,15 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
std::swap(m_zstream, rhs.m_zstream); std::swap(m_zstream, rhs.m_zstream);
std::swap(m_gzheader, rhs.m_gzheader); std::swap(m_gzheader, rhs.m_gzheader);
auto p = std::copy(rhs.gptr(), rhs.egptr(), m_out_buffer.begin()); auto p = std::copy(rhs.gptr(), rhs.egptr(), m_out_buffer.data());
this->setg(m_out_buffer.data(), m_out_buffer.data() + m_out_buffer.size(), p); this->setg(m_out_buffer.data(), m_out_buffer.data(), p);
if (m_zstream and m_zstream->avail_in > 0) if (m_zstream and m_zstream->avail_in > 0)
{ {
auto next_in_offset = m_zstream->next_in - reinterpret_cast<unsigned char *>(rhs.m_in_buffer.data()); auto next_in_offset = m_zstream->next_in - reinterpret_cast<unsigned char *>(rhs.m_in_buffer.data());
std::copy(rhs.m_in_buffer.begin() + next_in_offset, std::copy(rhs.m_in_buffer.data() + next_in_offset,
rhs.m_in_buffer.begin() + next_in_offset + m_zstream->avail_in, rhs.m_in_buffer.data() + next_in_offset + m_zstream->avail_in,
m_in_buffer.begin()); m_in_buffer.data());
m_zstream->next_in = reinterpret_cast<unsigned char *>(m_in_buffer.data()); m_zstream->next_in = reinterpret_cast<unsigned char *>(m_in_buffer.data());
} }
......
...@@ -194,6 +194,7 @@ struct item_value ...@@ -194,6 +194,7 @@ struct item_value
/// \brief constructor /// \brief constructor
item_value(std::string_view text) item_value(std::string_view text)
: m_length(text.length()) : m_length(text.length())
, m_storage(0)
{ {
if (m_length >= kBufferSize) if (m_length >= kBufferSize)
{ {
...@@ -210,7 +211,7 @@ struct item_value ...@@ -210,7 +211,7 @@ struct item_value
item_value(item_value &&rhs) item_value(item_value &&rhs)
: m_length(std::exchange(rhs.m_length, 0)) : m_length(std::exchange(rhs.m_length, 0))
, m_data(std::exchange(rhs.m_data, nullptr)) , m_storage(std::exchange(rhs.m_storage, 0))
{ {
} }
...@@ -219,7 +220,7 @@ struct item_value ...@@ -219,7 +220,7 @@ struct item_value
if (this != &rhs) if (this != &rhs)
{ {
m_length = std::exchange(rhs.m_length, m_length); m_length = std::exchange(rhs.m_length, m_length);
m_data = std::exchange(rhs.m_data, m_data); m_storage = std::exchange(rhs.m_storage, m_storage);
} }
return *this; return *this;
} }
...@@ -228,7 +229,7 @@ struct item_value ...@@ -228,7 +229,7 @@ struct item_value
{ {
if (m_length >= kBufferSize) if (m_length >= kBufferSize)
delete[] m_data; delete[] m_data;
m_data = nullptr; m_storage = 0;
m_length = 0; m_length = 0;
} }
...@@ -245,6 +246,7 @@ struct item_value ...@@ -245,6 +246,7 @@ struct item_value
{ {
char m_local_data[8]; char m_local_data[8];
char *m_data; char *m_data;
uint64_t m_storage;
}; };
static constexpr size_t kBufferSize = sizeof(m_local_data); static constexpr size_t kBufferSize = sizeof(m_local_data);
...@@ -257,9 +259,6 @@ struct item_value ...@@ -257,9 +259,6 @@ struct item_value
} }
}; };
// static_assert(sizeof(item_value) == 24, "sizeof(item_value) should be 24 bytes");
static_assert(sizeof(item_value) == 16, "sizeof(item_value) should be 16 bytes");
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Transient object to access stored data // Transient object to access stored data
......
...@@ -101,13 +101,13 @@ class atom ...@@ -101,13 +101,13 @@ class atom
row_handle row_aniso() row_handle row_aniso()
{ {
auto cat = m_db.get("atom_site_anisotrop"); auto cat = m_db.get("atom_site_anisotrop");
return cat ? cat->find1(key("id") == m_id) : row_handle{}; return cat ? cat->operator[]({ {"id", m_id} }) : row_handle{};
} }
const row_handle row_aniso() const const row_handle row_aniso() const
{ {
auto cat = m_db.get("atom_site_anisotrop"); auto cat = m_db.get("atom_site_anisotrop");
return cat ? cat->find1(key("id") == m_id) : row_handle{}; return cat ? cat->operator[]({ {"id", m_id} }) : row_handle{};
} }
const datablock &m_db; const datablock &m_db;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <regex>
#include <cif++/row.hpp> #include <cif++/row.hpp>
...@@ -93,23 +94,23 @@ class sac_parser ...@@ -93,23 +94,23 @@ class sac_parser
static bool is_unquoted_string(std::string_view text) static bool is_unquoted_string(std::string_view text)
{ {
auto s = text.begin(); bool result = is_ordinary(text.front());
bool result = is_ordinary(*s++);
while (result and s != text.end())
{
result = is_non_blank(*s);
++s;
}
// but be careful it does not contain e.g. stop_
if (result) if (result)
{ {
static const std::regex reservedRx(R"((^(?:data|save)|.*(?:loop|stop|global))_.+)", std::regex_constants::icase); for (auto ch : text)
result = not std::regex_match(text.begin(), text.end(), reservedRx); {
if (is_non_blank(ch))
continue;
result = false;
break;
}
} }
return result; static const std::regex kReservedRx(R"(loop_|stop_|global_|data_\S+|save_\S+)", std::regex_constants::icase);
// but be careful it does not contain e.g. stop_
return result and not std::regex_match(text.begin(), text.end(), kReservedRx);
} }
protected: protected:
......
...@@ -8,6 +8,6 @@ Name: libcifpp ...@@ -8,6 +8,6 @@ Name: libcifpp
Description: C++ library for the manipulation of mmCIF files. Description: C++ library for the manipulation of mmCIF files.
Version: @PACKAGE_VERSION@ Version: @PACKAGE_VERSION@
Requires.private: zlib, liblzma Requires.private: zlib
Libs: -L${libdir} -lcifpp Libs: -L${libdir} -lcifpp
Cflags: -I${includedir} -pthread Cflags: -I${includedir} -pthread
...@@ -1142,10 +1142,6 @@ category::iterator category::erase(iterator pos) ...@@ -1142,10 +1142,6 @@ category::iterator category::erase(iterator pos)
row *r = rh.get_row(); row *r = rh.get_row();
iterator result = ++pos; iterator result = ++pos;
iset keys;
if (m_cat_validator)
keys = iset(m_cat_validator->m_keys.begin(), m_cat_validator->m_keys.end());
if (m_head == nullptr) if (m_head == nullptr)
throw std::runtime_error("erase"); throw std::runtime_error("erase");
...@@ -1174,7 +1170,7 @@ category::iterator category::erase(iterator pos) ...@@ -1174,7 +1170,7 @@ category::iterator category::erase(iterator pos)
// in mmcif_pdbx.dic dictionary. // in mmcif_pdbx.dic dictionary.
// //
// For each link group in _pdbx_item_linked_group_list // For each link group in _pdbx_item_linked_group_list
// a std::set of keys from one category is mapped to another. // a set of keys from one category is mapped to another.
// If all values in a child are the same as the specified parent ones // If all values in a child are the same as the specified parent ones
// the child is removed as well, recursively of course. // the child is removed as well, recursively of course.
...@@ -1198,25 +1194,29 @@ category::iterator category::erase(iterator pos) ...@@ -1198,25 +1194,29 @@ category::iterator category::erase(iterator pos)
return result; return result;
} }
size_t category::erase(condition &&cond) template<typename T>
class save_value
{ {
size_t result = 0; public:
save_value(T &v, const T nv = {})
cond.prepare(*this); : m_v(v)
, m_sv(std::exchange(m_v, nv))
{
}
auto ri = begin(); ~save_value()
while (ri != end())
{ {
if (cond(*ri)) m_v = m_sv;
{
ri = erase(ri);
++result;
}
else
++ri;
} }
return result; private:
T &m_v;
const T m_sv;
};
size_t category::erase(condition &&cond)
{
return erase(std::move(cond), {});
} }
size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit) size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
...@@ -1225,12 +1225,26 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit ...@@ -1225,12 +1225,26 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit
cond.prepare(*this); cond.prepare(*this);
std::map<category *, condition> potential_orphans;
auto ri = begin(); auto ri = begin();
while (ri != end()) while (ri != end())
{ {
if (cond(*ri)) if (cond(*ri))
{ {
visit(*ri); if (visit)
visit(*ri);
for (auto &&[childCat, link] : m_child_links)
{
auto cond = get_children_condition(*ri, *childCat);
if (not cond)
continue;
potential_orphans[childCat] = std::move(potential_orphans[childCat]) or std::move(cond);
}
save_value sv(m_validator);
ri = erase(ri); ri = erase(ri);
++result; ++result;
} }
...@@ -1238,6 +1252,9 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit ...@@ -1238,6 +1252,9 @@ size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit
++ri; ++ri;
} }
for (auto &&[childCat, condition] : potential_orphans)
childCat->erase_orphans(std::move(condition), *this);
return result; return result;
} }
......
...@@ -76,53 +76,82 @@ namespace detail ...@@ -76,53 +76,82 @@ namespace detail
return this; return this;
} }
condition_impl *and_condition_impl::prepare(const category &c) bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
{ {
for (auto &sub : mSub) bool result = true;
sub = sub->prepare(c);
for (;;) for (auto s = b; s != e; ++s)
{ {
auto si = find_if(mSub.begin(), mSub.end(), [](condition_impl *sub) { return dynamic_cast<and_condition_impl *>(sub) != nullptr; }); auto &cs = (*s)->m_sub;
if (si == mSub.end())
break;
and_condition_impl *sub_and = static_cast<and_condition_impl *>(*si);
mSub.erase(si);
mSub.insert(mSub.end(), sub_and->mSub.begin(), sub_and->mSub.end()); if (find_if(cs.begin(), cs.end(), [c](const condition_impl *i) { return i->equals(c); }) == cs.end())
sub_and->mSub.clear(); {
delete sub_and; result = false;
break;
}
} }
return this; return result;
} }
condition_impl *or_condition_impl::prepare(const category &c) condition_impl *and_condition_impl::combine_equal(std::vector<and_condition_impl *> &subs, or_condition_impl *oc)
{ {
condition_impl *result = this; and_condition_impl *and_result = nullptr;
mA = mA->prepare(c); auto first = subs.front();
mB = mB->prepare(c); auto &fc = first->m_sub;
key_equals_condition_impl *equals = dynamic_cast<key_equals_condition_impl*>(mA); for (auto c : fc)
key_is_empty_condition_impl *empty = dynamic_cast<key_is_empty_condition_impl*>(mB); {
if (not found_in_range(c, subs.begin() + 1, subs.end()))
continue;
if (and_result == nullptr)
and_result = new and_condition_impl();
and_result->m_sub.push_back(c);
fc.erase(remove(fc.begin(), fc.end(), c), fc.end());
for (auto sub : subs)
{
auto &ssub = sub->m_sub;
for (auto sc : ssub)
{
if (not sc->equals(c))
continue;
ssub.erase(remove(ssub.begin(), ssub.end(), sc), ssub.end());
delete sc;
break;
}
}
}
if (equals == nullptr and empty == nullptr) if (and_result != nullptr)
{ {
equals = dynamic_cast<key_equals_condition_impl*>(mB); and_result->m_sub.push_back(oc);
empty = dynamic_cast<key_is_empty_condition_impl*>(mA); return and_result;
} }
if (equals != nullptr and empty != nullptr and equals->m_item_tag == empty->m_item_tag) return oc;
}
condition_impl *or_condition_impl::prepare(const category &c)
{
std::vector<and_condition_impl *> and_conditions;
for (auto &sub : m_sub)
{ {
result = new detail::key_equals_or_empty_condition_impl(equals); sub = sub->prepare(c);
result = result->prepare(c); if (typeid(*sub) == typeid(and_condition_impl))
delete this; and_conditions.push_back(static_cast<and_condition_impl *>(sub));
} }
return result; if (and_conditions.size() == m_sub.size())
return and_condition_impl::combine_equal(and_conditions, this);
return this;
} }
} // namespace detail } // namespace detail
......
...@@ -125,7 +125,7 @@ void file::load_dictionary(std::string_view name) ...@@ -125,7 +125,7 @@ void file::load_dictionary(std::string_view name)
bool file::contains(std::string_view name) const bool file::contains(std::string_view name) const
{ {
return std::find_if(begin(), end(), [name](const datablock &db) { return db.name() == name; }) != end(); return std::find_if(begin(), end(), [name](const datablock &db) { return iequals(db.name(), name); }) != end();
} }
datablock &file::operator[](std::string_view name) datablock &file::operator[](std::string_view name)
......
...@@ -1688,7 +1688,10 @@ atom &structure::emplace_atom(atom &&atom) ...@@ -1688,7 +1688,10 @@ atom &structure::emplace_atom(atom &&atom)
R = i - 1; R = i - 1;
} }
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size()); if (R == -1) // msvc...
m_atom_index.insert(m_atom_index.begin(), m_atoms.size());
else
m_atom_index.insert(m_atom_index.begin() + R + 1, m_atoms.size());
// make sure the atom_type is known // make sure the atom_type is known
auto &atom_type = m_db["atom_type"]; auto &atom_type = m_db["atom_type"];
......
...@@ -380,18 +380,13 @@ sac_parser::CIFToken sac_parser::get_next_token() ...@@ -380,18 +380,13 @@ sac_parser::CIFToken sac_parser::get_next_token()
{ {
std::string s = to_lower_copy(m_token_value); std::string s = to_lower_copy(m_token_value);
if (s == "global_") if (s == "data_")
result = CIFToken::GLOBAL;
else if (s == "stop_")
result = CIFToken::STOP;
else if (s == "loop_")
result = CIFToken::LOOP;
else if (s == "data_")
{ {
state = State::DATA; state = State::DATA;
continue; continue;
} }
else if (s == "save_")
if (s == "save_")
{ {
state = State::SAVE; state = State::SAVE;
continue; continue;
...@@ -405,6 +400,12 @@ sac_parser::CIFToken sac_parser::get_next_token() ...@@ -405,6 +400,12 @@ sac_parser::CIFToken sac_parser::get_next_token()
if (m_token_value == ".") if (m_token_value == ".")
mTokenType = CIFValue::Inapplicable; mTokenType = CIFValue::Inapplicable;
else if (iequals(m_token_value, "global_"))
result = CIFToken::GLOBAL;
else if (iequals(m_token_value, "stop_"))
result = CIFToken::STOP;
else if (iequals(m_token_value, "loop_"))
result = CIFToken::LOOP;
else if (m_token_value == "?") else if (m_token_value == "?")
{ {
mTokenType = CIFValue::Unknown; mTokenType = CIFValue::Unknown;
...@@ -786,6 +787,9 @@ void sac_parser::parse_save_frame() ...@@ -786,6 +787,9 @@ void sac_parser::parse_save_frame()
void parser::produce_datablock(const std::string &name) void parser::produce_datablock(const std::string &name)
{ {
if (VERBOSE >= 4)
std::cerr << "producing data_" << name << std::endl;
const auto &[iter, ignore] = m_file.emplace(name); const auto &[iter, ignore] = m_file.emplace(name);
m_datablock = &(*iter); m_datablock = &(*iter);
} }
...@@ -801,7 +805,7 @@ void parser::produce_category(const std::string &name) ...@@ -801,7 +805,7 @@ void parser::produce_category(const std::string &name)
void parser::produce_row() void parser::produce_row()
{ {
if (VERBOSE >= 4) if (VERBOSE >= 4 and m_category != nullptr)
std::cerr << "producing row for category " << m_category->name() << std::endl; std::cerr << "producing row for category " << m_category->name() << std::endl;
if (m_category == nullptr) if (m_category == nullptr)
......
...@@ -6102,13 +6102,6 @@ int PDBFileParser::PDBChain::AlignResToSeqRes() ...@@ -6102,13 +6102,6 @@ int PDBFileParser::PDBChain::AlignResToSeqRes()
switch (tb(x, y)) switch (tb(x, y))
{ {
case -1: case -1:
// if (cif::VERBOSE > 0)
// std::cerr << "A residue found in the ATOM records "
// << "(" << ry[y].mMonID << " @ " << mDbref.chainID << ":" << ry[y].mSeqNum
// << ((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) << ")"
// << " was not found in the SEQRES records" << std::endl;
// --y;
throw std::runtime_error("A residue found in the ATOM records (" + ry[y].mMonID + throw std::runtime_error("A residue found in the ATOM records (" + ry[y].mMonID +
" @ " + std::string{ mDbref.chainID } + ":" + std::to_string(ry[y].mSeqNum) + " @ " + std::string{ mDbref.chainID } + ":" + std::to_string(ry[y].mSeqNum) +
((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) + ((ry[y].mIcode == ' ' or ry[y].mIcode == 0) ? "" : std::string{ ry[y].mIcode }) +
...@@ -6123,10 +6116,11 @@ int PDBFileParser::PDBChain::AlignResToSeqRes() ...@@ -6123,10 +6116,11 @@ int PDBFileParser::PDBChain::AlignResToSeqRes()
break; break;
case 0: case 0:
if (cif::VERBOSE > 3 and rx[x].mMonID != ry[y].mMonID) if (rx[x].mMonID != ry[y].mMonID)
std::cerr << "Warning, unaligned residues at " << x << "/" << y << "(" << rx[x].mMonID << '/' << ry[y].mMonID << ')' << std::endl; {
else if (cif::VERBOSE > 4) std::cerr << "Warning, unaligned residues at " << x << "/" << y << "(" << rx[x].mMonID << '/' << ry[y].mMonID << ") SEQRES does not agree with ATOM records" << std::endl;
std::cerr << rx[x].mMonID << " -> " << ry[y].mMonID << " (" << ry[y].mSeqNum << ')' << std::endl; rx[x].mMonID = ry[y].mMonID;
}
rx[x].mSeqNum = ry[y].mSeqNum; rx[x].mSeqNum = ry[y].mSeqNum;
rx[x].mIcode = ry[y].mIcode; rx[x].mIcode = ry[y].mIcode;
...@@ -6211,7 +6205,16 @@ file read(std::istream &is) ...@@ -6211,7 +6205,16 @@ file read(std::istream &is)
if (ch == 'h' or ch == 'H') if (ch == 'h' or ch == 'H')
ReadPDBFile(is, result); ReadPDBFile(is, result);
else else
result.load(is); {
try
{
result.load(is);
}
catch (const std::exception &ex)
{
std::throw_with_nested(std::runtime_error("Since the file did not start with a valid PDB HEADER line mmCIF was assumed, but that failed."));
}
}
} }
// Must be a PDB like file, right? // Must be a PDB like file, right?
......
...@@ -320,7 +320,7 @@ struct tls_selection_not : public tls_selection ...@@ -320,7 +320,7 @@ struct tls_selection_not : public tls_selection
for (auto &r : residues) for (auto &r : residues)
r.selected = not r.selected; r.selected = not r.selected;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "NOT" << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "NOT" << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -339,7 +339,7 @@ struct tls_selection_all : public tls_selection ...@@ -339,7 +339,7 @@ struct tls_selection_all : public tls_selection
for (auto &r : residues) for (auto &r : residues)
r.selected = true; r.selected = true;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "ALL" << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "ALL" << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -361,7 +361,7 @@ struct tls_selection_chain : public tls_selection_all ...@@ -361,7 +361,7 @@ struct tls_selection_chain : public tls_selection_all
for (auto &r : residues) for (auto &r : residues)
r.selected = allChains or r.chainID == m_chain; r.selected = allChains or r.chainID == m_chain;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "CHAIN " << m_chain << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "CHAIN " << m_chain << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -384,7 +384,7 @@ struct tls_selection_res_id : public tls_selection_all ...@@ -384,7 +384,7 @@ struct tls_selection_res_id : public tls_selection_all
for (auto &r : residues) for (auto &r : residues)
r.selected = r.seqNr == m_seq_nr and r.iCode == m_icode; r.selected = r.seqNr == m_seq_nr and r.iCode == m_icode;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "ResID " << m_seq_nr << (m_icode ? std::string{ m_icode } : "") << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "ResID " << m_seq_nr << (m_icode ? std::string{ m_icode } : "") << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -411,7 +411,7 @@ struct tls_selection_range_seq : public tls_selection_all ...@@ -411,7 +411,7 @@ struct tls_selection_range_seq : public tls_selection_all
(r.seqNr <= m_last or m_last == kResidueNrWildcard)); (r.seqNr <= m_last or m_last == kResidueNrWildcard));
} }
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "Range " << m_first << ':' << m_last << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "Range " << m_first << ':' << m_last << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -461,7 +461,7 @@ struct tls_selection_range_id : public tls_selection_all ...@@ -461,7 +461,7 @@ struct tls_selection_range_id : public tls_selection_all
} }
} }
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "Through " << m_first << ':' << m_last << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "Through " << m_first << ':' << m_last << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -502,7 +502,7 @@ struct tls_selection_union : public tls_selection ...@@ -502,7 +502,7 @@ struct tls_selection_union : public tls_selection
for (auto ai = a.begin(), bi = b.begin(), ri = residues.begin(); ri != residues.end(); ++ai, ++bi, ++ri) for (auto ai = a.begin(), bi = b.begin(), ri = residues.begin(); ri != residues.end(); ++ai, ++bi, ++ri)
ri->selected = ai->selected or bi->selected; ri->selected = ai->selected or bi->selected;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "Union" << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "Union" << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -543,7 +543,7 @@ struct tls_selection_intersection : public tls_selection ...@@ -543,7 +543,7 @@ struct tls_selection_intersection : public tls_selection
for (auto ai = a.begin(), bi = b.begin(), ri = residues.begin(); ri != residues.end(); ++ai, ++bi, ++ri) for (auto ai = a.begin(), bi = b.begin(), ri = residues.begin(); ri != residues.end(); ++ai, ++bi, ++ri)
ri->selected = ai->selected and bi->selected; ri->selected = ai->selected and bi->selected;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "Intersection" << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "Intersection" << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -567,7 +567,7 @@ struct tls_selection_by_name : public tls_selection_all ...@@ -567,7 +567,7 @@ struct tls_selection_by_name : public tls_selection_all
for (auto &r : residues) for (auto &r : residues)
r.selected = r.name == m_name; r.selected = r.name == m_name;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "Name " << m_name << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "Name " << m_name << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -595,7 +595,7 @@ struct tls_selection_by_element : public tls_selection_all ...@@ -595,7 +595,7 @@ struct tls_selection_by_element : public tls_selection_all
for (auto &r : residues) for (auto &r : residues)
r.selected = iequals(r.name, m_element); r.selected = iequals(r.name, m_element);
if (cif::VERBOSE) if (cif::VERBOSE > 0)
{ {
std::cout << std::string(indentLevel * 2, ' ') << "Element " << m_element << std::endl; std::cout << std::string(indentLevel * 2, ' ') << "Element " << m_element << std::endl;
dump_selection(residues, indentLevel); dump_selection(residues, indentLevel);
...@@ -1404,7 +1404,7 @@ std::tuple<std::string, int> TLSSelectionParserImplBuster::ParseAtom() ...@@ -1404,7 +1404,7 @@ std::tuple<std::string, int> TLSSelectionParserImplBuster::ParseAtom()
match(':'); match(':');
std::string atom = m_value_s; std::string atom = m_value_s;
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Warning: ignoring atom ID '" << atom << "' in TLS selection" << std::endl; std::cerr << "Warning: ignoring atom ID '" << atom << "' in TLS selection" << std::endl;
match(bt_IDENT); match(bt_IDENT);
...@@ -1958,14 +1958,14 @@ std::unique_ptr<tls_selection> parse_tls_selection_details(const std::string &pr ...@@ -1958,14 +1958,14 @@ std::unique_ptr<tls_selection> parse_tls_selection_details(const std::string &pr
if (not result) if (not result)
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Falling back to old BUSTER" << std::endl; std::cerr << "Falling back to old BUSTER" << std::endl;
result = busterOld.Parse(selection); result = busterOld.Parse(selection);
} }
if (not result) if (not result)
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Falling back to PHENIX" << std::endl; std::cerr << "Falling back to PHENIX" << std::endl;
result = phenix.Parse(selection); result = phenix.Parse(selection);
} }
...@@ -1976,35 +1976,35 @@ std::unique_ptr<tls_selection> parse_tls_selection_details(const std::string &pr ...@@ -1976,35 +1976,35 @@ std::unique_ptr<tls_selection> parse_tls_selection_details(const std::string &pr
if (not result) if (not result)
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Falling back to BUSTER" << std::endl; std::cerr << "Falling back to BUSTER" << std::endl;
result = buster.Parse(selection); result = buster.Parse(selection);
} }
if (not result) if (not result)
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Falling back to old BUSTER" << std::endl; std::cerr << "Falling back to old BUSTER" << std::endl;
result = busterOld.Parse(selection); result = busterOld.Parse(selection);
} }
} }
else else
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "No known program specified, trying PHENIX" << std::endl; std::cerr << "No known program specified, trying PHENIX" << std::endl;
result = phenix.Parse(selection); result = phenix.Parse(selection);
if (not result) if (not result)
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Falling back to BUSTER" << std::endl; std::cerr << "Falling back to BUSTER" << std::endl;
result = buster.Parse(selection); result = buster.Parse(selection);
} }
if (not result) if (not result)
{ {
if (cif::VERBOSE) if (cif::VERBOSE > 0)
std::cerr << "Falling back to old BUSTER" << std::endl; std::cerr << "Falling back to old BUSTER" << std::endl;
result = busterOld.Parse(selection); result = busterOld.Parse(selection);
} }
......
...@@ -87,17 +87,17 @@ class Matrix : public MatrixExpression<Matrix> ...@@ -87,17 +87,17 @@ class Matrix : public MatrixExpression<Matrix>
Matrix &operator=(Matrix &&m) = default; Matrix &operator=(Matrix &&m) = default;
Matrix &operator=(const Matrix &m) = default; Matrix &operator=(const Matrix &m) = default;
uint32_t dim_m() const { return m_m; } size_t dim_m() const { return m_m; }
uint32_t dim_n() const { return m_n; } size_t dim_n() const { return m_n; }
double operator()(uint32_t i, uint32_t j) const double operator()(size_t i, size_t j) const
{ {
assert(i < m_m); assert(i < m_m);
assert(j < m_n); assert(j < m_n);
return m_data[i * m_n + j]; return m_data[i * m_n + j];
} }
double &operator()(uint32_t i, uint32_t j) double &operator()(size_t i, size_t j)
{ {
assert(i < m_m); assert(i < m_m);
assert(j < m_n); assert(j < m_n);
...@@ -105,7 +105,7 @@ class Matrix : public MatrixExpression<Matrix> ...@@ -105,7 +105,7 @@ class Matrix : public MatrixExpression<Matrix>
} }
private: private:
uint32_t m_m = 0, m_n = 0; size_t m_m = 0, m_n = 0;
std::vector<double> m_data; std::vector<double> m_data;
}; };
...@@ -522,15 +522,17 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> & ...@@ -522,15 +522,17 @@ quaternion align_points(const std::vector<point> &pa, const std::vector<point> &
point nudge(point p, float offset) point nudge(point p, float offset)
{ {
static const float kPI_f = static_cast<float>(kPI);
static std::random_device rd; static std::random_device rd;
static std::mt19937_64 rng(rd()); static std::mt19937_64 rng(rd());
std::uniform_real_distribution<float> randomAngle(0, 2 * kPI); std::uniform_real_distribution<float> randomAngle(0, 2 * kPI_f);
std::normal_distribution<> randomOffset(0, offset); std::normal_distribution<float> randomOffset(0, offset);
float theta = randomAngle(rng); float theta = randomAngle(rng);
float phi1 = randomAngle(rng) - kPI; float phi1 = randomAngle(rng) - kPI_f;
float phi2 = randomAngle(rng) - kPI; float phi2 = randomAngle(rng) - kPI_f;
quaternion q = spherical(1.0f, theta, phi1, phi2); quaternion q = spherical(1.0f, theta, phi1, phi2);
......
...@@ -124,7 +124,8 @@ std::string get_executable_path() ...@@ -124,7 +124,8 @@ std::string get_executable_path()
{ {
using namespace std::literals; using namespace std::literals;
char path[PATH_MAX] = ""; // This used to be PATH_MAX, but lets simply assume 1024 is enough...
char path[1024] = "";
if (readlink("/proc/self/exe", path, sizeof(path)) == -1) if (readlink("/proc/self/exe", path, sizeof(path)) == -1)
throw std::runtime_error("could not get exe path "s + strerror(errno)); throw std::runtime_error("could not get exe path "s + strerror(errno));
return {path}; return {path};
......
...@@ -58,6 +58,12 @@ bool init_unit_test() ...@@ -58,6 +58,12 @@ bool init_unit_test()
// not a test, just initialize test dir // not a test, just initialize test dir
if (boost::unit_test::framework::master_test_suite().argc == 2) if (boost::unit_test::framework::master_test_suite().argc == 2)
gTestDir = boost::unit_test::framework::master_test_suite().argv[1]; gTestDir = boost::unit_test::framework::master_test_suite().argv[1];
else
{
while (not gTestDir.empty() and not std::filesystem::exists(gTestDir / "test"))
gTestDir = gTestDir.parent_path();
gTestDir /= "test";
}
// do this now, avoids the need for installing // do this now, avoids the need for installing
cif::add_file_resource("mmcif_pdbx.dic", gTestDir / ".." / "rsrc" / "mmcif_pdbx.dic"); cif::add_file_resource("mmcif_pdbx.dic", gTestDir / ".." / "rsrc" / "mmcif_pdbx.dic");
......
...@@ -39,6 +39,12 @@ int main(int argc, char* argv[]) ...@@ -39,6 +39,12 @@ int main(int argc, char* argv[])
if (argc == 3) if (argc == 3)
testdir = argv[2]; testdir = argv[2];
else
{
while (not testdir.empty() and not std::filesystem::exists(testdir / "test"))
testdir = testdir.parent_path();
testdir /= "test";
}
if (std::filesystem::exists(testdir / ".." / "data" / "ccd-subset.cif")) if (std::filesystem::exists(testdir / ".." / "data" / "ccd-subset.cif"))
cif::add_file_resource("components.cif", testdir / ".." / "data" / "ccd-subset.cif"); cif::add_file_resource("components.cif", testdir / ".." / "data" / "ccd-subset.cif");
......
...@@ -2322,14 +2322,16 @@ _test.text ?? ...@@ -2322,14 +2322,16 @@ _test.text ??
BOOST_AUTO_TEST_CASE(output_test_1) BOOST_AUTO_TEST_CASE(output_test_1)
{ {
cif::VERBOSE = 5;
auto data1 = R"( auto data1 = R"(
data_Q data_Q
loop_ loop_
_test.text _test.text
"stop_the_crap" stop_the_crap
'and stop_ this too' 'and stop_ this too'
'data_dinges' 'data_dinges'
'blablaglobal_bla' blablaglobal_bla
boo.data_.whatever boo.data_.whatever
'data_.whatever' 'data_.whatever'
'stop_' 'stop_'
...@@ -2346,7 +2348,7 @@ boo.data_.whatever ...@@ -2346,7 +2348,7 @@ boo.data_.whatever
const char *s; const char *s;
bool q; bool q;
} kS[] = { } kS[] = {
{ "stop_the_crap", false }, { "stop_the_crap", true },
{ "and stop_ this too", false }, { "and stop_ this too", false },
{ "data_dinges", false }, { "data_dinges", false },
{ "blablaglobal_bla", true }, { "blablaglobal_bla", true },
......
#!/bin/bash #!/bin/sh
set -e set -e
...@@ -7,8 +7,8 @@ if [ "$EUID" -ne 0 ] ...@@ -7,8 +7,8 @@ if [ "$EUID" -ne 0 ]
exit exit
fi fi
if [ -f /etc/libcifpp.conf ] ; then if [ -f "@CIFPP_ETC_DIR@/libcifpp.conf" ] ; then
. /etc/libcifpp.conf . "@CIFPP_ETC_DIR@/libcifpp.conf"
fi fi
# check to see if we're supposed to run at all # check to see if we're supposed to run at all
...@@ -17,7 +17,7 @@ if [ "$update" != "true" ] ; then ...@@ -17,7 +17,7 @@ if [ "$update" != "true" ] ; then
fi fi
# if cache directory doesn't exist, exit. # if cache directory doesn't exist, exit.
if ! [ -d @CIFPP_CACHE_DIR@ ]; then if ! [ -d "@CIFPP_CACHE_DIR@" ]; then
exit exit
fi fi
...@@ -46,10 +46,10 @@ fetch_dictionary () { ...@@ -46,10 +46,10 @@ fetch_dictionary () {
fetch_dictionary "@CIFPP_CACHE_DIR@/mmcif_pdbx.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz" fetch_dictionary "@CIFPP_CACHE_DIR@/mmcif_pdbx.dic" "https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz"
fetch_dictionary "@CIFPP_CACHE_DIR@/components.cif" "ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz" fetch_dictionary "@CIFPP_CACHE_DIR@/components.cif" "ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif.gz"
# notify subscribers wget -O"@CIFPP_CACHE_DIR@/mmcif_ma.dic" "https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic"
if [ -d /etc/libcifpp/cache-update.d ] && [ -x /bin/run-parts ]; then # notify subscribers, will fail on FreeBSD
run-parts --arg "@CIFPP_CACHE_DIR@" -- /etc/libcifpp/cache-update.d
fi
wget -O/var/cache/libcifpp/mmcif_ma.dic "https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic" if [ -d "@CIFPP_ETC_DIR@/libcifpp/cache-update.d" ] && [ -x /bin/run-parts ]; then
run-parts --arg "@CIFPP_CACHE_DIR@" -- "@CIFPP_ETC_DIR@/libcifpp/cache-update.d"
fi
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