mirror of
https://github.com/PDB-REDO/libcifpp.git
synced 2026-06-04 22:14:24 +08:00
Compare commits
82 Commits
develop-ci
...
v7.0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a96b1e07f4 | ||
|
|
f48c31bcb5 | ||
|
|
d85ab93a35 | ||
|
|
a6804b5aca | ||
|
|
e4dcb211ee | ||
|
|
a5a5f47f7a | ||
|
|
25c900c387 | ||
|
|
4e95f7b83e | ||
|
|
66ad3b0cee | ||
|
|
e853cd1ca0 | ||
|
|
b9544033c6 | ||
|
|
17840cb8cc | ||
|
|
f85b6d94b8 | ||
|
|
6c32a9f198 | ||
|
|
cefeebbfb8 | ||
|
|
941a015b43 | ||
|
|
ae0e9fbe77 | ||
|
|
3484c3dd2e | ||
|
|
5be8f749bd | ||
|
|
cf484707a0 | ||
|
|
f12e529c0b | ||
|
|
01b90a2ba5 | ||
|
|
cd1e952812 | ||
|
|
996f1e4277 | ||
|
|
2d84694f86 | ||
|
|
65718c64cc | ||
|
|
6e30365f55 | ||
|
|
c0555b6d86 | ||
|
|
1ff9b6c071 | ||
|
|
c1a51a1dfa | ||
|
|
bfbbeb90e7 | ||
|
|
588e075325 | ||
|
|
66717fee68 | ||
|
|
844f52c955 | ||
|
|
e679cd05c1 | ||
|
|
1e72ce4830 | ||
|
|
3bb21c5403 | ||
|
|
6d1be23ad0 | ||
|
|
0472b9a4a4 | ||
|
|
c9acff49f9 | ||
|
|
7cab560595 | ||
|
|
ac98531a2f | ||
|
|
917e0ba79c | ||
|
|
3ebceb7522 | ||
|
|
92bd52da12 | ||
|
|
fb56a9cd6e | ||
|
|
a4680f7d38 | ||
|
|
da8a72a8aa | ||
|
|
ac497932b5 | ||
|
|
9927b5061a | ||
|
|
cedaab9642 | ||
|
|
50bf2145ec | ||
|
|
dc77729f50 | ||
|
|
e3330d667a | ||
|
|
9822f397a1 | ||
|
|
a3b5ce9959 | ||
|
|
9eb06e929a | ||
|
|
629e06d647 | ||
|
|
51ccb92184 | ||
|
|
3cd27f13fd | ||
|
|
ae668530c0 | ||
|
|
4a8b1c056c | ||
|
|
d7a5e598bc | ||
|
|
3f1ee32cc6 | ||
|
|
725d6ead98 | ||
|
|
baf70579de | ||
|
|
cd28ab58a3 | ||
|
|
a78fa0a81d | ||
|
|
82130be5f5 | ||
|
|
510ce62dfb | ||
|
|
93375a5087 | ||
|
|
be738e7fb1 | ||
|
|
9c78131df3 | ||
|
|
d94f6f4d19 | ||
|
|
9a3eced350 | ||
|
|
2fed7a76fb | ||
|
|
f02e59df1b | ||
|
|
04147a2fe9 | ||
|
|
0e83bc31dc | ||
|
|
75a5f7960f | ||
|
|
3f93c27b07 | ||
|
|
ab781d4516 |
342
CMakeLists.txt
342
CMakeLists.txt
@@ -22,16 +22,17 @@
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
|
||||
# set the project name
|
||||
project(
|
||||
libcifpp
|
||||
VERSION 7.0.0
|
||||
VERSION 7.0.5
|
||||
LANGUAGES CXX)
|
||||
|
||||
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(FindAtomic)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
@@ -40,11 +41,6 @@ include(CheckCXXSourceCompiles)
|
||||
include(GenerateExportHeader)
|
||||
include(CTest)
|
||||
include(FetchContent)
|
||||
include(ExternalProject)
|
||||
|
||||
set(CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# When building with ninja-multiconfig, build both debug and release by default
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||
@@ -71,10 +67,7 @@ if(NOT(BUILD_FOR_CCP4 AND WIN32))
|
||||
option(BUILD_SHARED_LIBS "Build a shared library instead of a static one" OFF)
|
||||
endif()
|
||||
|
||||
if(BUILD_FOR_CCP4)
|
||||
unset(CIFPP_DOWNLOAD_CCD)
|
||||
unset(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
else()
|
||||
if(PROJECT_IS_TOP_LEVEL AND NOT BUILD_FOR_CCP4)
|
||||
# Lots of code depend on the availability of the components.cif file
|
||||
option(CIFPP_DOWNLOAD_CCD
|
||||
"Download the CCD file components.cif during installation" ON)
|
||||
@@ -84,6 +77,9 @@ else()
|
||||
option(CIFPP_INSTALL_UPDATE_SCRIPT
|
||||
"Install the script to update CCD and dictionary files" ON)
|
||||
endif()
|
||||
else()
|
||||
unset(CIFPP_DOWNLOAD_CCD)
|
||||
unset(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
endif()
|
||||
|
||||
# When CCP4 is sourced in the environment, we can recreate the symmetry
|
||||
@@ -126,6 +122,7 @@ if(WIN32)
|
||||
add_definitions(-D _WIN32_WINNT=0x0501)
|
||||
endif()
|
||||
|
||||
# Man, this is 2024 we're living in...
|
||||
add_definitions(-DNOMINMAX)
|
||||
|
||||
# We do not want to write an export file for all our symbols...
|
||||
@@ -137,6 +134,7 @@ if(MSVC)
|
||||
add_compile_options(/permissive- /bigobj)
|
||||
add_link_options(/NODEFAULTLIB:library)
|
||||
|
||||
# This is dubious...
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
else()
|
||||
@@ -164,7 +162,7 @@ if(GXX_LIBSTDCPP)
|
||||
|
||||
try_run(STD_REGEX_RUNNING STD_REGEX_COMPILING
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test
|
||||
${PROJECT_SOURCE_DIR}/cmake/test-rx.cpp)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-rx.cpp)
|
||||
|
||||
if(STD_REGEX_RUNNING STREQUAL FAILED_TO_RUN)
|
||||
message(
|
||||
@@ -189,10 +187,6 @@ if(GXX_LIBSTDCPP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG)
|
||||
find_package(Threads)
|
||||
|
||||
if(MSVC)
|
||||
# Avoid linking the shared library of zlib Search ZLIB_ROOT first if it is
|
||||
# set.
|
||||
@@ -221,7 +215,12 @@ if(MSVC)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(ZLIB QUIET)
|
||||
find_package(Threads)
|
||||
|
||||
if(NOT ZLIB_FOUND)
|
||||
message(FATAL_ERROR "The zlib development files were not found you this system, please install them and try again (hint: on debian/ubuntu use apt-get install zlib1g-dev)")
|
||||
endif()
|
||||
|
||||
# Using Eigen3 is a bit of a thing. We don't want to build it completely since
|
||||
# we only need a couple of header files. Nothing special. But often, eigen3 is
|
||||
@@ -247,96 +246,109 @@ else()
|
||||
set(EIGEN_INCLUDE_DIR ${my-eigen3_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
include(FindFilesystem)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
|
||||
|
||||
include(FindAtomic)
|
||||
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
|
||||
|
||||
# Create a revision file, containing the current git version info
|
||||
include(VersionString)
|
||||
write_version_header(${PROJECT_SOURCE_DIR}/src/ LIB_NAME "LibCIFPP")
|
||||
write_version_header(${CMAKE_CURRENT_SOURCE_DIR}/src/ LIB_NAME "LibCIFPP")
|
||||
|
||||
# SymOp data table
|
||||
if(CIFPP_RECREATE_SYMOP_DATA)
|
||||
# The tool to create the table
|
||||
add_executable(symop-map-generator
|
||||
"${PROJECT_SOURCE_DIR}/src/symop-map-generator.cpp")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/symop-map-generator.cpp")
|
||||
|
||||
target_compile_features(symop-map-generator PUBLIC cxx_std_20)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
COMMAND
|
||||
$<TARGET_FILE:symop-map-generator> $ENV{CLIBD}/syminfo.lib
|
||||
$ENV{CLIBD}/symop.lib ${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
|
||||
$ENV{CLIBD}/symop.lib ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp)
|
||||
|
||||
add_custom_target(
|
||||
OUTPUT
|
||||
${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib"
|
||||
"$ENV{CLIBD}/symop.lib")
|
||||
endif()
|
||||
|
||||
# Sources
|
||||
set(project_sources
|
||||
${PROJECT_SOURCE_DIR}/src/category.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/condition.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/datablock.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/dictionary_parser.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/file.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/item.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/parser.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/row.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/validate.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/text.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/utilities.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/atom_type.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/compound.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/point.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/symmetry.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/model.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/cif2pdb.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/pdb2cif.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/pdb_record.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/reconstruct.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/pdb/validate-pdbx.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/category.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/condition.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/datablock.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/dictionary_parser.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/file.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/item.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/parser.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/row.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/validate.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/text.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utilities.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/atom_type.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/compound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/point.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/symmetry.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/model.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/cif2pdb.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb_record.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/pdb2cif_remark_3.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/reconstruct.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/pdb/validate-pdbx.cpp
|
||||
)
|
||||
|
||||
set(project_headers
|
||||
${PROJECT_SOURCE_DIR}/include/cif++.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/utilities.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/item.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/datablock.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/file.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/validate.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/iterator.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/parser.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/forward_decl.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/dictionary_parser.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/condition.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/category.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/row.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/atom_type.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/compound.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/point.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/symmetry.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/model.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/pdb.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/pdb/cif2pdb.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/pdb/io.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/pdb/pdb2cif.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/pdb/tls.hpp)
|
||||
include/cif++.hpp
|
||||
include/cif++/atom_type.hpp
|
||||
include/cif++/category.hpp
|
||||
include/cif++/compound.hpp
|
||||
include/cif++/condition.hpp
|
||||
include/cif++/datablock.hpp
|
||||
include/cif++/dictionary_parser.hpp
|
||||
include/cif++/exports.hpp
|
||||
include/cif++/file.hpp
|
||||
include/cif++/format.hpp
|
||||
include/cif++/forward_decl.hpp
|
||||
include/cif++/gzio.hpp
|
||||
include/cif++/item.hpp
|
||||
include/cif++/iterator.hpp
|
||||
include/cif++/matrix.hpp
|
||||
include/cif++/model.hpp
|
||||
include/cif++/parser.hpp
|
||||
include/cif++/pdb/cif2pdb.hpp
|
||||
include/cif++/pdb.hpp
|
||||
include/cif++/pdb/io.hpp
|
||||
include/cif++/pdb/pdb2cif.hpp
|
||||
include/cif++/pdb/tls.hpp
|
||||
include/cif++/point.hpp
|
||||
include/cif++/row.hpp
|
||||
include/cif++/symmetry.hpp
|
||||
include/cif++/text.hpp
|
||||
include/cif++/utilities.hpp
|
||||
include/cif++/validate.hpp
|
||||
)
|
||||
|
||||
add_library(cifpp ${project_sources} ${project_headers}
|
||||
${PROJECT_SOURCE_DIR}/src/symop_table_data.hpp)
|
||||
add_library(cifpp)
|
||||
add_library(cifpp::cifpp ALIAS cifpp)
|
||||
|
||||
target_sources(cifpp
|
||||
PRIVATE ${project_sources}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp
|
||||
PUBLIC
|
||||
FILE_SET cifpp_headers TYPE HEADERS
|
||||
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
FILES ${project_headers}
|
||||
)
|
||||
|
||||
# The code now really requires C++20
|
||||
target_compile_features(cifpp PUBLIC cxx_std_20)
|
||||
|
||||
set(CMAKE_DEBUG_POSTFIX d)
|
||||
set_target_properties(cifpp PROPERTIES DEBUG_POSTFIX "d")
|
||||
|
||||
generate_export_header(cifpp EXPORT_FILE_NAME
|
||||
${PROJECT_SOURCE_DIR}/include/cif++/exports.hpp)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/cif++/exports.hpp)
|
||||
|
||||
if(BOOST_REGEX)
|
||||
target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1
|
||||
@@ -353,12 +365,11 @@ set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_include_directories(
|
||||
cifpp
|
||||
PUBLIC "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
PRIVATE "${BOOST_REGEX_INCLUDE_DIR}" "${EIGEN_INCLUDE_DIR}")
|
||||
|
||||
target_link_libraries(cifpp PUBLIC Threads::Threads ZLIB::ZLIB
|
||||
${CIFPP_REQUIRED_LIBRARIES})
|
||||
target_link_libraries(cifpp PUBLIC Threads::Threads ZLIB::ZLIB std::atomic)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
target_link_options(cifpp PRIVATE -undefined dynamic_lookup)
|
||||
@@ -366,7 +377,7 @@ endif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
|
||||
if(CIFPP_DOWNLOAD_CCD)
|
||||
# download the components.cif file from CCD
|
||||
set(COMPONENTS_CIF ${PROJECT_SOURCE_DIR}/rsrc/components.cif)
|
||||
set(COMPONENTS_CIF ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/components.cif)
|
||||
|
||||
if(EXISTS ${COMPONENTS_CIF})
|
||||
file(SIZE ${COMPONENTS_CIF} CCD_FILE_SIZE)
|
||||
@@ -401,7 +412,7 @@ if(CIFPP_DOWNLOAD_CCD)
|
||||
add_custom_command(
|
||||
OUTPUT ${COMPONENTS_CIF}
|
||||
COMMAND "${GUNZIP}" ${COMPONENTS_CIF}.gz
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/rsrc/)
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/)
|
||||
|
||||
add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF})
|
||||
endif()
|
||||
@@ -431,6 +442,10 @@ if(CIFPP_DATA_DIR)
|
||||
target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}")
|
||||
endif()
|
||||
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
set(CIFPP_SHARE_DIR ${CIFPP_DATA_DIR} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT BUILD_FOR_CCP4)
|
||||
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local")
|
||||
set(CIFPP_CACHE_DIR
|
||||
@@ -452,14 +467,9 @@ else()
|
||||
endif()
|
||||
|
||||
# Install rules
|
||||
install(
|
||||
TARGETS cifpp
|
||||
EXPORT cifpp-targets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
INCLUDES
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(TARGETS cifpp
|
||||
EXPORT cifpp
|
||||
FILE_SET cifpp_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
if(MSVC AND BUILD_SHARED_LIBS)
|
||||
install(
|
||||
@@ -479,50 +489,33 @@ if(OLD_CONFIG_FILES)
|
||||
install(CODE "file(REMOVE ${OLD_CONFIG_FILES})")
|
||||
endif()
|
||||
|
||||
install(
|
||||
EXPORT cifpp-targets
|
||||
FILE "cifpp-targets.cmake"
|
||||
install(EXPORT cifpp
|
||||
NAMESPACE cifpp::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp)
|
||||
FILE "cifpp-targets.cmake"
|
||||
DESTINATION lib/cmake/cifpp)
|
||||
|
||||
install(
|
||||
DIRECTORY include/cif++
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
COMPONENT Devel)
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rsrc/mmcif_ma.dic
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp)
|
||||
|
||||
install(
|
||||
FILES include/cif++.hpp
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
COMPONENT Devel)
|
||||
|
||||
if(CIFPP_DATA_DIR)
|
||||
install(
|
||||
FILES ${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ma.dic ${COMPONENTS_CIF}
|
||||
DESTINATION ${CIFPP_DATA_DIR})
|
||||
if(CIFPP_DATA_DIR AND CIFPP_DOWNLOAD_CCD)
|
||||
install(FILES ${COMPONENTS_CIF}
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp)
|
||||
endif()
|
||||
|
||||
if(CIFPP_CACHE_DIR)
|
||||
install(
|
||||
FILES ${PROJECT_SOURCE_DIR}/rsrc/mmcif_ddl.dic
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_pdbx.dic
|
||||
${PROJECT_SOURCE_DIR}/rsrc/mmcif_ma.dic ${COMPONENTS_CIF}
|
||||
DESTINATION ${CIFPP_CACHE_DIR})
|
||||
endif()
|
||||
|
||||
set(CONFIG_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/cmake/cifpp-config.cmake.in)
|
||||
set(CONFIG_TEMPLATE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cifpp-config.cmake.in)
|
||||
|
||||
configure_package_config_file(
|
||||
${CONFIG_TEMPLATE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
|
||||
INSTALL_DESTINATION lib/cmake/cifpp
|
||||
PATH_VARS CIFPP_DATA_DIR)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
|
||||
COMPONENT Devel)
|
||||
DESTINATION lib/cmake/cifpp)
|
||||
|
||||
set_target_properties(
|
||||
cifpp
|
||||
@@ -540,109 +533,42 @@ write_basic_package_version_file(
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
# In case we're included as sub_directory:
|
||||
if(NOT PROJECT_IS_TOP_LEVEL)
|
||||
set(CIFPP_SHARE_DIR ${PROJECT_SOURCE_DIR}/rsrc PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
# We're using the older version 2 of Catch2
|
||||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v2.13.9)
|
||||
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
|
||||
list(
|
||||
APPEND
|
||||
CIFPP_tests
|
||||
unit-v2
|
||||
unit-3d
|
||||
format
|
||||
model
|
||||
rename-compound
|
||||
sugar
|
||||
spinner
|
||||
reconstruction
|
||||
validate-pdbx)
|
||||
|
||||
foreach(CIFPP_TEST IN LISTS CIFPP_tests)
|
||||
set(CIFPP_TEST "${CIFPP_TEST}-test")
|
||||
set(CIFPP_TEST_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/test/${CIFPP_TEST}.cpp")
|
||||
|
||||
add_executable(
|
||||
${CIFPP_TEST} ${CIFPP_TEST_SOURCE}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test/test-main.cpp")
|
||||
|
||||
target_link_libraries(${CIFPP_TEST} PRIVATE Threads::Threads cifpp::cifpp
|
||||
Catch2::Catch2)
|
||||
target_include_directories(${CIFPP_TEST} PRIVATE "${EIGEN_INCLUDE_DIR}")
|
||||
|
||||
if(MSVC)
|
||||
# Specify unwind semantics so that MSVC knowns how to handle exceptions
|
||||
target_compile_options(${CIFPP_TEST} PRIVATE /EHsc)
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
"run-${CIFPP_TEST}"
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch ${CIFPP_TEST})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch
|
||||
COMMAND $<TARGET_FILE:${CIFPP_TEST}> --data-dir
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test)
|
||||
|
||||
add_test(NAME ${CIFPP_TEST} COMMAND $<TARGET_FILE:${CIFPP_TEST}> --data-dir
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test)
|
||||
endforeach()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
# Optionally install the update scripts for CCD and dictionary files
|
||||
if(CIFPP_INSTALL_UPDATE_SCRIPT)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR ${CMAKE_SYSTEM_NAME} STREQUAL
|
||||
"GNU")
|
||||
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local")
|
||||
set(CIFPP_CRON_DIR
|
||||
"/etc/cron.weekly"
|
||||
CACHE PATH "The cron directory, for the update script")
|
||||
else()
|
||||
set(CIFPP_CRON_DIR
|
||||
"${CIFPP_ETC_DIR}/cron.weekly"
|
||||
CACHE PATH "The cron directory, for the update script")
|
||||
endif()
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
set(CIFPP_CRON_DIR
|
||||
"${CIFPP_ETC_DIR}/periodic/weekly"
|
||||
CACHE PATH "The cron directory, for the update script")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tools/update-libcifpp-data.in
|
||||
update-libcifpp-data @ONLY)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
|
||||
${CMAKE_SYSTEM_NAME} STREQUAL "GNU" OR
|
||||
${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
|
||||
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cron.weekly
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE
|
||||
WORLD_READ)
|
||||
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)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/update-libcifpp-data
|
||||
DESTINATION ${CIFPP_CRON_DIR}
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE
|
||||
WORLD_READ)
|
||||
|
||||
install(DIRECTORY DESTINATION ${CIFPP_CACHE_DIR})
|
||||
|
||||
# a config file, to make it complete
|
||||
if(NOT EXISTS "${CIFPP_ETC_DIR}/libcifpp.conf")
|
||||
# install(DIRECTORY DESTINATION "${CMAKE_INSTALL_LOCALSTATEDIR}/libcifpp")
|
||||
if(NOT EXISTS "${CMAKE_INSTALL_SYSCONFDIR}/libcifpp.conf")
|
||||
file(
|
||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf
|
||||
[[# Uncomment the next line to enable automatic updates
|
||||
# update=true
|
||||
]])
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf
|
||||
DESTINATION "${CIFPP_ETC_DIR}")
|
||||
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR})
|
||||
install(
|
||||
CODE "message(\"A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")"
|
||||
)
|
||||
|
||||
install(DIRECTORY DESTINATION "${CIFPP_ETC_DIR}/libcifpp/cache-update.d")
|
||||
install(DIRECTORY DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/libcifpp/cache-update.d)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}")
|
||||
@@ -651,13 +577,3 @@ endif()
|
||||
if(BUILD_DOCUMENTATION)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_SOURCE_TGZ ON)
|
||||
set(CPACK_SOURCE_TBZ2 OFF)
|
||||
set(CPACK_SOURCE_TXZ OFF)
|
||||
set(CPACK_SOURCE_TZ OFF)
|
||||
set(CPACK_SOURCE_IGNORE_FILES "/rsrc/components.cif;/build;/.vscode;/.git")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
|
||||
include(CPack)
|
||||
|
||||
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (file.empty())
|
||||
{
|
||||
std::cerr << "Empty file" << std::endl;
|
||||
std::cerr << "Empty file\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -66,8 +66,8 @@ int main(int argc, char *argv[])
|
||||
auto n = atom_site.count(cif::key("label_atom_id") == "OXT");
|
||||
|
||||
std::cout << "File contains " << atom_site.size() << " atoms of which "
|
||||
<< n << (n == 1 ? " is" : " are") << " OXT" << std::endl
|
||||
<< "residues with an OXT are:" << std::endl;
|
||||
<< n << (n == 1 ? " is" : " are") << " OXT\n"
|
||||
<< "residues with an OXT are:\n";
|
||||
|
||||
// Loop over all atoms with atom-id "OXT" and print out some info.
|
||||
// That info is extracted using structured binding in C++
|
||||
@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
|
||||
cif::key("label_atom_id") == "OXT",
|
||||
"label_asym_id", "label_comp_id", "label_seq_id"))
|
||||
{
|
||||
std::cout << asym << ' ' << comp << ' ' << seqnr << std::endl;
|
||||
std::cout << asym << ' ' << comp << ' ' << seqnr << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
18
changelog
18
changelog
@@ -1,3 +1,21 @@
|
||||
Version 7.0.5
|
||||
- Fix case where category index was not updated for updated value
|
||||
|
||||
Version 7.0.4
|
||||
- Do not install headers and library in case we're not the top project
|
||||
|
||||
Version 7.0.3
|
||||
- Fix installation, write exports.hpp again
|
||||
|
||||
Version 7.0.2
|
||||
- Fix in testing error_code results.
|
||||
|
||||
Version 7.0.1
|
||||
- Various reconstruction fixes
|
||||
- category order in output fixed
|
||||
- better implementation of constructors for file, datablock and category
|
||||
- small optimisation in iterator
|
||||
|
||||
Version 7.0.0
|
||||
- Renaming many methods and parameters to be more
|
||||
consistent with the mmCIF dictionaries.
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
# Simplistic reimplementation of https://github.com/vector-of-bool/CMakeCM/blob/master/modules/FindFilesystem.cmake
|
||||
|
||||
if(TARGET std::filesystem)
|
||||
return()
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
cmake_push_check_state()
|
||||
|
||||
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
|
||||
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||
|
||||
set(code [[
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
|
||||
int main() {
|
||||
auto cwd = std::filesystem::current_path();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
]])
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 8.4.0)
|
||||
# >> https://stackoverflow.com/questions/63902528/program-crashes-when-filesystempath-is-destroyed
|
||||
set(CXX_FILESYSTEM_NO_LINK_NEEDED 0)
|
||||
else()
|
||||
# Check a simple filesystem program without any linker flags
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
endif()
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
set(_found 1)
|
||||
else()
|
||||
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
|
||||
# Add the libstdc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set(_found ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
|
||||
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
# Try the libc++ flag
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
|
||||
check_cxx_source_compiles("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set(_found ${CXX_FILESYSTEM_CPPFS_NEEDED})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_found)
|
||||
add_library(std::filesystem INTERFACE IMPORTED)
|
||||
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
|
||||
|
||||
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||
# Nothing to add...
|
||||
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME stdc++fs)
|
||||
set(STDCPPFS_LIBRARY stdc++fs)
|
||||
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||
set_target_properties(std::filesystem PROPERTIES IMPORTED_LIBNAME c++fs)
|
||||
set(STDCPPFS_LIBRARY c++fs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_pop_check_state()
|
||||
|
||||
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
|
||||
mark_as_advanced(Filesystem_FOUND)
|
||||
|
||||
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
|
||||
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
||||
endif()
|
||||
|
||||
@@ -13,7 +13,7 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cif::file file = cif::pdb::read(argv[1]);
|
||||
cif::file file(argv[1]);
|
||||
|
||||
if (file.empty())
|
||||
{
|
||||
|
||||
@@ -200,7 +200,7 @@ enum class radius_type
|
||||
};
|
||||
|
||||
/// @brief The number of radii per element which can be requested from atom_type_info
|
||||
constexpr size_t kRadiusTypeCount = static_cast<size_t>(radius_type::type_count);
|
||||
constexpr std::size_t kRadiusTypeCount = static_cast<std::size_t>(radius_type::type_count);
|
||||
|
||||
/// An enum used to select either the effective or the crystal radius of an ion.
|
||||
/// See explanation on Wikipedia: https://en.wikipedia.org/wiki/Ionic_radius
|
||||
@@ -276,7 +276,7 @@ class atom_type_traits
|
||||
{
|
||||
if (type >= radius_type::type_count)
|
||||
throw std::invalid_argument("invalid radius requested");
|
||||
return m_info->radii[static_cast<size_t>(type)] / 100.f;
|
||||
return m_info->radii[static_cast<std::size_t>(type)] / 100.f;
|
||||
}
|
||||
|
||||
/// \brief Return the radius for a charged version of this atom in a solid crystal
|
||||
|
||||
@@ -141,31 +141,39 @@ class category
|
||||
|
||||
/// \endcond
|
||||
|
||||
category() = default; ///< Default constructor
|
||||
category(std::string_view name); ///< Constructor taking a \a name
|
||||
category(const category &rhs); ///< Copy constructor
|
||||
category(category &&rhs); ///< Move constructor
|
||||
category &operator=(const category &rhs); ///< Copy assignement operator
|
||||
category &operator=(category &&rhs); ///< Move assignement operator
|
||||
category() = default; ///< Default constructor
|
||||
category(std::string_view name); ///< Constructor taking a \a name
|
||||
category(const category &rhs); ///< Copy constructor
|
||||
|
||||
category(category &&rhs) noexcept ///< Move constructor
|
||||
{
|
||||
swap(*this, rhs);
|
||||
}
|
||||
|
||||
category &operator=(category rhs) ///< assignement operator
|
||||
{
|
||||
swap(*this, rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @brief Destructor
|
||||
/// @note Please note that the destructor is not virtual. It is assumed that
|
||||
/// you will not derive from this class.
|
||||
~category();
|
||||
|
||||
friend void swap(category &a, category &b) noexcept;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
const std::string &name() const { return m_name; } ///< Returns the name of the category
|
||||
|
||||
[[deprecated("use key_items instead")]]
|
||||
iset key_fields() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category
|
||||
[[deprecated("use key_items instead")]] iset key_fields() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category
|
||||
|
||||
iset key_items() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category
|
||||
iset key_items() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category
|
||||
|
||||
[[deprecated("use key_item_indices instead")]]
|
||||
std::set<uint16_t> key_field_indices() const; ///< Returns a set of indices for the key items.
|
||||
[[deprecated("use key_item_indices instead")]] std::set<uint16_t> key_field_indices() const; ///< Returns a set of indices for the key items.
|
||||
|
||||
std::set<uint16_t> key_item_indices() const; ///< Returns a set of indices for the key items.
|
||||
std::set<uint16_t> key_item_indices() const; ///< Returns a set of indices for the key items.
|
||||
|
||||
/// @brief Set the validator for this category to @a v
|
||||
/// @param v The category_validator to assign. A nullptr value is allowed.
|
||||
@@ -174,7 +182,7 @@ class category
|
||||
|
||||
/// @brief Update the links in this category
|
||||
/// @param db The enclosing @ref datablock
|
||||
void update_links(datablock &db);
|
||||
void update_links(const datablock &db);
|
||||
|
||||
/// @brief Return the global @ref validator for the data
|
||||
/// @return The @ref validator or nullptr if not assigned
|
||||
@@ -285,15 +293,15 @@ class category
|
||||
}
|
||||
|
||||
/// Return a count of the rows in this container
|
||||
size_t size() const
|
||||
std::size_t size() const
|
||||
{
|
||||
return std::distance(cbegin(), cend());
|
||||
}
|
||||
|
||||
/// Return the theoretical maximum number or rows that can be stored
|
||||
size_t max_size() const
|
||||
std::size_t max_size() const
|
||||
{
|
||||
return std::numeric_limits<size_t>::max(); // this is a bit optimistic, I guess
|
||||
return std::numeric_limits<std::size_t>::max(); // this is a bit optimistic, I guess
|
||||
}
|
||||
|
||||
/// Return true if the category is empty
|
||||
@@ -823,9 +831,9 @@ class category
|
||||
/// @brief Return the total number of rows that match condition @a cond
|
||||
/// @param cond The condition to match
|
||||
/// @return The count
|
||||
size_t count(condition &&cond) const
|
||||
std::size_t count(condition &&cond) const
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
if (cond)
|
||||
{
|
||||
@@ -895,14 +903,14 @@ class category
|
||||
/// @brief Erase all rows that match condition @a cond
|
||||
/// @param cond The condition
|
||||
/// @return The number of rows that have been erased
|
||||
size_t erase(condition &&cond);
|
||||
std::size_t erase(condition &&cond);
|
||||
|
||||
/// @brief Erase all rows that match condition @a cond calling
|
||||
/// the visitor function @a visit for each before actually erasing it.
|
||||
/// @param cond The condition
|
||||
/// @param visit The visitor function
|
||||
/// @return The number of rows that have been erased
|
||||
size_t erase(condition &&cond, std::function<void(row_handle)> &&visit);
|
||||
std::size_t erase(condition &&cond, std::function<void(row_handle)> &&visit);
|
||||
|
||||
/// @brief Emplace the values in @a ri in a new row
|
||||
/// @param ri An object containing the values to insert
|
||||
@@ -964,6 +972,32 @@ class category
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
using value_provider_type = std::function<std::string_view(std::string_view)>;
|
||||
|
||||
/// \brief Update a single item named @a item_name in the rows that match
|
||||
/// \a cond to values provided by a callback function \a value_provider
|
||||
/// making sure the linked categories are updated according to the link.
|
||||
/// That means, child categories are updated if the links are absolute
|
||||
/// and unique. If they are not, the child category rows are split.
|
||||
|
||||
void update_value(condition &&cond, std::string_view item_name,
|
||||
value_provider_type &&value_provider)
|
||||
{
|
||||
auto rs = find(std::move(cond));
|
||||
std::vector<row_handle> rows;
|
||||
std::copy(rs.begin(), rs.end(), std::back_inserter(rows));
|
||||
update_value(rows, item_name, std::move(value_provider));
|
||||
}
|
||||
|
||||
/// \brief Update a single item named @a item_name in the rows \a rows
|
||||
/// to values provided by a callback function \a value_provider
|
||||
/// making sure the linked categories are updated according to the link.
|
||||
/// That means, child categories are updated if the links are absolute
|
||||
/// and unique. If they are not, the child category rows are split.
|
||||
|
||||
void update_value(const std::vector<row_handle> &rows, std::string_view item_name,
|
||||
value_provider_type &&value_provider);
|
||||
|
||||
/// \brief Update a single item named @a item_name in the rows that match \a cond to value \a value
|
||||
/// making sure the linked categories are updated according to the link.
|
||||
/// That means, child categories are updated if the links are absolute
|
||||
@@ -982,15 +1016,18 @@ class category
|
||||
/// That means, child categories are updated if the links are absolute
|
||||
/// and unique. If they are not, the child category rows are split.
|
||||
|
||||
void update_value(const std::vector<row_handle> &rows, std::string_view item_name, std::string_view value);
|
||||
void update_value(const std::vector<row_handle> &rows, std::string_view item_name, std::string_view value)
|
||||
{
|
||||
update_value(rows, item_name, [value](std::string_view)
|
||||
{ return value; });
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Naming used to be very inconsistent. For backward compatibility,
|
||||
// the old function names are here as deprecated variants.
|
||||
|
||||
/// \brief Return the index number for \a column_name
|
||||
[[deprecated("Use get_item_ix instead")]]
|
||||
uint16_t get_column_ix(std::string_view column_name) const
|
||||
[[deprecated("Use get_item_ix instead")]] uint16_t get_column_ix(std::string_view column_name) const
|
||||
{
|
||||
return get_item_ix(column_name);
|
||||
}
|
||||
@@ -998,8 +1035,7 @@ class category
|
||||
/// @brief Return the name for column with index @a ix
|
||||
/// @param ix The index number
|
||||
/// @return The name of the column
|
||||
[[deprecated("use get_item_name instead")]]
|
||||
std::string_view get_column_name(uint16_t ix) const
|
||||
[[deprecated("use get_item_name instead")]] std::string_view get_column_name(uint16_t ix) const
|
||||
{
|
||||
return get_item_name(ix);
|
||||
}
|
||||
@@ -1007,8 +1043,7 @@ class category
|
||||
/// @brief Make sure a item with name @a item_name is known and return its index number
|
||||
/// @param item_name The name of the item
|
||||
/// @return The index number of the item
|
||||
[[deprecated("use add_item instead")]]
|
||||
uint16_t add_column(std::string_view item_name)
|
||||
[[deprecated("use add_item instead")]] uint16_t add_column(std::string_view item_name)
|
||||
{
|
||||
return add_item(item_name);
|
||||
}
|
||||
@@ -1016,15 +1051,13 @@ class category
|
||||
/** @brief Remove column name @a colum_name
|
||||
* @param column_name The column to be removed
|
||||
*/
|
||||
[[deprecated("use remove_item instead")]]
|
||||
void remove_column(std::string_view column_name)
|
||||
[[deprecated("use remove_item instead")]] void remove_column(std::string_view column_name)
|
||||
{
|
||||
remove_item(column_name);
|
||||
}
|
||||
|
||||
/** @brief Rename column @a from_name to @a to_name */
|
||||
[[deprecated("use rename_item instead")]]
|
||||
void rename_column(std::string_view from_name, std::string_view to_name)
|
||||
[[deprecated("use rename_item instead")]] void rename_column(std::string_view from_name, std::string_view to_name)
|
||||
{
|
||||
rename_item(from_name, to_name);
|
||||
}
|
||||
@@ -1032,15 +1065,13 @@ class category
|
||||
/// @brief Return whether a column with name @a name exists in this category
|
||||
/// @param name The name of the column
|
||||
/// @return True if the column exists
|
||||
[[deprecated("use has_item instead")]]
|
||||
bool has_column(std::string_view name) const
|
||||
[[deprecated("use has_item instead")]] bool has_column(std::string_view name) const
|
||||
{
|
||||
return has_item(name);
|
||||
}
|
||||
|
||||
/// @brief Return the cif::iset of columns in this category
|
||||
[[deprecated("use get_items instead")]]
|
||||
iset get_columns() const
|
||||
[[deprecated("use get_items instead")]] iset get_columns() const
|
||||
{
|
||||
return get_items();
|
||||
}
|
||||
@@ -1096,7 +1127,7 @@ class category
|
||||
{
|
||||
item_validator = m_cat_validator->get_validator_for_item(item_name);
|
||||
if (item_validator == nullptr)
|
||||
m_validator->report_error( validation_error::item_not_allowed_in_category, m_name, item_name, false);
|
||||
m_validator->report_error(validation_error::item_not_allowed_in_category, m_name, item_name, false);
|
||||
}
|
||||
|
||||
m_items.emplace_back(item_name, item_validator);
|
||||
@@ -1140,8 +1171,7 @@ class category
|
||||
|
||||
/// This function returns effectively the list of fully qualified item
|
||||
/// names, that is category_name + '.' + item_name for each item
|
||||
[[deprecated("use get_item_order instead")]]
|
||||
std::vector<std::string> get_tag_order() const
|
||||
[[deprecated("use get_item_order instead")]] std::vector<std::string> get_tag_order() const
|
||||
{
|
||||
return get_item_order();
|
||||
}
|
||||
@@ -1233,6 +1263,7 @@ class category
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: NEED TO FIX THIS!
|
||||
category *linked;
|
||||
const link_validator *v;
|
||||
};
|
||||
|
||||
@@ -138,7 +138,7 @@ struct compound_bond
|
||||
/// This information is derived from the CDD by default.
|
||||
///
|
||||
/// To create compounds, you use the factory method. You can add your own
|
||||
/// compound definitions by calling the addExtraComponents function and
|
||||
/// compound definitions by calling the push_dictionary function and
|
||||
/// pass it a valid CCD formatted file.
|
||||
|
||||
class compound
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "cif++/row.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
@@ -370,7 +371,7 @@ namespace detail
|
||||
{
|
||||
key_equals_condition_impl(item &&i)
|
||||
: m_item_name(i.name())
|
||||
, m_value(i.value())
|
||||
, m_value(std::forward<item>(i).value())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -470,6 +471,106 @@ namespace detail
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_equals_number_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_number_condition_impl(const std::string &name, double v)
|
||||
: m_item_name(name)
|
||||
, m_value(v)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override;
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
return m_single_hit.has_value() ? *m_single_hit == r : r[m_item_ix].compare(m_value) == 0;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << m_item_name << " == " << m_value;
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_number_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_number_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
|
||||
// watch out, both m_item_ix might be the same while item_names might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_name == ri->m_item_name;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
double m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_equals_number_or_empty_condition_impl : public condition_impl
|
||||
{
|
||||
key_equals_number_or_empty_condition_impl(key_equals_number_condition_impl *equals)
|
||||
: m_item_name(equals->m_item_name)
|
||||
, m_value(equals->m_value)
|
||||
, m_single_hit(equals->m_single_hit)
|
||||
{
|
||||
}
|
||||
|
||||
condition_impl *prepare(const category &c) override
|
||||
{
|
||||
m_item_ix = get_item_ix(c, m_item_name);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool test(row_handle r) const override
|
||||
{
|
||||
bool result = false;
|
||||
if (m_single_hit.has_value())
|
||||
result = *m_single_hit == r;
|
||||
else
|
||||
result = r[m_item_ix].empty() or r[m_item_ix].compare(m_value) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void str(std::ostream &os) const override
|
||||
{
|
||||
os << '(' << m_item_name << " == " << m_value << " OR " << m_item_name << " IS NULL)";
|
||||
}
|
||||
|
||||
virtual std::optional<row_handle> single() const override
|
||||
{
|
||||
return m_single_hit;
|
||||
}
|
||||
|
||||
virtual bool equals(const condition_impl *rhs) const override
|
||||
{
|
||||
if (typeid(*rhs) == typeid(key_equals_number_or_empty_condition_impl))
|
||||
{
|
||||
auto ri = static_cast<const key_equals_number_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
|
||||
// watch out, both m_item_ix might be the same while item_names might be diffent (in case they both do not exist in the category)
|
||||
return m_item_ix == ri->m_item_ix and m_value == ri->m_value and m_item_name == ri->m_item_name;
|
||||
}
|
||||
return this == rhs;
|
||||
}
|
||||
|
||||
std::string m_item_name;
|
||||
uint16_t m_item_ix = 0;
|
||||
double m_value;
|
||||
std::optional<row_handle> m_single_hit;
|
||||
};
|
||||
|
||||
struct key_compare_condition_impl : public condition_impl
|
||||
{
|
||||
template <typename COMP>
|
||||
@@ -876,7 +977,8 @@ inline condition operator or(condition &&a, condition &&b)
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
else if (typeid(*b.m_impl) == typeid(detail::key_equals_condition_impl) and
|
||||
|
||||
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);
|
||||
@@ -886,6 +988,26 @@ inline condition operator or(condition &&a, condition &&b)
|
||||
return condition(new detail::key_equals_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
if (typeid(*a.m_impl) == typeid(detail::key_equals_number_condition_impl) and
|
||||
typeid(*b.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_number_condition_impl *>(a.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(b.m_impl);
|
||||
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_number_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
if (typeid(*b.m_impl) == typeid(detail::key_equals_number_condition_impl) and
|
||||
typeid(*a.m_impl) == typeid(detail::key_is_empty_condition_impl))
|
||||
{
|
||||
auto ci = static_cast<detail::key_equals_number_condition_impl *>(b.m_impl);
|
||||
auto ce = static_cast<detail::key_is_empty_condition_impl *>(a.m_impl);
|
||||
|
||||
if (ci->m_item_name == ce->m_item_name)
|
||||
return condition(new detail::key_equals_number_or_empty_condition_impl(ci));
|
||||
}
|
||||
|
||||
return condition(new detail::or_condition_impl(std::move(a), std::move(b)));
|
||||
}
|
||||
|
||||
@@ -959,13 +1081,16 @@ struct key
|
||||
std::string m_item_name; ///< The item name
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
concept Numeric = ((std::is_floating_point_v<T> or std::is_integral_v<T>) and not std::is_same_v<T, bool>);
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a numeric value @a v
|
||||
*/
|
||||
template <Numeric T>
|
||||
condition operator==(const key &key, const T &v)
|
||||
{
|
||||
return condition(new detail::key_equals_condition_impl({ key.m_item_name, v }));
|
||||
return condition(new detail::key_equals_number_condition_impl(key.m_item_name, v));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -979,6 +1104,16 @@ inline condition operator==(const key &key, std::string_view value)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create an equals condition based on a key @a key and a value @a value
|
||||
*/
|
||||
template <typename T>
|
||||
requires std::is_same_v<T, bool>
|
||||
inline condition operator==(const key &key, T value)
|
||||
{
|
||||
return condition(new detail::key_equals_condition_impl({ key.m_item_name, value ? "y" : "n" }));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a not equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
@@ -999,7 +1134,7 @@ inline condition operator!=(const key &key, std::string_view value)
|
||||
/**
|
||||
* @brief Operator to create a greater than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator>(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1007,14 +1142,14 @@ condition operator>(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) > 0; },
|
||||
{ return r[item_name].compare(v) > 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a greater than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator>=(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1022,14 +1157,14 @@ condition operator>=(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) >= 0; },
|
||||
{ return r[item_name].compare(v) >= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator<(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1037,14 +1172,14 @@ condition operator<(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) < 0; },
|
||||
{ return r[item_name].compare(v) < 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
template <typename T>
|
||||
template <Numeric T>
|
||||
condition operator<=(const key &key, const T &v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
@@ -1052,7 +1187,63 @@ condition operator<=(const key &key, const T &v)
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].template compare<T>(v, icase) <= 0; },
|
||||
{ return r[item_name].compare(v) <= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a greater than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator>(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " > " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) > 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a greater than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator>=(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " >= " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) >= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator<(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " < " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) < 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a less than or equals condition based on a key @a key and a value @a v
|
||||
*/
|
||||
inline condition operator<=(const key &key, std::string_view v)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << " <= " << v;
|
||||
|
||||
return condition(new detail::key_compare_condition_impl(
|
||||
key.m_item_name, [item_name = key.m_item_name, v](row_handle r, bool icase)
|
||||
{ return r[item_name].compare(v, icase) <= 0; },
|
||||
s.str()));
|
||||
}
|
||||
|
||||
@@ -1093,6 +1284,19 @@ condition operator==(const key &key, const std::optional<T> &v)
|
||||
return condition(new detail::key_is_empty_condition_impl(key.m_item_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a condition to search any item for a value @a v if @a v contains a value
|
||||
* compare to null if not.
|
||||
*/
|
||||
template <typename T>
|
||||
condition operator!=(const key &key, const std::optional<T> &v)
|
||||
{
|
||||
if (v.has_value())
|
||||
return condition(new detail::not_condition_impl(condition(new detail::key_equals_condition_impl({ key.m_item_name, *v }))));
|
||||
else
|
||||
return condition(new detail::not_condition_impl(condition(new detail::key_is_empty_condition_impl(key.m_item_name))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Operator to create a boolean opposite of the condition in @a rhs
|
||||
*/
|
||||
@@ -1146,7 +1350,7 @@ namespace literals
|
||||
* @param length The length of @a text
|
||||
* @return key The cif::key created
|
||||
*/
|
||||
inline key operator""_key(const char *text, size_t length)
|
||||
inline key operator""_key(const char *text, std::size_t length)
|
||||
{
|
||||
return key(std::string(text, length));
|
||||
}
|
||||
|
||||
@@ -61,12 +61,26 @@ class datablock : public std::list<category>
|
||||
|
||||
/** @cond */
|
||||
datablock(const datablock &);
|
||||
datablock(datablock &&) = default;
|
||||
|
||||
datablock &operator=(const datablock &);
|
||||
datablock &operator=(datablock &&) = default;
|
||||
datablock(datablock &&db) noexcept
|
||||
{
|
||||
swap_(*this, db);
|
||||
}
|
||||
|
||||
datablock &operator=(datablock db)
|
||||
{
|
||||
swap_(*this, db);
|
||||
return *this;
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
friend void swap_(datablock &a, datablock &b) noexcept
|
||||
{
|
||||
std::swap(a.m_name, b.m_name);
|
||||
std::swap(a.m_validator, b.m_validator);
|
||||
std::swap(static_cast<std::list<category>&>(a), static_cast<std::list<category>&>(b));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,11 +85,11 @@ class file : public std::list<datablock>
|
||||
* @param data The pointer to the character string with data to load
|
||||
* @param length The length of the data
|
||||
*/
|
||||
explicit file(const char *data, size_t length)
|
||||
explicit file(const char *data, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -100,10 +100,22 @@ class file : public std::list<datablock>
|
||||
}
|
||||
|
||||
/** @cond */
|
||||
file(const file &) = default;
|
||||
file(file &&) = default;
|
||||
file &operator=(const file &) = default;
|
||||
file &operator=(file &&) = default;
|
||||
file(const file &rhs)
|
||||
: std::list<datablock>(rhs)
|
||||
{
|
||||
}
|
||||
|
||||
file(file &&rhs)
|
||||
{
|
||||
this->swap(rhs);
|
||||
}
|
||||
|
||||
file &operator=(file f)
|
||||
{
|
||||
this->swap(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
|
||||
@@ -125,7 +125,7 @@ class format_plus_arg
|
||||
|
||||
private:
|
||||
|
||||
template <size_t... I>
|
||||
template <std::size_t... I>
|
||||
void copy_vargs(std::index_sequence<I...>)
|
||||
{
|
||||
((std::get<I>(m_vargs) = *std::get<I>(m_args)), ...);
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace cif::gzio
|
||||
{
|
||||
|
||||
/** The default buffer size to use */
|
||||
const size_t kDefaultBufferSize = 256;
|
||||
const std::size_t kDefaultBufferSize = 256;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -112,7 +112,7 @@ class basic_streambuf : public std::basic_streambuf<CharT, Traits>
|
||||
/// This implementation of streambuf can decompress (inflate) data compressed
|
||||
/// using zlib.
|
||||
|
||||
template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSize>
|
||||
template <typename CharT, typename Traits, std::size_t BufferSize = kDefaultBufferSize>
|
||||
class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
|
||||
{
|
||||
public:
|
||||
@@ -317,7 +317,7 @@ class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
|
||||
///
|
||||
/// This implementation of streambuf can compress (deflate) data using zlib.
|
||||
|
||||
template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSize>
|
||||
template <typename CharT, typename Traits, std::size_t BufferSize = kDefaultBufferSize>
|
||||
class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -117,11 +117,9 @@ class item
|
||||
char buffer[32];
|
||||
|
||||
auto r = to_chars(buffer, buffer + sizeof(buffer) - 1, value, chars_format::fixed, precision);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
throw std::runtime_error("Could not format number");
|
||||
|
||||
assert(r.ptr >= buffer and r.ptr < buffer + sizeof(buffer));
|
||||
*r.ptr = 0;
|
||||
m_value.assign(buffer, r.ptr - buffer);
|
||||
}
|
||||
|
||||
@@ -138,11 +136,9 @@ class item
|
||||
char buffer[32];
|
||||
|
||||
auto r = to_chars(buffer, buffer + sizeof(buffer) - 1, value, chars_format::general);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
throw std::runtime_error("Could not format number");
|
||||
|
||||
assert(r.ptr >= buffer and r.ptr < buffer + sizeof(buffer));
|
||||
*r.ptr = 0;
|
||||
m_value.assign(buffer, r.ptr - buffer);
|
||||
}
|
||||
|
||||
@@ -155,11 +151,9 @@ class item
|
||||
char buffer[32];
|
||||
|
||||
auto r = std::to_chars(buffer, buffer + sizeof(buffer) - 1, value);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
throw std::runtime_error("Could not format number");
|
||||
|
||||
assert(r.ptr >= buffer and r.ptr < buffer + sizeof(buffer));
|
||||
*r.ptr = 0;
|
||||
m_value.assign(buffer, r.ptr - buffer);
|
||||
}
|
||||
|
||||
@@ -174,12 +168,21 @@ class item
|
||||
|
||||
/// \brief constructor for an item with name \a name and as
|
||||
/// content value \a value
|
||||
item(const std::string_view name, const std::string_view value)
|
||||
item(const std::string_view name, std::string_view value)
|
||||
: m_name(name)
|
||||
, m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief constructor for an item with name \a name and as
|
||||
/// content value \a value
|
||||
template<typename T, std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
|
||||
item(const std::string_view name, T &&value)
|
||||
: m_name(name)
|
||||
, m_value(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief constructor for an item with name \a name and as
|
||||
/// content the optional value \a value
|
||||
template <typename T>
|
||||
@@ -219,7 +222,8 @@ class item
|
||||
/** @endcond */
|
||||
|
||||
std::string_view name() const { return m_name; } ///< Return the name of the item
|
||||
std::string_view value() const { return m_value; } ///< Return the value of the item
|
||||
std::string_view value() const & { return m_value; } ///< Return the value of the item
|
||||
std::string value() const && { return std::move(m_value); } ///< Return the value of the item
|
||||
|
||||
/// \brief replace the content of the stored value with \a v
|
||||
void value(std::string_view v) { m_value = v; }
|
||||
@@ -234,10 +238,10 @@ class item
|
||||
bool is_unknown() const { return m_value == "?"; }
|
||||
|
||||
/// \brief the length of the value string
|
||||
size_t length() const { return m_value.length(); }
|
||||
std::size_t length() const { return m_value.length(); }
|
||||
|
||||
/// \brief support for structured binding
|
||||
template <size_t N>
|
||||
template <std::size_t N>
|
||||
decltype(auto) get() const
|
||||
{
|
||||
if constexpr (N == 0)
|
||||
@@ -284,19 +288,16 @@ struct item_value
|
||||
}
|
||||
|
||||
/** @cond */
|
||||
item_value(item_value &&rhs)
|
||||
item_value(item_value &&rhs) noexcept
|
||||
: m_length(std::exchange(rhs.m_length, 0))
|
||||
, m_storage(std::exchange(rhs.m_storage, 0))
|
||||
{
|
||||
}
|
||||
|
||||
item_value &operator=(item_value &&rhs)
|
||||
item_value &operator=(item_value &&rhs) noexcept
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
m_length = std::exchange(rhs.m_length, m_length);
|
||||
m_storage = std::exchange(rhs.m_storage, m_storage);
|
||||
}
|
||||
std::swap(m_length, rhs.m_length);
|
||||
std::swap(m_storage, rhs.m_storage);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -318,7 +319,7 @@ struct item_value
|
||||
return m_length != 0;
|
||||
}
|
||||
|
||||
size_t m_length = 0; ///< Length of the data
|
||||
std::size_t m_length = 0; ///< Length of the data
|
||||
union
|
||||
{
|
||||
char m_local_data[8]; ///< Storage area for small strings (strings smaller than kBufferSize)
|
||||
@@ -327,7 +328,7 @@ struct item_value
|
||||
};
|
||||
|
||||
/** The maximum length of locally stored strings */
|
||||
static constexpr size_t kBufferSize = sizeof(m_local_data);
|
||||
static constexpr std::size_t kBufferSize = sizeof(m_local_data);
|
||||
|
||||
// By using std::string_view instead of c_str we obain a
|
||||
// nice performance gain since we avoid many calls to strlen.
|
||||
@@ -363,8 +364,35 @@ struct item_handle
|
||||
template <typename T>
|
||||
item_handle &operator=(const T &value)
|
||||
{
|
||||
item v{ "", value };
|
||||
assign_value(v);
|
||||
assign_value(item{ "", value }.value());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign value @a value to the item referenced
|
||||
*
|
||||
* @tparam T Type of the value
|
||||
* @param value The value
|
||||
* @return reference to this item_handle
|
||||
*/
|
||||
template <typename T>
|
||||
item_handle &operator=(T &&value)
|
||||
{
|
||||
assign_value(item{ "", std::forward<T>(value) }.value());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign value @a value to the item referenced
|
||||
*
|
||||
* @tparam T Type of the value
|
||||
* @param value The value
|
||||
* @return reference to this item_handle
|
||||
*/
|
||||
template <std::size_t N>
|
||||
item_handle &operator=(const char (&value)[N])
|
||||
{
|
||||
assign_value(item{ "", std::move(value) }.value());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -508,7 +536,7 @@ struct item_handle
|
||||
uint16_t m_item_ix;
|
||||
row_handle &m_row_handle;
|
||||
|
||||
void assign_value(const item &value);
|
||||
void assign_value(std::string_view value);
|
||||
};
|
||||
|
||||
// So sad that older gcc implementations of from_chars did not support floats yet...
|
||||
@@ -532,7 +560,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
|
||||
|
||||
std::from_chars_result r = (b + 1 < e and *b == '+' and std::isdigit(b[1])) ? selected_charconv<value_type>::from_chars(b + 1, e, result) : selected_charconv<value_type>::from_chars(b, e, result);
|
||||
|
||||
if (r.ec != std::errc() or r.ptr != e)
|
||||
if ((bool)r.ec or r.ptr != e)
|
||||
{
|
||||
result = {};
|
||||
if (cif::VERBOSE)
|
||||
@@ -567,7 +595,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
|
||||
|
||||
std::from_chars_result r = (b + 1 < e and *b == '+' and std::isdigit(b[1])) ? selected_charconv<value_type>::from_chars(b + 1, e, v) : selected_charconv<value_type>::from_chars(b, e, v);
|
||||
|
||||
if (r.ec != std::errc() or r.ptr != e)
|
||||
if ((bool)r.ec or r.ptr != e)
|
||||
{
|
||||
if (cif::VERBOSE)
|
||||
{
|
||||
@@ -580,6 +608,8 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
|
||||
}
|
||||
result = 1;
|
||||
}
|
||||
else if (std::abs(v - value) <= std::numeric_limits<value_type>::epsilon())
|
||||
result = 0;
|
||||
else if (v < value)
|
||||
result = -1;
|
||||
else if (v > value)
|
||||
@@ -634,7 +664,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, bool>>>
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
template <std::size_t N>
|
||||
struct item_handle::item_value_as<char[N]>
|
||||
{
|
||||
static std::string convert(const item_handle &ref)
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace cif
|
||||
/**
|
||||
* @brief Implementation of an iterator that can return
|
||||
* multiple values in a tuple. Of course, that tuple can
|
||||
* then used in structured binding to receive the values
|
||||
* then be used in structured binding to receive the values
|
||||
* in a for loop e.g.
|
||||
*
|
||||
* @tparam Category The category for this iterator
|
||||
@@ -67,7 +67,7 @@ class iterator_impl
|
||||
/** @endcond */
|
||||
|
||||
/** variable that contains the number of elements in the tuple */
|
||||
static constexpr size_t N = sizeof...(Ts);
|
||||
static constexpr std::size_t N = sizeof...(Ts);
|
||||
|
||||
/** @cond */
|
||||
using category_type = std::remove_cv_t<Category>;
|
||||
@@ -84,11 +84,11 @@ class iterator_impl
|
||||
iterator_impl() = default;
|
||||
|
||||
iterator_impl(const iterator_impl &rhs) = default;
|
||||
iterator_impl(iterator_impl &&rhs) = default;
|
||||
|
||||
template <typename C2, typename... T2s>
|
||||
iterator_impl(const iterator_impl<C2, T2s...> &rhs)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(rhs.m_current)
|
||||
: m_current(const_cast<row_handle&>(rhs.m_current))
|
||||
, m_value(rhs.m_value)
|
||||
, m_item_ix(rhs.m_item_ix)
|
||||
{
|
||||
@@ -96,8 +96,7 @@ class iterator_impl
|
||||
|
||||
template <typename IRowType>
|
||||
iterator_impl(iterator_impl<IRowType, Ts...> &rhs)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(const_cast<row_type *>(rhs.m_current))
|
||||
: m_current(const_cast<row_handle&>(rhs.m_current))
|
||||
, m_value(rhs.m_value)
|
||||
, m_item_ix(rhs.m_item_ix)
|
||||
{
|
||||
@@ -106,19 +105,17 @@ class iterator_impl
|
||||
|
||||
template <typename IRowType>
|
||||
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, N> &cix)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(rhs.m_current)
|
||||
: m_current(const_cast<row_handle&>(rhs.m_current))
|
||||
, m_item_ix(cix)
|
||||
{
|
||||
m_value = get(std::make_index_sequence<N>());
|
||||
}
|
||||
|
||||
iterator_impl &operator=(const iterator_impl &i)
|
||||
iterator_impl &operator=(iterator_impl i)
|
||||
{
|
||||
m_category = i.m_category;
|
||||
m_current = i.m_current;
|
||||
m_item_ix = i.m_item_ix;
|
||||
m_value = i.m_value;
|
||||
std::swap(m_current, i.m_current);
|
||||
std::swap(m_item_ix, i.m_item_ix);
|
||||
std::swap(m_value, i.m_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -136,18 +133,18 @@ class iterator_impl
|
||||
|
||||
operator const row_handle() const
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
operator row_handle()
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
iterator_impl &operator++()
|
||||
{
|
||||
if (m_current != nullptr)
|
||||
m_current = m_current->m_next;
|
||||
if (m_current)
|
||||
m_current.m_row = m_current.m_row->m_next;
|
||||
|
||||
m_value = get(std::make_index_sequence<N>());
|
||||
|
||||
@@ -179,20 +176,13 @@ class iterator_impl
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
template <size_t... Is>
|
||||
template <std::size_t... Is>
|
||||
tuple_type get(std::index_sequence<Is...>) const
|
||||
{
|
||||
if (m_current != nullptr)
|
||||
{
|
||||
row_handle rh{ *m_category, *m_current };
|
||||
return tuple_type{ rh[m_item_ix[Is]].template as<Ts>()... };
|
||||
}
|
||||
|
||||
return {};
|
||||
return m_current ? tuple_type{ m_current[m_item_ix[Is]].template as<Ts>()... } : tuple_type{};
|
||||
}
|
||||
|
||||
category_type *m_category = nullptr;
|
||||
row_type *m_current = nullptr;
|
||||
row_handle m_current;
|
||||
value_type m_value;
|
||||
std::array<uint16_t, N> m_item_ix;
|
||||
};
|
||||
@@ -219,37 +209,34 @@ class iterator_impl<Category>
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = row_handle;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = row_handle;
|
||||
using reference = row_handle;
|
||||
using pointer = value_type *;
|
||||
using reference = value_type &;
|
||||
|
||||
iterator_impl() = default;
|
||||
|
||||
iterator_impl(const iterator_impl &rhs) = default;
|
||||
iterator_impl(iterator_impl &&rhs) = default;
|
||||
|
||||
template <typename C2>
|
||||
iterator_impl(const iterator_impl<C2> &rhs)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(const_cast<row_type *>(rhs.m_current))
|
||||
: m_current(const_cast<row_handle &>(rhs.m_current))
|
||||
{
|
||||
}
|
||||
|
||||
iterator_impl(Category &cat, row *current)
|
||||
: m_category(const_cast<category_type *>(&cat))
|
||||
, m_current(current)
|
||||
: m_current(cat, *current)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename IRowType>
|
||||
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 0> &)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(rhs.m_current)
|
||||
: m_current(const_cast<row_handle &>(rhs.m_current))
|
||||
{
|
||||
}
|
||||
|
||||
iterator_impl &operator=(const iterator_impl &i)
|
||||
iterator_impl &operator=(iterator_impl i)
|
||||
{
|
||||
m_category = i.m_category;
|
||||
m_current = i.m_current;
|
||||
std::swap(m_current, i.m_current);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -257,7 +244,7 @@ class iterator_impl<Category>
|
||||
|
||||
reference operator*()
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
pointer operator->()
|
||||
@@ -267,18 +254,18 @@ class iterator_impl<Category>
|
||||
|
||||
operator const row_handle() const
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
operator row_handle()
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
iterator_impl &operator++()
|
||||
{
|
||||
if (m_current != nullptr)
|
||||
m_current = m_current->m_next;
|
||||
if (m_current)
|
||||
m_current.m_row = m_current.m_row->m_next;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -308,8 +295,7 @@ class iterator_impl<Category>
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
category_type *m_category = nullptr;
|
||||
row_type *m_current = nullptr;
|
||||
row_handle m_current;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -342,11 +328,11 @@ class iterator_impl<Category, T>
|
||||
iterator_impl() = default;
|
||||
|
||||
iterator_impl(const iterator_impl &rhs) = default;
|
||||
iterator_impl(iterator_impl &&rhs) = default;
|
||||
|
||||
template <typename C2, typename T2>
|
||||
iterator_impl(const iterator_impl<C2, T2> &rhs)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(rhs.m_current)
|
||||
: m_current(rhs.m_current)
|
||||
, m_value(rhs.m_value)
|
||||
, m_item_ix(rhs.m_item_ix)
|
||||
{
|
||||
@@ -354,29 +340,26 @@ class iterator_impl<Category, T>
|
||||
|
||||
template <typename IRowType>
|
||||
iterator_impl(iterator_impl<IRowType, T> &rhs)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(const_cast<row_type *>(rhs.m_current))
|
||||
: m_current(const_cast<row_handle&>(rhs.m_current))
|
||||
, m_value(rhs.m_value)
|
||||
, m_item_ix(rhs.m_item_ix)
|
||||
{
|
||||
m_value = get(m_current);
|
||||
m_value = get();
|
||||
}
|
||||
|
||||
template <typename IRowType>
|
||||
iterator_impl(const iterator_impl<IRowType> &rhs, const std::array<uint16_t, 1> &cix)
|
||||
: m_category(rhs.m_category)
|
||||
, m_current(rhs.m_current)
|
||||
: m_current(const_cast<row_handle&>(rhs.m_current))
|
||||
, m_item_ix(cix[0])
|
||||
{
|
||||
m_value = get();
|
||||
}
|
||||
|
||||
iterator_impl &operator=(const iterator_impl &i)
|
||||
iterator_impl &operator=(iterator_impl i)
|
||||
{
|
||||
m_category = i.m_category;
|
||||
m_current = i.m_current;
|
||||
m_item_ix = i.m_item_ix;
|
||||
m_value = i.m_value;
|
||||
std::swap(m_current, i.m_current);
|
||||
std::swap(m_item_ix, i.m_item_ix);
|
||||
std::swap(m_value, i.m_value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -394,18 +377,18 @@ class iterator_impl<Category, T>
|
||||
|
||||
operator const row_handle() const
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
operator row_handle()
|
||||
{
|
||||
return { *m_category, *m_current };
|
||||
return m_current;
|
||||
}
|
||||
|
||||
iterator_impl &operator++()
|
||||
{
|
||||
if (m_current != nullptr)
|
||||
m_current = m_current->m_next;
|
||||
if (m_current)
|
||||
m_current.m_row = m_current.m_row->m_next;
|
||||
|
||||
m_value = get();
|
||||
|
||||
@@ -439,17 +422,10 @@ class iterator_impl<Category, T>
|
||||
private:
|
||||
value_type get() const
|
||||
{
|
||||
if (m_current != nullptr)
|
||||
{
|
||||
row_handle rh{ *m_category, *m_current };
|
||||
return rh[m_item_ix].template as<T>();
|
||||
}
|
||||
|
||||
return {};
|
||||
return m_current ? m_current[m_item_ix].template as<value_type>() : value_type{};
|
||||
}
|
||||
|
||||
category_type *m_category = nullptr;
|
||||
row_type *m_current = nullptr;
|
||||
row_handle m_current;
|
||||
value_type m_value;
|
||||
uint16_t m_item_ix;
|
||||
};
|
||||
@@ -474,7 +450,7 @@ class iterator_proxy
|
||||
{
|
||||
public:
|
||||
/** @cond */
|
||||
static constexpr const size_t N = sizeof...(Ts);
|
||||
static constexpr const std::size_t N = sizeof...(Ts);
|
||||
|
||||
using category_type = Category;
|
||||
using row_type = std::conditional_t<std::is_const_v<category_type>, const row, row>;
|
||||
@@ -497,7 +473,7 @@ class iterator_proxy
|
||||
|
||||
bool empty() const { return m_begin == m_end; } ///< Return true if the range is empty
|
||||
explicit operator bool() const { return not empty(); } ///< Easy way to detect if the range is empty
|
||||
size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
std::size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
|
||||
// row front() { return *begin(); }
|
||||
// row back() { return *(std::prev(end())); }
|
||||
@@ -536,7 +512,7 @@ class conditional_iterator_proxy
|
||||
{
|
||||
public:
|
||||
/** @cond */
|
||||
static constexpr const size_t N = sizeof...(Ts);
|
||||
static constexpr const std::size_t N = sizeof...(Ts);
|
||||
|
||||
using category_type = std::remove_cv_t<CategoryType>;
|
||||
|
||||
@@ -630,7 +606,7 @@ class conditional_iterator_proxy
|
||||
|
||||
bool empty() const; ///< Return true if the range is empty
|
||||
explicit operator bool() const { return not empty(); } ///< Easy way to detect if the range is empty
|
||||
size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
std::size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
|
||||
|
||||
row_handle front() { return *begin(); } ///< Return reference to the first row
|
||||
// row_handle back() { return *begin(); }
|
||||
|
||||
@@ -59,27 +59,27 @@ template <typename M>
|
||||
class matrix_expression
|
||||
{
|
||||
public:
|
||||
constexpr size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); } ///< Return the size (dimension) in direction m
|
||||
constexpr size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); } ///< Return the size (dimension) in direction n
|
||||
constexpr std::size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); } ///< Return the size (dimension) in direction m
|
||||
constexpr std::size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); } ///< Return the size (dimension) in direction n
|
||||
|
||||
constexpr bool empty() const { return dim_m() == 0 or dim_n() == 0; } ///< Convenient way to test for empty matrices
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr auto &operator()(size_t i, size_t j)
|
||||
constexpr auto &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
return static_cast<M &>(*this).operator()(i, j);
|
||||
}
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return static_cast<const M &>(*this).operator()(i, j);
|
||||
}
|
||||
|
||||
/** Swap the contents of rows @a r1 and @a r2 */
|
||||
void swap_row(size_t r1, size_t r2)
|
||||
void swap_row(std::size_t r1, std::size_t r2)
|
||||
{
|
||||
for (size_t c = 0; c < dim_m(); ++c)
|
||||
for (std::size_t c = 0; c < dim_m(); ++c)
|
||||
{
|
||||
auto v = operator()(r1, c);
|
||||
operator()(r1, c) = operator()(r2, c);
|
||||
@@ -88,9 +88,9 @@ class matrix_expression
|
||||
}
|
||||
|
||||
/** Swap the contents of columns @a c1 and @a c2 */
|
||||
void swap_col(size_t c1, size_t c2)
|
||||
void swap_col(std::size_t c1, std::size_t c2)
|
||||
{
|
||||
for (size_t r = 0; r < dim_n(); ++r)
|
||||
for (std::size_t r = 0; r < dim_n(); ++r)
|
||||
{
|
||||
auto &a = operator()(r, c1);
|
||||
auto &b = operator()(r, c2);
|
||||
@@ -103,11 +103,11 @@ class matrix_expression
|
||||
{
|
||||
os << '[';
|
||||
|
||||
for (size_t i = 0; i < m.dim_m(); ++i)
|
||||
for (std::size_t i = 0; i < m.dim_m(); ++i)
|
||||
{
|
||||
os << '[';
|
||||
|
||||
for (size_t j = 0; j < m.dim_n(); ++j)
|
||||
for (std::size_t j = 0; j < m.dim_n(); ++j)
|
||||
{
|
||||
os << m(i, j);
|
||||
if (j + 1 < m.dim_n())
|
||||
@@ -156,9 +156,9 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
, m_n(m.dim_n())
|
||||
, m_data(m_m * m_n)
|
||||
{
|
||||
for (size_t i = 0; i < m_m; ++i)
|
||||
for (std::size_t i = 0; i < m_m; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < m_n; ++j)
|
||||
for (std::size_t j = 0; j < m_n; ++j)
|
||||
operator()(i, j) = m(i, j);
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
* @param n Requested dimension N
|
||||
* @param v Value to store in each element
|
||||
*/
|
||||
matrix(size_t m, size_t n, value_type v = 0)
|
||||
matrix(std::size_t m, std::size_t n, value_type v = 0)
|
||||
: m_m(m)
|
||||
, m_n(n)
|
||||
, m_data(m_m * m_n)
|
||||
@@ -187,11 +187,11 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
matrix &operator=(const matrix &m) = default;
|
||||
/** @endcond */
|
||||
|
||||
constexpr size_t dim_m() const { return m_m; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
@@ -199,7 +199,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
assert(i < m_m);
|
||||
assert(j < m_n);
|
||||
@@ -207,7 +207,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_m = 0, m_n = 0;
|
||||
std::size_t m_m = 0, m_n = 0;
|
||||
std::vector<value_type> m_data;
|
||||
};
|
||||
|
||||
@@ -224,7 +224,7 @@ class matrix : public matrix_expression<matrix<F>>
|
||||
* element m i,j is mapped to [i * n + j] and thus storage is row major
|
||||
*/
|
||||
|
||||
template <typename F, size_t M, size_t N>
|
||||
template <typename F, std::size_t M, std::size_t N>
|
||||
class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
{
|
||||
public:
|
||||
@@ -232,16 +232,16 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
using value_type = F;
|
||||
|
||||
/** The storage size */
|
||||
static constexpr size_t kSize = M * N;
|
||||
static constexpr std::size_t kSize = M * N;
|
||||
|
||||
/** Copy constructor */
|
||||
template <typename M2>
|
||||
matrix_fixed(const M2 &m)
|
||||
{
|
||||
assert(M == m.dim_m() and N == m.dim_n());
|
||||
for (size_t i = 0; i < M; ++i)
|
||||
for (std::size_t i = 0; i < M; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < N; ++j)
|
||||
for (std::size_t j = 0; j < N; ++j)
|
||||
operator()(i, j) = m(i, j);
|
||||
}
|
||||
}
|
||||
@@ -266,18 +266,18 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
/** @endcond */
|
||||
|
||||
/** Store the values in @a a in the matrix */
|
||||
template<size_t... Ixs>
|
||||
template<std::size_t... Ixs>
|
||||
matrix_fixed& fill(const F (&a)[kSize], std::index_sequence<Ixs...>)
|
||||
{
|
||||
m_data = { a[Ixs]... };
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return N; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return N; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
assert(i < M);
|
||||
assert(j < N);
|
||||
@@ -285,7 +285,7 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
assert(i < M);
|
||||
assert(j < N);
|
||||
@@ -322,7 +322,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
using value_type = F;
|
||||
|
||||
/** constructor for a matrix of size @a n x @a n elements with value @a v */
|
||||
symmetric_matrix(size_t n, value_type v = 0)
|
||||
symmetric_matrix(std::size_t n, value_type v = 0)
|
||||
: m_n(n)
|
||||
, m_data((m_n * (m_n + 1)) / 2)
|
||||
{
|
||||
@@ -337,11 +337,11 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
symmetric_matrix &operator=(const symmetric_matrix &m) = default;
|
||||
/** @endcond */
|
||||
|
||||
constexpr size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return i < j
|
||||
? m_data[(j * (j + 1)) / 2 + i]
|
||||
@@ -349,7 +349,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
if (i > j)
|
||||
std::swap(i, j);
|
||||
@@ -358,7 +358,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_n;
|
||||
std::size_t m_n;
|
||||
std::vector<value_type> m_data;
|
||||
};
|
||||
|
||||
@@ -373,7 +373,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
|
||||
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
|
||||
* element m i,j is mapped to [i * n + j] and thus storage is row major
|
||||
*/
|
||||
template <typename F, size_t M>
|
||||
template <typename F, std::size_t M>
|
||||
class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F, M>>
|
||||
{
|
||||
public:
|
||||
@@ -393,11 +393,11 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
|
||||
symmetric_matrix_fixed &operator=(const symmetric_matrix_fixed &m) = default;
|
||||
/** @endcond */
|
||||
|
||||
constexpr size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return M; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return M; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return M; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return i < j
|
||||
? m_data[(j * (j + 1)) / 2 + i]
|
||||
@@ -405,7 +405,7 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
|
||||
}
|
||||
|
||||
/** Return a reference to element [ @a i, @a j ] */
|
||||
constexpr value_type &operator()(size_t i, size_t j)
|
||||
constexpr value_type &operator()(std::size_t i, std::size_t j)
|
||||
{
|
||||
if (i > j)
|
||||
std::swap(i, j);
|
||||
@@ -444,22 +444,22 @@ class identity_matrix : public matrix_expression<identity_matrix<F>>
|
||||
using value_type = F;
|
||||
|
||||
/** constructor taking a dimension @a n */
|
||||
identity_matrix(size_t n)
|
||||
identity_matrix(std::size_t n)
|
||||
: m_n(n)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_n; } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_n; } ///< Return dimension n
|
||||
|
||||
/** Return the value of element [ @a i, @a j ] */
|
||||
constexpr value_type operator()(size_t i, size_t j) const
|
||||
constexpr value_type operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return static_cast<value_type>(i == j ? 1 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_n;
|
||||
std::size_t m_n;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -484,11 +484,11 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
|
||||
assert(m_m1.dim_n() == m_m2.dim_n());
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return m_m1(i, j) - m_m2(i, j);
|
||||
}
|
||||
@@ -523,17 +523,17 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult
|
||||
assert(m1.dim_m() == m2.dim_n());
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
using value_type = decltype(m_m1(0, 0));
|
||||
|
||||
value_type result = {};
|
||||
|
||||
for (size_t k = 0; k < m_m1.dim_m(); ++k)
|
||||
for (std::size_t k = 0; k < m_m1.dim_m(); ++k)
|
||||
result += m_m1(i, k) * m_m2(k, j);
|
||||
|
||||
return result;
|
||||
@@ -564,11 +564,11 @@ class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_mult
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
return m_m(i, j) * m_v;
|
||||
}
|
||||
@@ -655,21 +655,21 @@ class matrix_cofactors : public matrix_expression<matrix_cofactors<M>>
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
constexpr std::size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
|
||||
constexpr std::size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
|
||||
|
||||
/** Access to the value of element [ @a i, @a j ] */
|
||||
constexpr auto operator()(size_t i, size_t j) const
|
||||
constexpr auto operator()(std::size_t i, std::size_t j) const
|
||||
{
|
||||
const size_t ixs[4][3] = {
|
||||
const std::size_t ixs[4][3] = {
|
||||
{ 1, 2, 3 },
|
||||
{ 0, 2, 3 },
|
||||
{ 0, 1, 3 },
|
||||
{ 0, 1, 2 }
|
||||
};
|
||||
|
||||
const size_t *ix = ixs[i];
|
||||
const size_t *iy = ixs[j];
|
||||
const std::size_t *ix = ixs[i];
|
||||
const std::size_t *iy = ixs[j];
|
||||
|
||||
auto result =
|
||||
m_m(ix[0], iy[0]) * m_m(ix[1], iy[1]) * m_m(ix[2], iy[2]) +
|
||||
|
||||
@@ -350,7 +350,12 @@ class atom
|
||||
std::string get_pdb_ins_code() const { return get_property("pdbx_PDB_ins_code"); } ///< Return the pdb_ins_code property
|
||||
|
||||
/// Return true if this atom is an alternate
|
||||
bool is_alternate() const { return not get_label_alt_id().empty(); }
|
||||
bool is_alternate() const
|
||||
{
|
||||
if (auto alt_id = get_label_alt_id(); alt_id.empty() or alt_id == ".")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Convenience method to return a string that might be ID in PDB space
|
||||
std::string pdb_id() const
|
||||
@@ -550,6 +555,9 @@ class residue
|
||||
/// \brief Return true if this residue has alternate atoms
|
||||
bool has_alternate_atoms() const;
|
||||
|
||||
/// \brief Return true if this residue has alternate atoms for the atom \a atomID
|
||||
bool has_alternate_atoms_for(const std::string &atomID) const;
|
||||
|
||||
/// \brief Return the list of unique alt ID's present in this residue
|
||||
std::set<std::string> get_alternate_ids() const;
|
||||
|
||||
@@ -572,6 +580,10 @@ class residue
|
||||
m_auth_seq_id == rhs.m_auth_seq_id);
|
||||
}
|
||||
|
||||
/// @brief Create a new atom and add it to the list
|
||||
/// @return newly created atom
|
||||
virtual atom create_new_atom(atom_type inType, const std::string &inAtomID, point inLocation);
|
||||
|
||||
protected:
|
||||
/** @cond */
|
||||
residue() {}
|
||||
@@ -604,7 +616,7 @@ class monomer : public residue
|
||||
monomer &operator=(monomer &&rhs);
|
||||
|
||||
/// \brief constructor with actual values
|
||||
monomer(const polymer &polymer, size_t index, int seqID, const std::string &authSeqID,
|
||||
monomer(const polymer &polymer, std::size_t index, int seqID, const std::string &authSeqID,
|
||||
const std::string &pdbInsCode, const std::string &compoundID);
|
||||
|
||||
bool is_first_in_chain() const; ///< Return if this residue is the first residue in the chain
|
||||
@@ -624,8 +636,8 @@ class monomer : public residue
|
||||
float omega() const; ///< Return the omega value for this residue
|
||||
|
||||
// torsion angles
|
||||
size_t nr_of_chis() const; ///< Return how many torsion angles can be calculated
|
||||
float chi(size_t i) const; ///< Return torsion angle @a i
|
||||
std::size_t nr_of_chis() const; ///< Return how many torsion angles can be calculated
|
||||
float chi(std::size_t i) const; ///< Return torsion angle @a i
|
||||
|
||||
bool is_cis() const; ///< Return true if this residue is in a cis conformation
|
||||
|
||||
@@ -672,9 +684,11 @@ class monomer : public residue
|
||||
return m_polymer == rhs.m_polymer and m_index == rhs.m_index;
|
||||
}
|
||||
|
||||
atom create_new_atom(atom_type inType, const std::string &inAtomID, point inLocation) override;
|
||||
|
||||
private:
|
||||
const polymer *m_polymer;
|
||||
size_t m_index;
|
||||
std::size_t m_index;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -741,7 +755,7 @@ class sugar : public residue
|
||||
{
|
||||
int result;
|
||||
auto r = std::from_chars(m_auth_seq_id.data(), m_auth_seq_id.data() + m_auth_seq_id.length(), result);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
throw std::runtime_error("The auth_seq_id should be a number for a sugar");
|
||||
return result;
|
||||
}
|
||||
@@ -756,9 +770,9 @@ class sugar : public residue
|
||||
void set_link(atom link) { m_link = link; }
|
||||
|
||||
/// \brief Return the sugar number of the sugar linked to C1
|
||||
size_t get_link_nr() const
|
||||
std::size_t get_link_nr() const
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
if (m_link)
|
||||
result = m_link.get_property_int("auth_seq_id");
|
||||
return result;
|
||||
@@ -865,10 +879,10 @@ class structure
|
||||
{
|
||||
public:
|
||||
/// \brief Read the structure from cif::file @a p
|
||||
structure(file &p, size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
structure(file &p, std::size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
|
||||
/// \brief Load the structure from already parsed mmCIF data in @a db
|
||||
structure(datablock &db, size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
structure(datablock &db, std::size_t modelNr = 1, StructureOpenOptions options = {});
|
||||
|
||||
/** @cond */
|
||||
structure(structure &&s) = default;
|
||||
@@ -881,7 +895,7 @@ class structure
|
||||
~structure() = default;
|
||||
|
||||
/// \brief Return the model number
|
||||
size_t get_model_nr() const { return m_model_nr; }
|
||||
std::size_t get_model_nr() const { return m_model_nr; }
|
||||
|
||||
/// \brief Return a list of all the atoms in this structure
|
||||
const std::vector<atom> &atoms() const { return m_atoms; }
|
||||
@@ -1091,6 +1105,9 @@ class structure
|
||||
/// \brief emplace the moved atom @a atom
|
||||
atom &emplace_atom(atom &&atom);
|
||||
|
||||
/// \brief Reorder atom_site atoms based on 'natural' ordering
|
||||
void reorder_atoms();
|
||||
|
||||
private:
|
||||
friend polymer;
|
||||
friend residue;
|
||||
@@ -1107,9 +1124,9 @@ class structure
|
||||
void remove_sugar(sugar &sugar);
|
||||
|
||||
datablock &m_db;
|
||||
size_t m_model_nr;
|
||||
std::size_t m_model_nr;
|
||||
std::vector<atom> m_atoms;
|
||||
std::vector<size_t> m_atom_index;
|
||||
std::vector<std::size_t> m_atom_index;
|
||||
std::list<polymer> m_polymers;
|
||||
std::list<branch> m_branches;
|
||||
std::vector<residue> m_non_polymers;
|
||||
|
||||
@@ -867,7 +867,7 @@ class spherical_dots
|
||||
}
|
||||
|
||||
/// \brief The number of points
|
||||
size_t size() const { return P; }
|
||||
std::size_t size() const { return P; }
|
||||
|
||||
/// \brief Access a point by index
|
||||
const point operator[](uint32_t inIx) const { return m_points[inIx]; }
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace detail
|
||||
template <typename... C>
|
||||
struct get_row_result
|
||||
{
|
||||
static constexpr size_t N = sizeof...(C);
|
||||
static constexpr std::size_t N = sizeof...(C);
|
||||
|
||||
get_row_result(const row_handle &r, std::array<uint16_t, N> &&items)
|
||||
: m_row(r)
|
||||
@@ -104,7 +104,7 @@ namespace detail
|
||||
return get<Ts...>(std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
template <typename... Ts, size_t... Is>
|
||||
template <typename... Ts, std::size_t... Is>
|
||||
std::tuple<Ts...> get(std::index_sequence<Is...>) const
|
||||
{
|
||||
return std::tuple<Ts...>{ m_row[m_items[Is]].template as<Ts>()... };
|
||||
@@ -208,6 +208,7 @@ class row_handle
|
||||
friend class category;
|
||||
friend class category_index;
|
||||
friend class row_initializer;
|
||||
template <typename, typename...> friend class iterator_impl;
|
||||
|
||||
row_handle() = default;
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace literals
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
inline sym_op operator""_symop(const char *text, size_t length)
|
||||
inline sym_op operator""_symop(const char *text, std::size_t length)
|
||||
{
|
||||
return sym_op({ text, length });
|
||||
}
|
||||
@@ -464,7 +464,7 @@ class spacegroup : public std::vector<transformation>
|
||||
|
||||
private:
|
||||
int m_nr;
|
||||
size_t m_index;
|
||||
std::size_t m_index;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -352,7 +352,7 @@ std::string cif_id_for_number(int number);
|
||||
* a dynamic programming approach to get the most efficient filling of
|
||||
* the space.
|
||||
*/
|
||||
std::vector<std::string> word_wrap(const std::string &text, size_t width);
|
||||
std::vector<std::string> word_wrap(const std::string &text, std::size_t width);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/// \brief std::from_chars for floating point types.
|
||||
@@ -378,12 +378,12 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
|
||||
} state = IntegerSign;
|
||||
int sign = 1;
|
||||
unsigned long long vi = 0;
|
||||
long double f = 1;
|
||||
int fl = 0, tz = 0;
|
||||
int exponent_sign = 1;
|
||||
int exponent = 0;
|
||||
bool done = false;
|
||||
|
||||
while (not done and result.ec == std::errc())
|
||||
while (not done and not (bool)result.ec)
|
||||
{
|
||||
char ch = result.ptr != last ? *result.ptr : 0;
|
||||
++result.ptr;
|
||||
@@ -427,7 +427,14 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
|
||||
if (ch >= '0' and ch <= '9')
|
||||
{
|
||||
vi = 10 * vi + (ch - '0');
|
||||
f /= 10;
|
||||
|
||||
if (ch == '0')
|
||||
tz += 1;
|
||||
else
|
||||
{
|
||||
fl += tz + 1;
|
||||
tz = 0;
|
||||
}
|
||||
}
|
||||
else if (ch == 'e' or ch == 'E')
|
||||
state = ExponentSign;
|
||||
@@ -467,9 +474,12 @@ std::from_chars_result from_chars(const char *first, const char *last, FloatType
|
||||
}
|
||||
}
|
||||
|
||||
if (result.ec == std::errc())
|
||||
if (not (bool)result.ec)
|
||||
{
|
||||
long double v = f * vi * sign;
|
||||
while (tz-- > 0)
|
||||
vi /= 10;
|
||||
|
||||
long double v = std::pow(10, -fl) * vi * sign;
|
||||
if (exponent != 0)
|
||||
v *= std::pow(10, exponent * exponent_sign);
|
||||
|
||||
|
||||
@@ -113,16 +113,12 @@ namespace colour
|
||||
/**
|
||||
* @brief Struct for delimited strings.
|
||||
*/
|
||||
template <typename StringType>
|
||||
struct coloured_string_t
|
||||
{
|
||||
static_assert(std::is_reference_v<StringType> or std::is_pointer_v<StringType>,
|
||||
"String type must be pointer or reference");
|
||||
|
||||
/**
|
||||
* @brief Construct a new coloured string t object
|
||||
*/
|
||||
coloured_string_t(StringType s, colour_type fc, colour_type bc, style_type st)
|
||||
coloured_string_t(std::string_view s, colour_type fc, colour_type bc, style_type st)
|
||||
: m_str(s)
|
||||
, m_fore_colour(static_cast<int>(fc) + 30)
|
||||
, m_back_colour(static_cast<int>(bc) + 40)
|
||||
@@ -152,12 +148,14 @@ namespace colour
|
||||
<< cs.m_str
|
||||
<< "\033[0m";
|
||||
}
|
||||
else
|
||||
os << cs.m_str;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
/// @cond
|
||||
StringType m_str;
|
||||
std::string_view m_str;
|
||||
int m_fore_colour, m_back_colour;
|
||||
int m_style;
|
||||
/// @endcond
|
||||
@@ -191,39 +189,13 @@ namespace colour
|
||||
* @param st Text style to use
|
||||
*/
|
||||
|
||||
template <typename char_type>
|
||||
inline auto coloured(const char_type *str,
|
||||
template <typename T>
|
||||
requires std::is_assignable_v<std::string_view, T>
|
||||
inline auto coloured(T str,
|
||||
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
|
||||
colour::style_type st = colour::style_type::regular)
|
||||
{
|
||||
return colour::detail::coloured_string_t<const char_type *>(str, fg, bg, st);
|
||||
}
|
||||
|
||||
/// @brief Manipulator for coloured strings.
|
||||
template <typename char_type, typename traits_type, typename allocator_type>
|
||||
inline auto coloured(const std::basic_string<char_type, traits_type, allocator_type> &str,
|
||||
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
|
||||
colour::style_type st = colour::style_type::regular)
|
||||
{
|
||||
return colour::detail::coloured_string_t<const std::basic_string<char_type, traits_type, allocator_type> &>(str, fg, bg, st);
|
||||
}
|
||||
|
||||
/// @brief Manipulator for coloured strings.
|
||||
template <typename char_type, typename traits_type, typename allocator_type>
|
||||
inline auto coloured(std::basic_string<char_type, traits_type, allocator_type> &str,
|
||||
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
|
||||
colour::style_type st = colour::style_type::regular)
|
||||
{
|
||||
return colour::detail::coloured_string_t<std::basic_string<char_type, traits_type, allocator_type> &>(str, fg, bg, st);
|
||||
}
|
||||
|
||||
/// @brief Manipulator for coloured strings.
|
||||
template <typename char_type, typename traits_type>
|
||||
inline auto coloured(std::basic_string_view<char_type, traits_type> &str,
|
||||
colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
|
||||
colour::style_type st = colour::style_type::regular)
|
||||
{
|
||||
return colour::detail::coloured_string_t<std::basic_string_view<char_type, traits_type> &>(str, fg, bg, st);
|
||||
return colour::detail::coloured_string_t(str, fg, bg, st);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -120,7 +120,7 @@ class validation_category_impl : public std::error_category
|
||||
case validation_error::missing_key_items:
|
||||
return "An index could not be constructed due to missing key items";
|
||||
case validation_error::item_not_allowed_in_category:
|
||||
return "Requested item allowed in category according to dictionary";
|
||||
return "Requested item not allowed in category according to dictionary";
|
||||
case validation_error::empty_file:
|
||||
return "The file contains no datablocks";
|
||||
case validation_error::empty_datablock:
|
||||
|
||||
8337
rsrc/mmcif_pdbx.dic
8337
rsrc/mmcif_pdbx.dic
File diff suppressed because it is too large
Load Diff
194
src/category.cpp
194
src/category.cpp
@@ -164,7 +164,7 @@ class category_index
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t size() const;
|
||||
std::size_t size() const;
|
||||
// bool isValid() const;
|
||||
|
||||
private:
|
||||
@@ -475,12 +475,12 @@ category_index::entry *category_index::erase(category &cat, entry *h, row *k)
|
||||
return fix_up(h);
|
||||
}
|
||||
|
||||
size_t category_index::size() const
|
||||
std::size_t category_index::size() const
|
||||
{
|
||||
std::stack<entry *> s;
|
||||
s.push(m_root);
|
||||
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
while (not s.empty())
|
||||
{
|
||||
@@ -521,71 +521,18 @@ category::category(const category &rhs)
|
||||
m_index = new category_index(*this);
|
||||
}
|
||||
|
||||
category::category(category &&rhs)
|
||||
: m_name(std::move(rhs.m_name))
|
||||
, m_items(std::move(rhs.m_items))
|
||||
, m_validator(rhs.m_validator)
|
||||
, m_cat_validator(rhs.m_cat_validator)
|
||||
, m_parent_links(std::move(rhs.m_parent_links))
|
||||
, m_child_links(std::move(rhs.m_child_links))
|
||||
, m_cascade(rhs.m_cascade)
|
||||
, m_index(rhs.m_index)
|
||||
, m_head(rhs.m_head)
|
||||
, m_tail(rhs.m_tail)
|
||||
void swap(category &a, category &b) noexcept
|
||||
{
|
||||
rhs.m_head = nullptr;
|
||||
rhs.m_tail = nullptr;
|
||||
rhs.m_index = nullptr;
|
||||
}
|
||||
|
||||
category &category::operator=(const category &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
if (not empty())
|
||||
clear();
|
||||
|
||||
m_name = rhs.m_name;
|
||||
m_items = rhs.m_items;
|
||||
m_cascade = rhs.m_cascade;
|
||||
|
||||
m_validator = nullptr;
|
||||
m_cat_validator = nullptr;
|
||||
|
||||
delete m_index;
|
||||
m_index = nullptr;
|
||||
|
||||
for (auto r = rhs.m_head; r != nullptr; r = r->m_next)
|
||||
insert_impl(cend(), clone_row(*r));
|
||||
|
||||
m_validator = rhs.m_validator;
|
||||
m_cat_validator = rhs.m_cat_validator;
|
||||
|
||||
if (m_cat_validator != nullptr and m_index == nullptr)
|
||||
m_index = new category_index(*this);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
category &category::operator=(category &&rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
m_name = std::move(rhs.m_name);
|
||||
m_items = std::move(rhs.m_items);
|
||||
m_cascade = rhs.m_cascade;
|
||||
m_validator = rhs.m_validator;
|
||||
m_cat_validator = rhs.m_cat_validator;
|
||||
m_parent_links = rhs.m_parent_links;
|
||||
m_child_links = rhs.m_child_links;
|
||||
|
||||
std::swap(m_index, rhs.m_index);
|
||||
std::swap(m_head, rhs.m_head);
|
||||
std::swap(m_tail, rhs.m_tail);
|
||||
}
|
||||
|
||||
return *this;
|
||||
std::swap(a.m_name, b.m_name);
|
||||
std::swap(a.m_items, b.m_items);
|
||||
std::swap(a.m_validator, b.m_validator);
|
||||
std::swap(a.m_cat_validator, b.m_cat_validator);
|
||||
std::swap(a.m_parent_links, b.m_parent_links);
|
||||
std::swap(a.m_child_links, b.m_child_links);
|
||||
std::swap(a.m_cascade, b.m_cascade);
|
||||
std::swap(a.m_index, b.m_index);
|
||||
std::swap(a.m_head, b.m_head);
|
||||
std::swap(a.m_tail, b.m_tail);
|
||||
}
|
||||
|
||||
category::~category()
|
||||
@@ -597,7 +544,7 @@ category::~category()
|
||||
|
||||
void category::remove_item(std::string_view item_name)
|
||||
{
|
||||
for (size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
{
|
||||
if (not iequals(item_name, m_items[ix].m_name))
|
||||
continue;
|
||||
@@ -616,7 +563,7 @@ void category::remove_item(std::string_view item_name)
|
||||
|
||||
void category::rename_item(std::string_view from_name, std::string_view to_name)
|
||||
{
|
||||
for (size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < m_items.size(); ++ix)
|
||||
{
|
||||
if (not iequals(from_name, m_items[ix].m_name))
|
||||
continue;
|
||||
@@ -719,7 +666,7 @@ void category::set_validator(const validator *v, datablock &db)
|
||||
update_links(db);
|
||||
}
|
||||
|
||||
void category::update_links(datablock &db)
|
||||
void category::update_links(const datablock &db)
|
||||
{
|
||||
m_child_links.clear();
|
||||
m_parent_links.clear();
|
||||
@@ -728,7 +675,7 @@ void category::update_links(datablock &db)
|
||||
{
|
||||
for (auto link : m_validator->get_links_for_parent(m_name))
|
||||
{
|
||||
auto childCat = db.get(link->m_child_category);
|
||||
auto childCat = const_cast<category *>(db.get(link->m_child_category));
|
||||
if (childCat == nullptr)
|
||||
continue;
|
||||
m_child_links.emplace_back(childCat, link);
|
||||
@@ -736,7 +683,7 @@ void category::update_links(datablock &db)
|
||||
|
||||
for (auto link : m_validator->get_links_for_child(m_name))
|
||||
{
|
||||
auto parentCat = db.get(link->m_parent_category);
|
||||
auto parentCat = const_cast<category *>(db.get(link->m_parent_category));
|
||||
if (parentCat == nullptr)
|
||||
continue;
|
||||
m_parent_links.emplace_back(parentCat, link);
|
||||
@@ -844,7 +791,7 @@ bool category::is_valid() const
|
||||
|
||||
iv->validate_value(vi->text(), ec);
|
||||
|
||||
if (ec != std::errc())
|
||||
if ((bool)ec)
|
||||
{
|
||||
m_validator->report_error(ec, m_name, m_items[cix].m_name, false);
|
||||
continue;
|
||||
@@ -885,7 +832,7 @@ bool category::validate_links() const
|
||||
if (name() == "atom_site" and (parent->name() == "pdbx_poly_seq_scheme" or parent->name() == "entity_poly_seq"))
|
||||
continue;
|
||||
|
||||
size_t missing = 0;
|
||||
std::size_t missing = 0;
|
||||
category first_missing_rows(name());
|
||||
|
||||
for (auto r : *this)
|
||||
@@ -962,7 +909,7 @@ condition category::get_parents_condition(row_handle rh, const category &parentC
|
||||
{
|
||||
condition cond;
|
||||
|
||||
for (size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
{
|
||||
auto childValue = rh[link->m_child_keys[ix]];
|
||||
|
||||
@@ -1004,7 +951,7 @@ condition category::get_children_condition(row_handle rh, const category &childC
|
||||
{
|
||||
condition cond;
|
||||
|
||||
for (size_t ix = 0; ix < link->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < link->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
auto childKey = link->m_child_keys[ix];
|
||||
auto parentKey = link->m_parent_keys[ix];
|
||||
@@ -1180,14 +1127,14 @@ class save_value
|
||||
const T m_sv;
|
||||
};
|
||||
|
||||
size_t category::erase(condition &&cond)
|
||||
std::size_t category::erase(condition &&cond)
|
||||
{
|
||||
return erase(std::move(cond), {});
|
||||
}
|
||||
|
||||
size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
|
||||
std::size_t category::erase(condition &&cond, std::function<void(row_handle)> &&visit)
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
cond.prepare(*this);
|
||||
|
||||
@@ -1327,7 +1274,7 @@ std::string category::get_unique_value(std::string_view item_name)
|
||||
if (result.empty())
|
||||
{
|
||||
// brain-dead implementation
|
||||
for (size_t ix = 0; ix < size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < size(); ++ix)
|
||||
{
|
||||
// result = m_name + "-" + std::to_string(ix);
|
||||
result = cif_id_for_number(ix);
|
||||
@@ -1339,7 +1286,8 @@ std::string category::get_unique_value(std::string_view item_name)
|
||||
return result;
|
||||
}
|
||||
|
||||
void category::update_value(const std::vector<row_handle> &rows, std::string_view item_name, std::string_view value)
|
||||
void category::update_value(const std::vector<row_handle> &rows, std::string_view item_name,
|
||||
value_provider_type &&value_provider)
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
@@ -1352,40 +1300,29 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
|
||||
auto &col = m_items[colIx];
|
||||
|
||||
// this is expensive, but better throw early on
|
||||
// check the value
|
||||
if (col.m_validator)
|
||||
{
|
||||
std::error_code ec;
|
||||
col.m_validator->validate_value(value, ec);
|
||||
if (ec)
|
||||
throw validation_exception(ec, m_name, item_name);
|
||||
}
|
||||
|
||||
// first some sanity checks, what was the old value and is it the same for all rows?
|
||||
std::string oldValue{ rows.front()[item_name].text() };
|
||||
for (auto row : rows)
|
||||
{
|
||||
if (oldValue != row[item_name].text())
|
||||
for (auto row : rows)
|
||||
{
|
||||
std::ostringstream os;
|
||||
std::string value{ value_provider(row[item_name].text()) };
|
||||
|
||||
os << "Inconsistent old values in update_value, trying to set " << std::quoted(value)
|
||||
<< " as value for item " << item_name << " in category " << m_name;
|
||||
|
||||
throw std::runtime_error(os.str());
|
||||
std::error_code ec;
|
||||
col.m_validator->validate_value(value, ec);
|
||||
if (ec)
|
||||
throw validation_exception(ec, m_name, item_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldValue == value) // no need to do anything
|
||||
return;
|
||||
|
||||
// update rows, but do not cascade
|
||||
for (auto row : rows)
|
||||
row.assign(colIx, value, false);
|
||||
|
||||
// see if we need to update any child categories that depend on this value
|
||||
// update and see if we need to update any child categories that depend on this value
|
||||
for (auto parent : rows)
|
||||
{
|
||||
std::string oldValue{ parent[item_name].text() };
|
||||
std::string value{ value_provider(oldValue) };
|
||||
|
||||
update_value(parent.get_row(), colIx, value, false, false);
|
||||
|
||||
for (auto &&[childCat, linked] : m_child_links)
|
||||
{
|
||||
if (std::find(linked->m_parent_keys.begin(), linked->m_parent_keys.end(), item_name) == linked->m_parent_keys.end())
|
||||
@@ -1394,7 +1331,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
condition cond;
|
||||
std::string childItemName;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1425,7 +1362,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
{
|
||||
condition cond_c;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1443,7 +1380,7 @@ void category::update_value(const std::vector<row_handle> &rows, std::string_vie
|
||||
// oops, we need to split this child, unless a row already exists for the new value
|
||||
condition check;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1507,8 +1444,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo
|
||||
// before updating
|
||||
|
||||
bool reinsert = false;
|
||||
if (updateLinked and // an update of an Item's value
|
||||
m_index != nullptr and key_item_indices().count(item))
|
||||
if (m_index != nullptr and key_item_indices().count(item))
|
||||
{
|
||||
reinsert = m_index->find(*this, row);
|
||||
if (reinsert)
|
||||
@@ -1539,7 +1475,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo
|
||||
condition cond;
|
||||
std::string childItemName;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1576,7 +1512,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo
|
||||
|
||||
condition cond_n;
|
||||
|
||||
for (size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < linked->m_parent_keys.size(); ++ix)
|
||||
{
|
||||
std::string pk = linked->m_parent_keys[ix];
|
||||
std::string ck = linked->m_child_keys[ix];
|
||||
@@ -1722,7 +1658,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
|
||||
m_index->insert(*this, n);
|
||||
|
||||
// insert at end, most often this is the case
|
||||
if (pos.m_current == nullptr)
|
||||
if (pos.m_current.m_row == nullptr)
|
||||
{
|
||||
if (m_head == nullptr)
|
||||
m_tail = m_head = n;
|
||||
@@ -1733,7 +1669,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
|
||||
{
|
||||
assert(m_head != nullptr);
|
||||
|
||||
if (pos.m_current == m_head)
|
||||
if (pos.m_current.m_row == m_head)
|
||||
m_head = n->m_next = m_head;
|
||||
else
|
||||
n = n->m_next = m_head->m_next;
|
||||
@@ -1761,6 +1697,12 @@ void category::swap_item(uint16_t item_ix, row_handle &a, row_handle &b)
|
||||
auto &ra = *a.m_row;
|
||||
auto &rb = *b.m_row;
|
||||
|
||||
while (ra.size() <= item_ix)
|
||||
ra.emplace_back("");
|
||||
|
||||
while (rb.size() <= item_ix)
|
||||
rb.emplace_back("");
|
||||
|
||||
std::swap(ra.at(item_ix), rb.at(item_ix));
|
||||
}
|
||||
|
||||
@@ -1783,7 +1725,7 @@ void category::sort(std::function<int(row_handle, row_handle)> f)
|
||||
m_tail = rows.back().get_row();
|
||||
|
||||
auto r = m_head;
|
||||
for (size_t i = 1; i < rows.size(); ++i)
|
||||
for (std::size_t i = 1; i < rows.size(); ++i)
|
||||
r = r->m_next = rows[i].get_row();
|
||||
r->m_next = nullptr;
|
||||
|
||||
@@ -1799,7 +1741,7 @@ void category::reorder_by_index()
|
||||
|
||||
namespace detail
|
||||
{
|
||||
size_t write_value(std::ostream &os, std::string_view value, size_t offset, size_t width, bool right_aligned)
|
||||
std::size_t write_value(std::ostream &os, std::string_view value, std::size_t offset, std::size_t width, bool right_aligned)
|
||||
{
|
||||
if (value.find('\n') != std::string::npos or width == 0 or value.length() > 132) // write as text item
|
||||
{
|
||||
@@ -1960,7 +1902,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
{
|
||||
os << "loop_\n";
|
||||
|
||||
std::vector<size_t> itemWidths(m_items.size());
|
||||
std::vector<std::size_t> itemWidths(m_items.size());
|
||||
|
||||
for (auto cix : order)
|
||||
{
|
||||
@@ -1982,7 +1924,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
|
||||
if (v->text().find('\n') == std::string_view::npos)
|
||||
{
|
||||
size_t l = v->text().length();
|
||||
std::size_t l = v->text().length();
|
||||
|
||||
if (not sac_parser::is_unquoted_string(v->text()))
|
||||
l += 2;
|
||||
@@ -1998,11 +1940,11 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
|
||||
for (auto r = m_head; r != nullptr; r = r->m_next) // loop over rows
|
||||
{
|
||||
size_t offset = 0;
|
||||
std::size_t offset = 0;
|
||||
|
||||
for (uint16_t cix : order)
|
||||
{
|
||||
size_t w = itemWidths[cix];
|
||||
std::size_t w = itemWidths[cix];
|
||||
|
||||
std::string_view s;
|
||||
auto iv = r->get(cix);
|
||||
@@ -2012,7 +1954,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
if (s.empty())
|
||||
s = "?";
|
||||
|
||||
size_t l = s.length();
|
||||
std::size_t l = s.length();
|
||||
if (not sac_parser::is_unquoted_string(s))
|
||||
l += 2;
|
||||
if (l < w)
|
||||
@@ -2040,7 +1982,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
else
|
||||
{
|
||||
// first find the indent level
|
||||
size_t l = 0;
|
||||
std::size_t l = 0;
|
||||
|
||||
for (auto &col : m_items)
|
||||
{
|
||||
@@ -2052,7 +1994,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
|
||||
l += 3;
|
||||
|
||||
size_t width = 1;
|
||||
std::size_t width = 1;
|
||||
|
||||
for (auto cix : order)
|
||||
{
|
||||
@@ -2067,7 +2009,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
if (s.empty())
|
||||
s = "?";
|
||||
|
||||
size_t l2 = s.length();
|
||||
std::size_t l2 = s.length();
|
||||
|
||||
if (not sac_parser::is_unquoted_string(s))
|
||||
l2 += 2;
|
||||
@@ -2093,7 +2035,7 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
|
||||
if (s.empty())
|
||||
s = "?";
|
||||
|
||||
size_t offset = l;
|
||||
std::size_t offset = l;
|
||||
if (s.length() + l >= kMaxLineLength)
|
||||
{
|
||||
os << '\n';
|
||||
@@ -2133,7 +2075,7 @@ bool category::operator==(const category &rhs) const
|
||||
typedef std::function<int(std::string_view, std::string_view)> compType;
|
||||
std::vector<std::tuple<std::string, compType>> item_names;
|
||||
std::vector<std::string> keys;
|
||||
std::vector<size_t> keyIx;
|
||||
std::vector<std::size_t> keyIx;
|
||||
|
||||
if (catValidator == nullptr)
|
||||
{
|
||||
|
||||
138
src/compound.cpp
138
src/compound.cpp
@@ -496,7 +496,7 @@ compound *compound_factory_impl::create(const std::string &id)
|
||||
m_index = parser.index_datablocks();
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cout << " done" << std::endl;
|
||||
std::cout << " done\n";
|
||||
|
||||
// reload the resource, perhaps this should be improved...
|
||||
if (m_file.empty())
|
||||
@@ -519,7 +519,7 @@ compound *compound_factory_impl::create(const std::string &id)
|
||||
parser.parse_single_datablock(id, m_index);
|
||||
|
||||
if (cif::VERBOSE > 1)
|
||||
std::cout << " done" << std::endl;
|
||||
std::cout << " done\n";
|
||||
|
||||
if (not file.empty())
|
||||
{
|
||||
@@ -545,12 +545,29 @@ class local_compound_factory_impl : public compound_factory_impl
|
||||
: compound_factory_impl(next)
|
||||
, m_local_file(file)
|
||||
{
|
||||
// const std::regex peptideRx("(?:[lmp]-)?peptide", std::regex::icase);
|
||||
|
||||
// for (const auto &[id, name, threeLetterCode, group] :
|
||||
// file["comp_list"]["chem_comp"].rows<std::string, std::string, std::string, std::string>("id", "name", "three_letter_code", "group"))
|
||||
// {
|
||||
// auto &rdb = m_local_file["comp_" + id];
|
||||
// if (rdb.empty())
|
||||
// {
|
||||
// // std::cerr << "Missing data in restraint file for id " + id + '\n';
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// construct_compound(rdb, id, name, threeLetterCode, group);
|
||||
// }
|
||||
}
|
||||
|
||||
compound *create(const std::string &id) override;
|
||||
|
||||
private:
|
||||
const cif::file &m_local_file;
|
||||
|
||||
compound *construct_compound(const datablock &db, const std::string &id, const std::string &name, const std::string &three_letter_code, const std::string &group);
|
||||
|
||||
cif::file m_local_file;
|
||||
};
|
||||
|
||||
compound *local_compound_factory_impl::create(const std::string &id)
|
||||
@@ -561,12 +578,21 @@ compound *local_compound_factory_impl::create(const std::string &id)
|
||||
{
|
||||
if (db.name() == "comp_" + id)
|
||||
{
|
||||
cif::datablock db_copy(db);
|
||||
auto chem_comp = db.get("chem_comp");
|
||||
if (not chem_comp)
|
||||
break;
|
||||
|
||||
result = new compound(db_copy, 1);
|
||||
try
|
||||
{
|
||||
const auto &[id, name, threeLetterCode, group] =
|
||||
chem_comp->front().get<std::string, std::string, std::string, std::string>("id", "name", "three_letter_code", "group");
|
||||
|
||||
std::shared_lock lock(mMutex);
|
||||
m_compounds.push_back(result);
|
||||
result = construct_compound(db, id, name, threeLetterCode, group);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
std::throw_with_nested(std::runtime_error("Error loading compound " + id));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -575,6 +601,100 @@ compound *local_compound_factory_impl::create(const std::string &id)
|
||||
return result;
|
||||
}
|
||||
|
||||
compound *local_compound_factory_impl::construct_compound(const datablock &rdb, const std::string &id,
|
||||
const std::string &name, const std::string &three_letter_code, const std::string &group)
|
||||
{
|
||||
cif::datablock db(id);
|
||||
|
||||
float formula_weight = 0;
|
||||
int formal_charge = 0;
|
||||
std::map<std::string,std::size_t> formula_data;
|
||||
|
||||
for (std::size_t ord = 1; const auto &[atom_id, type_symbol, type, charge, x, y, z] :
|
||||
rdb["chem_comp_atom"].rows<std::string, std::string, std::string, int, float, float, float>(
|
||||
"atom_id", "type_symbol", "type", "charge", "x", "y", "z"))
|
||||
{
|
||||
auto atom = cif::atom_type_traits(type_symbol);
|
||||
formula_weight += atom.weight();
|
||||
|
||||
formula_data[type_symbol] += 1;
|
||||
|
||||
db["chem_comp_atom"].emplace({
|
||||
{ "comp_id", id },
|
||||
{ "atom_id", atom_id },
|
||||
{ "type_symbol", type_symbol },
|
||||
{ "charge", charge },
|
||||
{ "model_Cartn_x", x, 3 },
|
||||
{ "model_Cartn_y", y, 3 },
|
||||
{ "model_Cartn_z", z, 3 },
|
||||
{ "pdbx_ordinal", ord++ }
|
||||
});
|
||||
|
||||
formal_charge += charge;
|
||||
}
|
||||
|
||||
for (std::size_t ord = 1; const auto &[atom_id_1, atom_id_2, type, aromatic] :
|
||||
rdb["chem_comp_bond"].rows<std::string, std::string, std::string, bool>("atom_id_1", "atom_id_2", "type", "aromatic"))
|
||||
{
|
||||
std::string value_order("SING");
|
||||
|
||||
if (cif::iequals(type, "single") or cif::iequals(type, "sing"))
|
||||
value_order = "SING";
|
||||
else if (cif::iequals(type, "double") or cif::iequals(type, "doub"))
|
||||
value_order = "DOUB";
|
||||
else if (cif::iequals(type, "triple") or cif::iequals(type, "trip"))
|
||||
value_order = "TRIP";
|
||||
|
||||
db["chem_comp_bond"].emplace({
|
||||
{ "comp_id", id },
|
||||
{ "atom_id_1", atom_id_1 },
|
||||
{ "atom_id_2", atom_id_2 },
|
||||
{ "value_order", value_order },
|
||||
{ "pdbx_aromatic_flag", aromatic },
|
||||
// TODO: fetch stereo_config info from chem_comp_chir
|
||||
{ "pdbx_ordinal", ord++ }
|
||||
});
|
||||
}
|
||||
|
||||
db.emplace_back(rdb["pdbx_chem_comp_descriptor"]);
|
||||
|
||||
std::string formula;
|
||||
for (bool first = true; const auto &[symbol, count]: formula_data)
|
||||
{
|
||||
if (std::exchange(first, false))
|
||||
formula += ' ';
|
||||
formula += symbol;
|
||||
if (count > 1)
|
||||
formula += std::to_string(count);
|
||||
}
|
||||
|
||||
std::string type;
|
||||
if (cif::iequals(group, "peptide") or cif::iequals(group, "l-peptide") or cif::iequals(group, "l-peptide linking"))
|
||||
type = "L-PEPTIDE LINKING";
|
||||
else if (cif::iequals(group, "dna"))
|
||||
type = "DNA LINKING";
|
||||
else if (cif::iequals(group, "rna"))
|
||||
type = "RNA LINKING";
|
||||
else
|
||||
type = "NON-POLYMER";
|
||||
|
||||
db["chem_comp"].emplace({
|
||||
{ "id", id },
|
||||
{ "name", name },
|
||||
{ "type", type },
|
||||
{ "formula", formula },
|
||||
{ "pdbx_formal_charge", formal_charge },
|
||||
{ "formula_weight", formula_weight },
|
||||
{ "three_letter_code", three_letter_code }
|
||||
});
|
||||
|
||||
std::shared_lock lock(mMutex);
|
||||
|
||||
auto result = new compound(db);
|
||||
m_compounds.push_back(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<compound_factory> compound_factory::s_instance;
|
||||
@@ -757,8 +877,8 @@ void compound_factory::report_missing_compound(std::string_view compound_id)
|
||||
<< "update=true\n\n"
|
||||
<< "If you do not have a working cron script, you can manually update the files\n"
|
||||
<< "in /var/cache/libcifpp using the following commands:\n\n"
|
||||
<< "curl -o " << CACHE_DIR << "/components.cif https://files.wwpdb.org/pub/pdb/data/monomers/components.cif.gz\n"
|
||||
<< "curl -o " << CACHE_DIR << "/mmcif_pdbx.dic https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic.gz\n"
|
||||
<< "curl -o " << CACHE_DIR << "/components.cif https://files.wwpdb.org/pub/pdb/data/monomers/components.cif\n"
|
||||
<< "curl -o " << CACHE_DIR << "/mmcif_pdbx.dic https://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic\n"
|
||||
<< "curl -o " << CACHE_DIR << "/mmcif_ma.dic https://github.com/ihmwg/ModelCIF/raw/master/dist/mmcif_ma.dic\n\n";
|
||||
#endif
|
||||
|
||||
|
||||
@@ -76,6 +76,20 @@ namespace detail
|
||||
return this;
|
||||
}
|
||||
|
||||
condition_impl *key_equals_number_condition_impl::prepare(const category &c)
|
||||
{
|
||||
m_item_ix = c.get_item_ix(m_item_name);
|
||||
|
||||
if (c.get_cat_validator() != nullptr and
|
||||
c.key_item_indices().contains(m_item_ix) and
|
||||
c.key_item_indices().size() == 1)
|
||||
{
|
||||
m_single_hit = c[{ { m_item_name, m_value } }];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
bool found_in_range(condition_impl *c, std::vector<and_condition_impl *>::iterator b, std::vector<and_condition_impl *>::iterator e)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
@@ -38,21 +38,6 @@ datablock::datablock(const datablock &db)
|
||||
cat.update_links(*this);
|
||||
}
|
||||
|
||||
datablock &datablock::operator=(const datablock &db)
|
||||
{
|
||||
if (this != &db)
|
||||
{
|
||||
std::list<category>::operator=(db);
|
||||
m_name = db.m_name;
|
||||
m_validator = db.m_validator;
|
||||
|
||||
for (auto &cat : *this)
|
||||
cat.update_links(*this);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void datablock::set_validator(const validator *v)
|
||||
{
|
||||
m_validator = v;
|
||||
@@ -64,6 +49,7 @@ void datablock::set_validator(const validator *v)
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
m_validator = nullptr;
|
||||
throw_with_nested(std::runtime_error("Error while setting validator in datablock " + m_name));
|
||||
}
|
||||
}
|
||||
@@ -123,6 +109,9 @@ bool datablock::validate_links() const
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
for (auto &cat : *this)
|
||||
const_cast<category &>(cat).update_links(*this);
|
||||
|
||||
for (auto &cat : *this)
|
||||
result = cat.validate_links() and result;
|
||||
|
||||
@@ -190,6 +179,11 @@ std::tuple<datablock::iterator, bool> datablock::emplace(std::string_view name)
|
||||
}
|
||||
|
||||
assert(i != end());
|
||||
|
||||
// links may have changed...
|
||||
for (auto &cat : *this)
|
||||
cat.update_links(*this);
|
||||
|
||||
return std::make_tuple(i, is_new);
|
||||
}
|
||||
|
||||
@@ -282,7 +276,11 @@ void datablock::write(std::ostream &os) const
|
||||
cat_order_t cat_order;
|
||||
|
||||
for (auto &cat : *this)
|
||||
{
|
||||
if (cat.name() == "entry" or cat.name() == "audit_conform")
|
||||
continue;
|
||||
cat_order.emplace_back(cat.name(), -1, false);
|
||||
}
|
||||
|
||||
for (auto i = cat_order.begin(); i != cat_order.end(); ++i)
|
||||
calculate_cat_order(cat_order, i, *m_validator);
|
||||
@@ -292,25 +290,18 @@ void datablock::write(std::ostream &os) const
|
||||
const auto &[cat_a, count_a, on_stack_a] = a;
|
||||
const auto &[cat_b, count_b, on_stack_b] = b;
|
||||
|
||||
int d = 0;
|
||||
|
||||
if (cat_a == "audit_conform")
|
||||
d = -1;
|
||||
else if (cat_b == "audit_conform")
|
||||
d = 1;
|
||||
else if (cat_a == "entry")
|
||||
d = -1;
|
||||
else if (cat_b == "entry")
|
||||
d = 1;
|
||||
else
|
||||
{
|
||||
d = std::get<1>(a) - std::get<1>(b);
|
||||
if (d == 0)
|
||||
d = cat_b.compare(cat_a);
|
||||
}
|
||||
int d = std::get<1>(a) - std::get<1>(b);
|
||||
if (d == 0)
|
||||
d = cat_b.compare(cat_a);
|
||||
|
||||
return d < 0; });
|
||||
|
||||
if (auto entry = get("entry"); entry != nullptr)
|
||||
entry->write(os);
|
||||
|
||||
if (auto audit_conform = get("audit_conform"); audit_conform != nullptr)
|
||||
audit_conform->write(os);
|
||||
|
||||
for (auto &&[cat, count, on_stack] : cat_order)
|
||||
get(cat)->write(os);
|
||||
}
|
||||
@@ -320,20 +311,13 @@ void datablock::write(std::ostream &os) const
|
||||
// and if it exists, _AND_ we have a Validator, write out the
|
||||
// audit_conform record.
|
||||
|
||||
for (auto &cat : *this)
|
||||
{
|
||||
if (cat.name() != "entry")
|
||||
continue;
|
||||
|
||||
cat.write(os);
|
||||
|
||||
break;
|
||||
}
|
||||
if (auto entry = get("entry"); entry != nullptr)
|
||||
entry->write(os);
|
||||
|
||||
// If the dictionary declares an audit_conform category, put it in,
|
||||
// but only if it does not exist already!
|
||||
if (get("audit_conform"))
|
||||
get("audit_conform")->write(os);
|
||||
if (auto audit_conform = get("audit_conform"); audit_conform != nullptr)
|
||||
audit_conform->write(os);
|
||||
|
||||
for (auto &cat : *this)
|
||||
{
|
||||
@@ -348,7 +332,7 @@ void datablock::write(std::ostream &os, const std::vector<std::string> &item_nam
|
||||
os << "data_" << m_name << '\n'
|
||||
<< "# \n";
|
||||
|
||||
std::vector<std::string> cat_order;
|
||||
std::vector<std::string> cat_order{ "entry", "audit_conform" };
|
||||
for (auto &o : item_name_order)
|
||||
{
|
||||
std::string cat_name, item_name;
|
||||
|
||||
@@ -308,17 +308,17 @@ class dictionary_parser : public parser
|
||||
|
||||
using key_type = std::tuple<std::string, std::string, int>;
|
||||
|
||||
std::map<key_type, size_t> linkIndex;
|
||||
std::map<key_type, std::size_t> linkIndex;
|
||||
|
||||
// Each link group consists of a set of keys
|
||||
std::vector<std::tuple<std::vector<std::string>, std::vector<std::string>>> linkKeys;
|
||||
|
||||
auto addLink = [&](size_t ix, const std::string &pk, const std::string &ck)
|
||||
auto addLink = [&](std::size_t ix, const std::string &pk, const std::string &ck)
|
||||
{
|
||||
auto &&[pkeys, ckeys] = linkKeys.at(ix);
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < pkeys.size(); ++i)
|
||||
for (std::size_t i = 0; i < pkeys.size(); ++i)
|
||||
{
|
||||
if (pkeys[i] == pk and ckeys[i] == ck)
|
||||
{
|
||||
@@ -357,7 +357,7 @@ class dictionary_parser : public parser
|
||||
linkKeys.push_back({});
|
||||
}
|
||||
|
||||
size_t ix = linkIndex.at(key);
|
||||
std::size_t ix = linkIndex.at(key);
|
||||
addLink(ix, piv->m_item_name, civ->m_item_name);
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ class dictionary_parser : public parser
|
||||
linkKeys.push_back({});
|
||||
}
|
||||
|
||||
size_t ix = linkIndex.at(key);
|
||||
std::size_t ix = linkIndex.at(key);
|
||||
addLink(ix, piv->m_item_name, civ->m_item_name);
|
||||
}
|
||||
}
|
||||
|
||||
34
src/file.cpp
34
src/file.cpp
@@ -31,11 +31,32 @@ namespace cif
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// TODO: This is wrong. A validator should be assigned to datablocks,
|
||||
// not to a file. Since audit_conform is a category specifying the
|
||||
// content of a datablock. Not the entire file.
|
||||
|
||||
void file::set_validator(const validator *v)
|
||||
{
|
||||
m_validator = v;
|
||||
for (auto &db : *this)
|
||||
db.set_validator(v);
|
||||
for (bool first = true; auto &db : *this)
|
||||
{
|
||||
try
|
||||
{
|
||||
db.set_validator(v);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
if (first)
|
||||
throw;
|
||||
|
||||
// Accept failure on secondary datablocks
|
||||
// now that many mmCIF files have invalid
|
||||
// restraint data concatenated.
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool file::is_valid() const
|
||||
@@ -78,12 +99,12 @@ bool file::validate_links() const
|
||||
{
|
||||
if (m_validator == nullptr)
|
||||
std::runtime_error("No validator loaded explicitly, cannot continue");
|
||||
|
||||
|
||||
bool result = true;
|
||||
|
||||
for (auto &db : *this)
|
||||
result = db.validate_links() and result;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -97,7 +118,7 @@ void file::load_dictionary()
|
||||
std::string name = audit_conform->front().get<std::string>("dict_name");
|
||||
|
||||
if (name == "mmcif_pdbx_v50")
|
||||
name = "mmcif_pdbx.dic"; // we had a bug here in libcifpp...
|
||||
name = "mmcif_pdbx.dic"; // we had a bug here in libcifpp...
|
||||
|
||||
if (not name.empty())
|
||||
{
|
||||
@@ -125,7 +146,8 @@ void file::load_dictionary(std::string_view name)
|
||||
|
||||
bool file::contains(std::string_view name) const
|
||||
{
|
||||
return std::find_if(begin(), end(), [name](const datablock &db) { return iequals(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)
|
||||
|
||||
@@ -52,10 +52,10 @@ std::string_view item_handle::text() const
|
||||
return {};
|
||||
}
|
||||
|
||||
void item_handle::assign_value(const item &v)
|
||||
void item_handle::assign_value(std::string_view value)
|
||||
{
|
||||
assert(not m_row_handle.empty());
|
||||
m_row_handle.assign(m_item_ix, v.value(), true);
|
||||
m_row_handle.assign(m_item_ix, value, true);
|
||||
}
|
||||
|
||||
void item_handle::swap(item_handle &b)
|
||||
|
||||
700
src/model.cpp
700
src/model.cpp
File diff suppressed because it is too large
Load Diff
@@ -182,7 +182,7 @@ std::vector<std::string> MapAsymIDs2ChainIDs(const std::vector<std::string> &asy
|
||||
}
|
||||
|
||||
// support for wrapping text using a 'continuation marker'
|
||||
size_t WriteContinuedLine(std::ostream &pdbFile, std::string header, int &count, int cLen, std::string text, std::string::size_type lStart = 0)
|
||||
std::size_t WriteContinuedLine(std::ostream &pdbFile, std::string header, int &count, int cLen, std::string text, std::string::size_type lStart = 0)
|
||||
{
|
||||
if (lStart == 0)
|
||||
{
|
||||
@@ -217,15 +217,15 @@ size_t WriteContinuedLine(std::ostream &pdbFile, std::string header, int &count,
|
||||
return lines.size();
|
||||
}
|
||||
|
||||
size_t WriteOneContinuedLine(std::ostream &pdbFile, std::string header, int cLen, std::string line, int lStart = 0)
|
||||
std::size_t WriteOneContinuedLine(std::ostream &pdbFile, std::string header, int cLen, std::string line, int lStart = 0)
|
||||
{
|
||||
int count = 0;
|
||||
return WriteContinuedLine(pdbFile, header, count, cLen, line, lStart);
|
||||
}
|
||||
|
||||
size_t WriteCitation(std::ostream &pdbFile, const datablock &db, row_handle r, int reference)
|
||||
std::size_t WriteCitation(std::ostream &pdbFile, const datablock &db, row_handle r, int reference)
|
||||
{
|
||||
size_t result = 0;
|
||||
std::size_t result = 0;
|
||||
|
||||
std::string s1;
|
||||
|
||||
@@ -560,7 +560,7 @@ void WriteTitle(std::ostream &pdbFile, const datablock &db)
|
||||
std::string cs = ++continuation > 1 ? std::to_string(continuation) : std::string();
|
||||
|
||||
pdbFile << cif::format(kRevDatFmt, revNum, cs, date, db.name(), modType);
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
for (std::size_t i = 0; i < 4; ++i)
|
||||
pdbFile << cif::format(" %-6.6s", (i < types.size() ? types[i] : std::string()));
|
||||
pdbFile << '\n';
|
||||
|
||||
@@ -681,7 +681,7 @@ class Fi : public FBase
|
||||
{
|
||||
long l = 0;
|
||||
auto r = std::from_chars(s.data(), s.data() + s.length(), l);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "Failed to write '" << s << "' as a long from field " << mField << ", this indicates an error in the code for writing PDB files\n";
|
||||
@@ -719,7 +719,7 @@ class Ff : public FBase
|
||||
|
||||
double d = 0;
|
||||
auto r = cif::from_chars(s.data(), s.data() + s.length(), d);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "Failed to write '" << s << "' as a double from field " << mField << ", this indicates an error in the code for writing PDB files\n";
|
||||
@@ -748,7 +748,7 @@ class Fs : public FBase
|
||||
virtual void out(std::ostream &os)
|
||||
{
|
||||
std::string s{ text() };
|
||||
size_t width = os.width();
|
||||
std::size_t width = os.width();
|
||||
|
||||
if (s.empty())
|
||||
{
|
||||
@@ -2368,7 +2368,7 @@ void WriteRemark280(std::ostream &pdbFile, const datablock &db)
|
||||
|
||||
const char *keys[] = { "pdbx_details", "ph", "method", "temp" };
|
||||
|
||||
for (size_t i = 0; i < (sizeof(keys) / sizeof(const char *)); ++i)
|
||||
for (std::size_t i = 0; i < (sizeof(keys) / sizeof(const char *)); ++i)
|
||||
{
|
||||
const char *c = keys[i];
|
||||
|
||||
@@ -2634,7 +2634,7 @@ void WriteRemark470(std::ostream &pdbFile, const datablock &db)
|
||||
{
|
||||
pdbFile << cif::format("REMARK 470 %3.3s %3.3s %1.1s%4d%1.1s ", modelNr, resName, chainID, seqNr, iCode) << " ";
|
||||
|
||||
for (size_t i = 0; i < 6 and not a.second.empty(); ++i)
|
||||
for (std::size_t i = 0; i < 6 and not a.second.empty(); ++i)
|
||||
{
|
||||
pdbFile << cif2pdbAtomName(a.second.front(), resName, db) << ' ';
|
||||
a.second.pop_front();
|
||||
@@ -3284,7 +3284,7 @@ int WriteMiscellaneousFeatures(std::ostream &pdbFile, const datablock &db)
|
||||
std::string siteID = std::get<0>(s);
|
||||
std::deque<std::string> &res = std::get<1>(s);
|
||||
|
||||
size_t numRes = res.size();
|
||||
std::size_t numRes = res.size();
|
||||
|
||||
int nr = 1;
|
||||
while (res.empty() == false)
|
||||
@@ -3393,7 +3393,7 @@ std::tuple<int, int> WriteCoordinatesForModel(std::ostream &pdbFile, const datab
|
||||
{
|
||||
int nr = 0;
|
||||
auto r = std::from_chars(modelNum.data(), modelNum.data() + modelNum.length(), nr);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
{
|
||||
if (VERBOSE > 0)
|
||||
std::cerr << "Model number '" << modelNum << "' is not a valid integer\n";
|
||||
|
||||
@@ -160,7 +160,7 @@ PDBRecord::~PDBRecord()
|
||||
{
|
||||
}
|
||||
|
||||
void *PDBRecord::operator new(size_t size, size_t vLen)
|
||||
void *PDBRecord::operator new(std::size_t size, std::size_t vLen)
|
||||
{
|
||||
return malloc(size + vLen + 1);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ void PDBRecord::operator delete(void *p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
void PDBRecord::operator delete(void *p, size_t vLen)
|
||||
void PDBRecord::operator delete(void *p, std::size_t vLen)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
@@ -180,7 +180,7 @@ bool PDBRecord::is(const char *name) const
|
||||
return iequals(mName, name);
|
||||
}
|
||||
|
||||
char PDBRecord::vC(size_t column)
|
||||
char PDBRecord::vC(std::size_t column)
|
||||
{
|
||||
char result = ' ';
|
||||
if (column - 7 < mVlen)
|
||||
@@ -188,7 +188,7 @@ char PDBRecord::vC(size_t column)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string PDBRecord::vS(size_t columnFirst, size_t columnLast)
|
||||
std::string PDBRecord::vS(std::size_t columnFirst, std::size_t columnLast)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
@@ -272,7 +272,7 @@ int PDBRecord::vI(int columnFirst, int columnLast)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string PDBRecord::vF(size_t columnFirst, size_t columnLast)
|
||||
std::string PDBRecord::vF(std::size_t columnFirst, std::size_t columnLast)
|
||||
{
|
||||
// for now... TODO: check format?
|
||||
return vS(columnFirst, columnLast);
|
||||
@@ -780,17 +780,17 @@ class PDBFileParser
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
char vC(size_t column) const
|
||||
char vC(std::size_t column) const
|
||||
{
|
||||
return mRec->vC(column);
|
||||
}
|
||||
|
||||
std::string vS(size_t columnFirst, size_t columnLast = std::numeric_limits<size_t>::max()) const
|
||||
std::string vS(std::size_t columnFirst, std::size_t columnLast = std::numeric_limits<std::size_t>::max()) const
|
||||
{
|
||||
return mRec->vS(columnFirst, columnLast);
|
||||
}
|
||||
|
||||
std::string vF(size_t columnFirst, size_t columnLast) const
|
||||
std::string vF(std::size_t columnFirst, std::size_t columnLast) const
|
||||
{
|
||||
return mRec->vF(columnFirst, columnLast);
|
||||
}
|
||||
@@ -847,7 +847,7 @@ class PDBFileParser
|
||||
void ParseRemarks();
|
||||
|
||||
// void ParseRemark3();
|
||||
// size_t ParseRemark3(const std::string& program, const Remark3Template templ[], size_t N);
|
||||
// std::size_t ParseRemark3(const std::string& program, const Remark3Template templ[], std::size_t N);
|
||||
// std::string NextRemark3Line();
|
||||
|
||||
void ParseRemark200();
|
||||
@@ -1132,7 +1132,7 @@ void PDBFileParser::PreParseInput(std::istream &is)
|
||||
if (not cs.empty())
|
||||
{
|
||||
auto r = std::from_chars(cs.data(), cs.data() + cs.length(), result);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
throw std::runtime_error("Continuation std::string '" + cs + "' is not valid");
|
||||
}
|
||||
|
||||
@@ -1320,7 +1320,7 @@ void PDBFileParser::PreParseInput(std::istream &is)
|
||||
{
|
||||
std::string siteName = value.substr(5, 3);
|
||||
cif::trim_right(value);
|
||||
size_t n = value.length() - 12;
|
||||
std::size_t n = value.length() - 12;
|
||||
value += std::string(11 - (n % 11), ' ');
|
||||
|
||||
while (lookahead.substr(0, 6) == type and lookahead.substr(11, 3) == siteName)
|
||||
@@ -1397,7 +1397,7 @@ void PDBFileParser::PreParseInput(std::istream &is)
|
||||
{
|
||||
auto f = cur->vF(74, 78);
|
||||
auto r = cif::from_chars(f.data(), f.data() + f.length(), link.distance);
|
||||
if (r.ec != std::errc() and cif::VERBOSE > 0)
|
||||
if ((bool)r.ec and cif::VERBOSE > 0)
|
||||
std::cerr << "Error parsing link distance at line " << cur->mLineNr << '\n';
|
||||
}
|
||||
// 74 – 78 Real(5.2) Length Link distance
|
||||
@@ -4202,7 +4202,7 @@ void PDBFileParser::ConstructEntities()
|
||||
|
||||
chains.push_back(std::string{ chain.mDbref.chainID });
|
||||
|
||||
size_t seqLen = 0, seqCanLen = 0;
|
||||
std::size_t seqLen = 0, seqCanLen = 0;
|
||||
|
||||
for (auto &res : chain.mSeqres)
|
||||
{
|
||||
@@ -4265,7 +4265,7 @@ void PDBFileParser::ConstructEntities()
|
||||
}
|
||||
|
||||
auto cat_ps = getCategory("entity_poly_seq");
|
||||
for (size_t i = 0; i < chain.mSeqres.size(); ++i)
|
||||
for (std::size_t i = 0; i < chain.mSeqres.size(); ++i)
|
||||
{
|
||||
auto &rs = chain.mSeqres[i];
|
||||
|
||||
@@ -4335,7 +4335,7 @@ void PDBFileParser::ConstructEntities()
|
||||
std::map<std::tuple<std::string, std::string>, int> ndbSeqNum; // for nonpoly scheme
|
||||
std::map<std::string, int> entityAuthSeqNum; // for nonpoly scheme too
|
||||
|
||||
for (size_t i = 0; i < mHets.size(); ++i)
|
||||
for (std::size_t i = 0; i < mHets.size(); ++i)
|
||||
{
|
||||
auto &heti = mHets[i];
|
||||
|
||||
@@ -4669,47 +4669,6 @@ void PDBFileParser::ConstructEntities()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finish by calculating the formula_weight for each entity
|
||||
for (auto entity : *getCategory("entity"))
|
||||
{
|
||||
auto entity_id = entity["id"].as<std::string>();
|
||||
float formula_weight = 0;
|
||||
|
||||
if (entity["type"] == "polymer")
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (std::string comp_id : getCategory("pdbx_poly_seq_scheme")->find<std::string>(cif::key("entity_id") == entity_id, "mon_id"))
|
||||
{
|
||||
auto compound = cif::compound_factory::instance().create(comp_id);
|
||||
assert(compound);
|
||||
if (not compound)
|
||||
throw std::runtime_error("missing information for compound " + comp_id);
|
||||
formula_weight += compound->formula_weight();
|
||||
++n;
|
||||
}
|
||||
|
||||
formula_weight -= (n - 1) * 18.015;
|
||||
}
|
||||
else if (entity["type"] == "water")
|
||||
formula_weight = 18.015;
|
||||
else
|
||||
{
|
||||
auto comp_id = getCategory("pdbx_nonpoly_scheme")->find_first<std::optional<std::string>>(cif::key("entity_id") == entity_id, "mon_id");
|
||||
if (comp_id.has_value())
|
||||
{
|
||||
auto compound = cif::compound_factory::instance().create(*comp_id);
|
||||
assert(compound);
|
||||
if (not compound)
|
||||
throw std::runtime_error("missing information for compound " + *comp_id);
|
||||
formula_weight = compound->formula_weight();
|
||||
}
|
||||
}
|
||||
|
||||
if (formula_weight > 0)
|
||||
entity.assign({ { "formula_weight", formula_weight, 3 } });
|
||||
}
|
||||
}
|
||||
|
||||
void PDBFileParser::ConstructSugarTrees(int &asymNr)
|
||||
@@ -5347,7 +5306,7 @@ void PDBFileParser::ParseConnectivtyAnnotation()
|
||||
|
||||
double d;
|
||||
auto r = cif::from_chars(distance.data(), distance.data() + distance.length(), d);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
{
|
||||
if (cif::VERBOSE > 0)
|
||||
std::cerr << "Distance value '" << distance << "' is not a valid float in LINK record\n";
|
||||
@@ -5753,7 +5712,7 @@ void PDBFileParser::ParseCoordinate(int modelNr)
|
||||
stable_sort(atoms.begin(), atoms.end(), rLess);
|
||||
|
||||
// now reiterate the atoms to reorder alternates
|
||||
for (size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
for (std::size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
{
|
||||
char altLoc = std::get<3>(atoms[i])->vC(17);
|
||||
|
||||
@@ -6402,7 +6361,7 @@ bool PDBFileParser::PDBChain::SameSequence(const PDBChain &rhs) const
|
||||
{
|
||||
bool result = mSeqres.size() == rhs.mSeqres.size();
|
||||
|
||||
for (size_t i = 0; result and i < mSeqres.size(); ++i)
|
||||
for (std::size_t i = 0; result and i < mSeqres.size(); ++i)
|
||||
result = mSeqres[i].mMonID == rhs.mSeqres[i].mMonID;
|
||||
|
||||
return result;
|
||||
@@ -6454,11 +6413,11 @@ file read(std::istream &is)
|
||||
{
|
||||
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."));
|
||||
}
|
||||
|
||||
// Since we're using the cif::pdb way of reading the file, the data may need
|
||||
// reconstruction
|
||||
reconstruct_pdbx(result);
|
||||
}
|
||||
|
||||
// Since we're using the cif::pdb way of reading the file, the data may need
|
||||
// reconstruction
|
||||
reconstruct_pdbx(result);
|
||||
}
|
||||
|
||||
// Must be a PDB like file, right?
|
||||
|
||||
@@ -980,8 +980,8 @@ std::string Remark3Parser::nextLine()
|
||||
|
||||
while (mRec != nullptr and mRec->is("REMARK 3"))
|
||||
{
|
||||
size_t valueIndent = 0;
|
||||
for (size_t i = 4; i < mRec->mVlen; ++i)
|
||||
std::size_t valueIndent = 0;
|
||||
for (std::size_t i = 4; i < mRec->mVlen; ++i)
|
||||
{
|
||||
if (mRec->mValue[i] == ' ')
|
||||
continue;
|
||||
@@ -1232,7 +1232,7 @@ void Remark3Parser::storeCapture(const char *category, std::initializer_list<con
|
||||
}
|
||||
// else if (iequals(category, "struct_ncs_dom"))
|
||||
// {
|
||||
// size_t id = cat.size() + 1;
|
||||
// std::size_t id = cat.size() + 1;
|
||||
//
|
||||
// cat.emplace({
|
||||
// { "id", id }
|
||||
|
||||
@@ -40,24 +40,24 @@ struct PDBRecord
|
||||
PDBRecord *mNext;
|
||||
uint32_t mLineNr;
|
||||
char mName[11];
|
||||
size_t mVlen;
|
||||
std::size_t mVlen;
|
||||
char mValue[1];
|
||||
|
||||
PDBRecord(uint32_t lineNr, const std::string &name, const std::string &value);
|
||||
~PDBRecord();
|
||||
|
||||
void *operator new(size_t);
|
||||
void *operator new(size_t size, size_t vLen);
|
||||
void *operator new(std::size_t);
|
||||
void *operator new(std::size_t size, std::size_t vLen);
|
||||
|
||||
void operator delete(void *p);
|
||||
void operator delete(void *p, size_t vLen);
|
||||
void operator delete(void *p, std::size_t vLen);
|
||||
|
||||
bool is(const char *name) const;
|
||||
|
||||
char vC(size_t column);
|
||||
std::string vS(size_t columnFirst, size_t columnLast = std::numeric_limits<size_t>::max());
|
||||
char vC(std::size_t column);
|
||||
std::string vS(std::size_t columnFirst, std::size_t columnLast = std::numeric_limits<std::size_t>::max());
|
||||
int vI(int columnFirst, int columnLast);
|
||||
std::string vF(size_t columnFirst, size_t columnLast);
|
||||
std::string vF(std::size_t columnFirst, std::size_t columnLast);
|
||||
};
|
||||
|
||||
} // namespace pdbx
|
||||
@@ -92,6 +92,72 @@ condition get_condition(residue_key_type &k)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void checkEntities(datablock &db)
|
||||
{
|
||||
using namespace cif::literals;
|
||||
|
||||
auto &cf = cif::compound_factory::instance();
|
||||
|
||||
for (auto entity : db["entity"].find("formula_weight"_key == null or "formula_weight"_key == 0))
|
||||
{
|
||||
const auto &[entity_id, type] = entity.get<std::string, std::string>("id", "type");
|
||||
|
||||
float formula_weight = 0;
|
||||
|
||||
if (type == "polymer")
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (std::string comp_id : db["pdbx_poly_seq_scheme"].find<std::string>("entity_id"_key == entity_id, "mon_id"))
|
||||
{
|
||||
auto compound = cf.create(comp_id);
|
||||
assert(compound);
|
||||
if (not compound)
|
||||
throw std::runtime_error("missing information for compound " + comp_id);
|
||||
formula_weight += compound->formula_weight();
|
||||
++n;
|
||||
}
|
||||
|
||||
formula_weight -= (n - 1) * 18.015;
|
||||
}
|
||||
else if (type == "water")
|
||||
formula_weight = 18.015;
|
||||
else if (type == "branched")
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (std::string comp_id : db["pdbx_entity_branch_list"].find<std::string>("entity_id"_key == entity_id, "comp_id"))
|
||||
{
|
||||
auto compound = cf.create(comp_id);
|
||||
assert(compound);
|
||||
if (not compound)
|
||||
throw std::runtime_error("missing information for compound " + comp_id);
|
||||
formula_weight += compound->formula_weight();
|
||||
++n;
|
||||
}
|
||||
|
||||
formula_weight -= (n - 1) * 18.015;
|
||||
}
|
||||
else if (type == "non-polymer")
|
||||
{
|
||||
auto comp_id = db["pdbx_nonpoly_scheme"].find_first<std::optional<std::string>>("entity_id"_key == entity_id, "mon_id");
|
||||
if (comp_id.has_value())
|
||||
{
|
||||
auto compound = cf.create(*comp_id);
|
||||
if (not compound)
|
||||
{
|
||||
std::cerr << "missing information for compound " << *comp_id << "\n";
|
||||
continue;
|
||||
}
|
||||
formula_weight = compound->formula_weight();
|
||||
}
|
||||
}
|
||||
|
||||
if (formula_weight > 0)
|
||||
entity.assign({ { "formula_weight", formula_weight, 3 } });
|
||||
}
|
||||
}
|
||||
|
||||
void createEntityIDs(datablock &db)
|
||||
{
|
||||
// Suppose the file does not have entity ID's. We have to make up some
|
||||
@@ -147,11 +213,11 @@ void createEntityIDs(datablock &db)
|
||||
lastSeqID = seq_id;
|
||||
}
|
||||
|
||||
std::map<size_t, std::string> entity_ids;
|
||||
std::map<std::size_t, std::string> entity_ids;
|
||||
|
||||
atom_site.add_item("label_entity_id");
|
||||
|
||||
for (size_t i = 0; i < entities.size(); ++i)
|
||||
for (std::size_t i = 0; i < entities.size(); ++i)
|
||||
{
|
||||
if (entity_ids.contains(i))
|
||||
continue;
|
||||
@@ -159,14 +225,14 @@ void createEntityIDs(datablock &db)
|
||||
auto entity_id = std::to_string(i + 1);
|
||||
entity_ids[i] = entity_id;
|
||||
|
||||
for (size_t j = i + 1; j < entities.size(); ++j)
|
||||
for (std::size_t j = i + 1; j < entities.size(); ++j)
|
||||
{
|
||||
if (entities[i] == entities[j])
|
||||
entity_ids[j] = entity_id;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t ix = 0; auto &e : entities)
|
||||
for (std::size_t ix = 0; auto &e : entities)
|
||||
{
|
||||
auto k = e.front();
|
||||
const auto &entity_id = entity_ids[ix++];
|
||||
@@ -325,7 +391,7 @@ void checkChemCompRecords(datablock &db)
|
||||
items.emplace_back(item{ "formula_weight", compound->formula_weight() });
|
||||
|
||||
if (not items.empty())
|
||||
chem_comp_entry.assign(std::move(items));
|
||||
chem_comp_entry.assign(items);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,6 +414,12 @@ void checkAtomRecords(datablock &db)
|
||||
if (atom_site.contains(key("label_seq_id") < 0))
|
||||
fixNegativeSeqID(atom_site);
|
||||
|
||||
std::set<int> polymer_entities;
|
||||
for (int id : db["entity"].find<int>("type"_key == "polymer", "id"))
|
||||
polymer_entities.insert(id);
|
||||
|
||||
std::set<std::string> missingCompounds;
|
||||
|
||||
for (auto row : atom_site)
|
||||
{
|
||||
residue_key_type k = row.get<std::optional<std::string>,
|
||||
@@ -378,20 +450,31 @@ void checkAtomRecords(datablock &db)
|
||||
std::string asym_id = get_asym_id(k);
|
||||
std::string comp_id = get_comp_id(k);
|
||||
|
||||
bool is_peptide = cf.is_peptide(comp_id);
|
||||
if (missingCompounds.contains(comp_id))
|
||||
continue;
|
||||
|
||||
bool is_polymer = polymer_entities.contains(row["label_entity_id"].as<int>());
|
||||
auto compound = cf.create(comp_id);
|
||||
|
||||
if (not compound)
|
||||
throw std::runtime_error("Missing compound information for " + comp_id);
|
||||
{
|
||||
missingCompounds.insert(comp_id);
|
||||
std::cerr << "Missing compound information for " << comp_id << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
auto chem_comp_entry = chem_comp.find_first("id"_key == comp_id);
|
||||
|
||||
std::optional<bool> non_std;
|
||||
if (cf.is_monomer(comp_id))
|
||||
non_std = cf.is_std_monomer(comp_id);
|
||||
|
||||
if (not chem_comp_entry)
|
||||
{
|
||||
chem_comp.emplace({ //
|
||||
{ "id", comp_id },
|
||||
{ "type", compound->type() },
|
||||
{ "mon_nstd_flag", cf.is_std_monomer(comp_id) ? "y" : "n" },
|
||||
{ "mon_nstd_flag", non_std },
|
||||
{ "name", compound->name() },
|
||||
{ "formula", compound->formula() },
|
||||
{ "formula_weight", compound->formula_weight() } });
|
||||
@@ -402,8 +485,8 @@ void checkAtomRecords(datablock &db)
|
||||
|
||||
if (not chem_comp_entry["type"])
|
||||
items.emplace_back(item{ "type", compound->type() });
|
||||
if (not chem_comp_entry["mon_nstd_flag"])
|
||||
items.emplace_back(item{ "mon_nstd_flag", cf.is_std_monomer(comp_id) ? "y" : "n" });
|
||||
if (not chem_comp_entry["mon_nstd_flag"] and non_std.has_value())
|
||||
items.emplace_back(item{ "mon_nstd_flag", non_std });
|
||||
if (not chem_comp_entry["name"])
|
||||
items.emplace_back(item{ "name", compound->name() });
|
||||
if (not chem_comp_entry["formula"])
|
||||
@@ -412,23 +495,21 @@ void checkAtomRecords(datablock &db)
|
||||
items.emplace_back(item{ "formula_weight", compound->formula_weight() });
|
||||
|
||||
if (not items.empty())
|
||||
chem_comp_entry.assign(std::move(items));
|
||||
chem_comp_entry.assign(items);
|
||||
}
|
||||
|
||||
if (is_peptide and not has_seq_id(k))
|
||||
if (is_polymer and not has_seq_id(k))
|
||||
throw std::runtime_error("atom_site record has peptide comp_id but no sequence number, cannot continue");
|
||||
|
||||
int seq_id = get_seq_id(k);
|
||||
|
||||
if (row["label_seq_id"].empty())
|
||||
if (is_polymer and row["label_seq_id"].empty() and cf.is_monomer(comp_id))
|
||||
row["label_seq_id"] = std::to_string(seq_id);
|
||||
|
||||
if (row["label_atom_id"].empty())
|
||||
row["label_atom_id"] = row["auth_atom_id"].text();
|
||||
if (row["label_asym_id"].empty())
|
||||
row["label_asym_id"] = row["auth_asym_id"].text();
|
||||
if (row["label_seq_id"].empty())
|
||||
row["label_seq_id"] = row["auth_seq_id"].text();
|
||||
if (row["label_comp_id"].empty())
|
||||
row["label_comp_id"] = row["auth_comp_id"].text();
|
||||
if (row["label_atom_id"].empty())
|
||||
@@ -448,14 +529,14 @@ void checkAtomRecords(datablock &db)
|
||||
|
||||
float v;
|
||||
auto s = row.get<std::string>(item_name);
|
||||
if (auto [ptr, ec] = cif::from_chars(s.data(), s.data() + s.length(), v); ec != std::errc())
|
||||
if (auto [ptr, ec] = cif::from_chars(s.data(), s.data() + s.length(), v); (bool)ec)
|
||||
continue;
|
||||
|
||||
if (s.length() < prec + 1 or s[s.length() - prec - 1] != '.')
|
||||
{
|
||||
char b[12];
|
||||
|
||||
if (auto [ptr, ec] = cif::to_chars(b, b + sizeof(b), v, cif::chars_format::fixed, prec); ec == std::errc())
|
||||
if (auto [ptr, ec] = cif::to_chars(b, b + sizeof(b), v, cif::chars_format::fixed, prec); (bool)ec)
|
||||
row.assign(item_name, { b, static_cast<std::string::size_type>(ptr - b) }, false, false);
|
||||
}
|
||||
}
|
||||
@@ -517,21 +598,21 @@ void checkAtomAnisotropRecords(datablock &db)
|
||||
{
|
||||
if (cif::VERBOSE and std::exchange(warnReplaceTypeSymbol, false))
|
||||
std::clog << "Replacing type_symbol in atom_site_anisotrop record(s)\n";
|
||||
row["type_symbol"] != parent["type_symbol"].text();
|
||||
row["type_symbol"] = parent["type_symbol"].text();
|
||||
}
|
||||
|
||||
if (row["pdbx_auth_alt_id"].empty())
|
||||
if (row["pdbx_auth_alt_id"].empty() and not parent["pdbx_auth_alt_id"].empty())
|
||||
row["pdbx_auth_alt_id"] = parent["pdbx_auth_alt_id"].text();
|
||||
if (row["pdbx_label_seq_id"].empty())
|
||||
if (row["pdbx_label_seq_id"].empty() and not parent["pdbx_label_seq_id"].empty())
|
||||
row["pdbx_label_seq_id"] = parent["label_seq_id"].text();
|
||||
if (row["pdbx_label_asym_id"].empty())
|
||||
if (row["pdbx_label_asym_id"].empty() and not parent["pdbx_label_asym_id"].empty())
|
||||
row["pdbx_label_asym_id"] = parent["label_asym_id"].text();
|
||||
if (row["pdbx_label_atom_id"].empty())
|
||||
if (row["pdbx_label_atom_id"].empty() and not parent["pdbx_label_atom_id"].empty())
|
||||
row["pdbx_label_atom_id"] = parent["label_atom_id"].text();
|
||||
if (row["pdbx_label_comp_id"].empty())
|
||||
if (row["pdbx_label_comp_id"].empty() and not parent["pdbx_label_comp_id"].empty())
|
||||
row["pdbx_label_comp_id"] = parent["label_comp_id"].text();
|
||||
if (row["pdbx_PDB_model_num"].empty())
|
||||
row["pdbx_PDB_model_num"] = parent["pdbx_PDB_model_num"].text();
|
||||
// if (row["pdbx_PDB_model_num"].empty() and not parent["pdbx_PDB_model_num"].empty())
|
||||
// row["pdbx_PDB_model_num"] = parent["pdbx_PDB_model_num"].text();
|
||||
}
|
||||
|
||||
if (not to_be_deleted.empty())
|
||||
@@ -705,7 +786,11 @@ void createEntityPoly(datablock &db)
|
||||
if (cf.is_base(comp_id))
|
||||
{
|
||||
c_type = "polydeoxyribonucleotide";
|
||||
letter = letter_can = compound_factory::kBaseMap.at(comp_id);
|
||||
letter_can = compound_factory::kBaseMap.at(comp_id);
|
||||
if (comp_id.length() == 1)
|
||||
letter = letter_can;
|
||||
else
|
||||
letter = '(' + letter_can + ')';
|
||||
}
|
||||
else if (cf.is_peptide(comp_id))
|
||||
{
|
||||
@@ -737,6 +822,18 @@ void createEntityPoly(datablock &db)
|
||||
|
||||
non_std_monomer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// c_type = "other";
|
||||
|
||||
letter_can = c->one_letter_code();
|
||||
if (letter_can == 0)
|
||||
letter_can = 'X';
|
||||
|
||||
letter = '(' + comp_id + ')';
|
||||
|
||||
non_std_monomer = true;
|
||||
}
|
||||
|
||||
if (type.empty())
|
||||
type = c_type;
|
||||
@@ -803,7 +900,7 @@ void createEntityPoly(datablock &db)
|
||||
|
||||
void createEntityPolySeq(datablock &db)
|
||||
{
|
||||
if (db.get("entity_poly") == nullptr)
|
||||
if (auto cat = db.get("entity_poly"); cat == nullptr or cat->empty())
|
||||
createEntityPoly(db);
|
||||
|
||||
using namespace literals;
|
||||
@@ -854,7 +951,10 @@ void createEntityPolySeq(datablock &db)
|
||||
|
||||
void createPdbxPolySeqScheme(datablock &db)
|
||||
{
|
||||
if (db.get("entity_poly_seq") == nullptr)
|
||||
if (auto cat = db.get("entity_poly"); cat == nullptr or cat->empty())
|
||||
createEntityPoly(db);
|
||||
|
||||
if (auto cat = db.get("entity_poly_seq"); cat == nullptr or cat->empty())
|
||||
createEntityPolySeq(db);
|
||||
|
||||
using namespace literals;
|
||||
@@ -991,7 +1091,7 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
// ... and any additional datablock will contain compound information
|
||||
cif::compound_source cs(file);
|
||||
|
||||
if (db.get("atom_site") == nullptr)
|
||||
if (auto cat = db.get("atom_site"); cat == nullptr or cat->empty())
|
||||
throw std::runtime_error("Cannot reconstruct PDBx file, atom data missing");
|
||||
|
||||
auto &validator = validator_factory::instance()[dictionary];
|
||||
@@ -999,7 +1099,7 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
std::string entry_id;
|
||||
|
||||
// Phenix files do not have an entry record
|
||||
if (db.get("entry") == nullptr)
|
||||
if (auto cat = db.get("entry"); cat == nullptr or cat->empty())
|
||||
{
|
||||
entry_id = db.name();
|
||||
category entry("entry");
|
||||
@@ -1064,7 +1164,7 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
iv->m_type != nullptr and
|
||||
iv->m_type->m_primitive_type == cif::DDL_PrimitiveType::Numb;
|
||||
|
||||
for (size_t ix = 0; auto row : cat)
|
||||
for (std::size_t ix = 0; auto row : cat)
|
||||
{
|
||||
if (number)
|
||||
row.assign(key, std::to_string(++ix), false, false);
|
||||
@@ -1253,16 +1353,19 @@ bool reconstruct_pdbx(file &file, std::string_view dictionary)
|
||||
|
||||
// Now create any missing categories
|
||||
// Next make sure we have struct_asym records
|
||||
if (db.get("struct_asym") == nullptr)
|
||||
if (auto cat = db.get("struct_asym"); cat == nullptr or cat->empty())
|
||||
createStructAsym(db);
|
||||
|
||||
if (db.get("entity") == nullptr)
|
||||
if (auto cat = db.get("entity"); cat == nullptr or cat->empty())
|
||||
createEntity(db);
|
||||
|
||||
if (db.get("pdbx_poly_seq_scheme") == nullptr)
|
||||
// fill in missing formula_weight, e.g.
|
||||
checkEntities(db);
|
||||
|
||||
if (auto cat = db.get("pdbx_poly_seq_scheme"); cat == nullptr or cat->empty())
|
||||
createPdbxPolySeqScheme(db);
|
||||
|
||||
if (db.get("ndb_poly_seq_scheme") != nullptr)
|
||||
if (auto cat = db.get("ndb_poly_seq_scheme"); cat == nullptr or cat->empty())
|
||||
comparePolySeqSchemes(db);
|
||||
|
||||
// skip unknown categories for now
|
||||
|
||||
@@ -48,7 +48,7 @@ condition get_parents_condition(const validator &validator, row_handle rh, const
|
||||
{
|
||||
condition cond;
|
||||
|
||||
for (size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
for (std::size_t ix = 0; ix < link->m_child_keys.size(); ++ix)
|
||||
{
|
||||
auto childValue = rh[link->m_child_keys[ix]];
|
||||
|
||||
@@ -71,7 +71,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary)
|
||||
{
|
||||
std::error_code ec;
|
||||
bool result = is_valid_pdbx_file(file, dictionary, ec);
|
||||
return result and ec == std::errc();
|
||||
return result and not (bool)ec;
|
||||
}
|
||||
|
||||
bool is_valid_pdbx_file(const file &file, std::error_code &ec)
|
||||
@@ -189,6 +189,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary, std::erro
|
||||
for (auto asym_id : struct_asym.find<std::string>("entity_id"_key == entity_id, "id"))
|
||||
{
|
||||
if (pdbx_poly_seq_scheme.count(
|
||||
"entity_id"_key == entity_id and
|
||||
"asym_id"_key == asym_id and
|
||||
"mon_id"_key == mon_id and
|
||||
"seq_id"_key == num and
|
||||
@@ -202,6 +203,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary, std::erro
|
||||
for (const auto &[seq_id, mon_id, hetero] : pdbx_poly_seq_scheme.find<int, std::string, bool>("entity_id"_key == entity_id, "seq_id", "mon_id", "hetero"))
|
||||
{
|
||||
if (entity_poly_seq.count(
|
||||
"entity_id"_key == entity_id and
|
||||
"mon_id"_key == mon_id and
|
||||
"num"_key == seq_id and
|
||||
"hetero"_key == hetero) != 1)
|
||||
@@ -326,7 +328,7 @@ bool is_valid_pdbx_file(const file &file, std::string_view dictionary, std::erro
|
||||
ec = make_error_code(validation_error::not_valid_pdbx);
|
||||
}
|
||||
|
||||
if (not result and ec == std::errc())
|
||||
if (not result and (bool)ec)
|
||||
ec = make_error_code(validation_error::not_valid_pdbx);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -111,7 +111,7 @@ sym_op::sym_op(std::string_view s)
|
||||
m_tb = r.ptr[2] - '0';
|
||||
m_tc = r.ptr[3] - '0';
|
||||
|
||||
if (r.ec != std::errc() or rnri > 192 or r.ptr[0] != '_' or m_ta > 9 or m_tb > 9 or m_tc > 9)
|
||||
if ((bool)r.ec or rnri > 192 or r.ptr[0] != '_' or m_ta > 9 or m_tb > 9 or m_tc > 9)
|
||||
throw std::invalid_argument("Could not convert string into sym_op");
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ std::string sym_op::string() const
|
||||
{
|
||||
char b[9];
|
||||
auto r = std::to_chars(b, b + sizeof(b), m_nr);
|
||||
if (r.ec != std::errc() or r.ptr > b + 4)
|
||||
if ((bool)r.ec or r.ptr > b + 4)
|
||||
throw std::runtime_error("Could not write out symmetry operation to string");
|
||||
|
||||
*r.ptr++ = '_';
|
||||
@@ -128,7 +128,7 @@ std::string sym_op::string() const
|
||||
*r.ptr++ = '0' + m_tc;
|
||||
*r.ptr = 0;
|
||||
|
||||
return { b, static_cast<size_t>(r.ptr - b) };
|
||||
return { b, static_cast<std::size_t>(r.ptr - b) };
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -184,7 +184,7 @@ void transformation::try_create_quaternion()
|
||||
|
||||
auto ev = es.eigenvalues();
|
||||
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
for (std::size_t j = 0; j < 4; ++j)
|
||||
{
|
||||
if (std::abs(ev[j].real() - 1) > 0.01)
|
||||
continue;
|
||||
@@ -221,7 +221,7 @@ transformation inverse(const transformation &t)
|
||||
spacegroup::spacegroup(int nr)
|
||||
: m_nr(nr)
|
||||
{
|
||||
const size_t N = kSymopNrTableSize;
|
||||
const std::size_t N = kSymopNrTableSize;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
@@ -234,7 +234,7 @@ spacegroup::spacegroup(int nr)
|
||||
|
||||
m_index = L;
|
||||
|
||||
for (size_t i = L; i < N and kSymopNrTable[i].spacegroup() == m_nr; ++i)
|
||||
for (std::size_t i = L; i < N and kSymopNrTable[i].spacegroup() == m_nr; ++i)
|
||||
emplace_back(kSymopNrTable[i].symop().data());
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ int get_space_group_number(std::string_view spacegroup)
|
||||
|
||||
int result = 0;
|
||||
|
||||
const size_t N = kNrOfSpaceGroups;
|
||||
const std::size_t N = kNrOfSpaceGroups;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
@@ -365,7 +365,7 @@ int get_space_group_number(std::string_view spacegroup)
|
||||
// not found, see if we can find a match based on xHM name
|
||||
if (result == 0)
|
||||
{
|
||||
for (size_t i = 0; i < kNrOfSpaceGroups; ++i)
|
||||
for (std::size_t i = 0; i < kNrOfSpaceGroups; ++i)
|
||||
{
|
||||
auto &sp = kSpaceGroups[i];
|
||||
if (sp.xHM == spacegroup)
|
||||
@@ -395,7 +395,7 @@ int get_space_group_number(std::string_view spacegroup, space_group_name type)
|
||||
|
||||
if (type == space_group_name::full)
|
||||
{
|
||||
const size_t N = kNrOfSpaceGroups;
|
||||
const std::size_t N = kNrOfSpaceGroups;
|
||||
int32_t L = 0, R = static_cast<int32_t>(N - 1);
|
||||
while (L <= R)
|
||||
{
|
||||
@@ -475,7 +475,7 @@ std::tuple<float,point,sym_op> crystal::closest_symmetry_copy(point a, point b)
|
||||
|
||||
a = orthogonal(fa, m_cell);
|
||||
|
||||
for (size_t i = 0; i < m_spacegroup.size(); ++i)
|
||||
for (std::size_t i = 0; i < m_spacegroup.size(); ++i)
|
||||
{
|
||||
sym_op s(static_cast<uint8_t>(i + 1));
|
||||
auto &t = m_spacegroup[i];
|
||||
|
||||
@@ -280,7 +280,7 @@ int main(int argc, char* const argv[])
|
||||
if (std::isdigit(line[0])) // start of new spacegroup
|
||||
{
|
||||
auto r = std::from_chars(line.data(), line.data() + line.length(), sgnr);
|
||||
if (r.ec != std::errc())
|
||||
if ((bool)r.ec)
|
||||
throw std::runtime_error("Error parsing symop.lib file");
|
||||
rnr = 1;
|
||||
continue;
|
||||
@@ -426,7 +426,7 @@ const space_group kSpaceGroups[] =
|
||||
out << R"(
|
||||
};
|
||||
|
||||
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
const std::size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
|
||||
const symop_datablock kSymopNrTable[] = {
|
||||
)";
|
||||
@@ -450,7 +450,7 @@ const symop_datablock kSymopNrTable[] = {
|
||||
|
||||
out << R"(};
|
||||
|
||||
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
const std::size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
|
||||
} // namespace mmcif
|
||||
)";
|
||||
|
||||
@@ -361,7 +361,7 @@ const space_group kSpaceGroups[] =
|
||||
|
||||
};
|
||||
|
||||
const size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
const std::size_t kNrOfSpaceGroups = sizeof(kSpaceGroups) / sizeof(space_group);
|
||||
|
||||
const symop_datablock kSymopNrTable[] = {
|
||||
// P 1
|
||||
@@ -5286,6 +5286,6 @@ const symop_datablock kSymopNrTable[] = {
|
||||
{ 5005, 4, { -1, 0, 0, 0, 1, 0, 0, 0,-1, 1, 2, 0, 0, 1, 2, } },
|
||||
};
|
||||
|
||||
const size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
const std::size_t kSymopNrTableSize = sizeof(kSymopNrTable) / sizeof(symop_datablock);
|
||||
|
||||
} // namespace mmcif
|
||||
|
||||
206
src/text.cpp
206
src/text.cpp
@@ -35,24 +35,24 @@ namespace cif
|
||||
// --------------------------------------------------------------------
|
||||
// This really makes a difference, having our own tolower routines
|
||||
|
||||
const uint8_t kCharToLowerMap[256] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
|
||||
const uint8_t kCharToLowerMap[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
@@ -171,7 +171,7 @@ std::string trim_right_copy(std::string_view s)
|
||||
e = pe;
|
||||
}
|
||||
|
||||
return {s.begin(), e};
|
||||
return { s.begin(), e };
|
||||
}
|
||||
|
||||
std::string trim_left_copy(std::string_view s)
|
||||
@@ -185,27 +185,46 @@ std::string trim_left_copy(std::string_view s)
|
||||
b = std::next(b);
|
||||
}
|
||||
|
||||
return {b, s.end()};
|
||||
return { b, s.end() };
|
||||
}
|
||||
|
||||
void trim_left(std::string &s)
|
||||
{
|
||||
auto b = s.begin();
|
||||
while (b != s.end())
|
||||
auto in = s.begin(), out = s.begin();
|
||||
|
||||
while (in != s.end() and std::isspace(*in))
|
||||
++in;
|
||||
|
||||
if (in == s.end())
|
||||
s.clear();
|
||||
else if (in != out)
|
||||
{
|
||||
if (not std::isspace(*b))
|
||||
break;
|
||||
|
||||
b = std::next(b);
|
||||
while (in != s.end())
|
||||
*out++ = *in++;
|
||||
s.erase(out, s.end());
|
||||
}
|
||||
|
||||
s.erase(s.begin(), b);
|
||||
}
|
||||
|
||||
void trim(std::string &s)
|
||||
{
|
||||
trim_right(s);
|
||||
trim_left(s);
|
||||
auto in = s.begin(), out = s.begin(), end = s.end();
|
||||
|
||||
while (end != s.begin() and std::isspace(*(end - 1)))
|
||||
--end;
|
||||
|
||||
while (in != end and std::isspace(*in))
|
||||
++in;
|
||||
|
||||
if (in == end)
|
||||
s.clear();
|
||||
else if (in != out)
|
||||
{
|
||||
while (in != end)
|
||||
*out++ = *in++;
|
||||
s.erase(out, s.end());
|
||||
}
|
||||
else if (end != s.end())
|
||||
s.erase(end, s.end());
|
||||
}
|
||||
|
||||
std::string trim_copy(std::string_view s)
|
||||
@@ -220,14 +239,14 @@ std::tuple<std::string, std::string> split_item_name(std::string_view item_name)
|
||||
if (item_name.empty())
|
||||
throw std::runtime_error("empty item_name");
|
||||
if (item_name[0] != '_')
|
||||
throw std::runtime_error("item_name '" + std::string { item_name } + "' does not start with underscore");
|
||||
throw std::runtime_error("item_name '" + std::string{ item_name } + "' does not start with underscore");
|
||||
|
||||
auto s = item_name.find('.');
|
||||
if (s == std::string::npos)
|
||||
// throw std::runtime_error("item_name does not contain dot (" + std::string{ item_name } + ')');
|
||||
return std::tuple<std::string, std::string>{ "", item_name.substr(1) };
|
||||
else
|
||||
return std::tuple<std::string, std::string>{item_name.substr(1, s - 1), item_name.substr(s + 1)};
|
||||
return std::tuple<std::string, std::string>{ item_name.substr(1, s - 1), item_name.substr(s + 1) };
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -242,8 +261,7 @@ std::string cif_id_for_number(int number)
|
||||
result += static_cast<char>('A' + r);
|
||||
|
||||
number = (number - r) / 26 - 1;
|
||||
}
|
||||
while (number >= 0);
|
||||
} while (number >= 0);
|
||||
|
||||
std::reverse(result.begin(), result.end());
|
||||
|
||||
@@ -298,29 +316,29 @@ enum LineBreakClass
|
||||
kLBC_Unknown
|
||||
};
|
||||
|
||||
const LineBreakClass kASCII_LBTable[128] =
|
||||
{
|
||||
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_CombiningMark, kLBC_BreakAfter, kLBC_LineFeed, kLBC_MandatoryBreak, kLBC_MandatoryBreak, kLBC_CarriageReturn, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_Space, kLBC_Exlamation, kLBC_Quotation, kLBC_Alphabetic, kLBC_PrefixNumeric, kLBC_PostfixNumeric, kLBC_Alphabetic, kLBC_Quotation,
|
||||
kLBC_OpenPunctuation, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_PrefixNumeric,
|
||||
const LineBreakClass kASCII_LBTable[128] = {
|
||||
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_CombiningMark, kLBC_BreakAfter, kLBC_LineFeed, kLBC_MandatoryBreak, kLBC_MandatoryBreak, kLBC_CarriageReturn, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark, kLBC_CombiningMark,
|
||||
kLBC_Space, kLBC_Exlamation, kLBC_Quotation, kLBC_Alphabetic, kLBC_PrefixNumeric, kLBC_PostfixNumeric, kLBC_Alphabetic, kLBC_Quotation,
|
||||
kLBC_OpenPunctuation, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_PrefixNumeric,
|
||||
|
||||
// comma treated differently here, it is not a numeric separator in PDB
|
||||
kLBC_SymbolAllowingBreakAfter /* kLBC_InfixNumericSeparator */,
|
||||
// comma treated differently here, it is not a numeric separator in PDB
|
||||
kLBC_SymbolAllowingBreakAfter /* kLBC_InfixNumericSeparator */,
|
||||
|
||||
kLBC_Hyphen, kLBC_InfixNumericSeparator, kLBC_SymbolAllowingBreakAfter,
|
||||
kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric,
|
||||
kLBC_Numeric, kLBC_Numeric, kLBC_InfixNumericSeparator, kLBC_InfixNumericSeparator, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Exlamation,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_PrefixNumeric, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_BreakAfter, kLBC_ClosePunctuation, kLBC_Alphabetic, kLBC_CombiningMark};
|
||||
kLBC_Hyphen, kLBC_InfixNumericSeparator, kLBC_SymbolAllowingBreakAfter,
|
||||
kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric, kLBC_Numeric,
|
||||
kLBC_Numeric, kLBC_Numeric, kLBC_InfixNumericSeparator, kLBC_InfixNumericSeparator, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Exlamation,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_PrefixNumeric, kLBC_CloseParenthesis, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic,
|
||||
kLBC_Alphabetic, kLBC_Alphabetic, kLBC_Alphabetic, kLBC_OpenPunctuation, kLBC_BreakAfter, kLBC_ClosePunctuation, kLBC_Alphabetic, kLBC_CombiningMark
|
||||
};
|
||||
|
||||
std::string::const_iterator nextLineBreak(std::string::const_iterator text, std::string::const_iterator end)
|
||||
{
|
||||
@@ -338,33 +356,33 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
|
||||
|
||||
const breakAction brkTable[27][27] = {
|
||||
// OP CL CP QU GL NS EX SY IS PR PO NU AL ID IN HY BA BB B2 ZW CM WJ H2 H3 JL JV JT
|
||||
/* OP */ {PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, CPB, PBK, PBK, PBK, PBK, PBK, PBK},
|
||||
/* CL */ {DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* CP */ {DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* QU */ {PBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
|
||||
/* GL */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
|
||||
/* NS */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* EX */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* SY */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* IS */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* PR */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, IBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
|
||||
/* PO */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* NU */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* AL */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* ID */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* IN */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* HY */ {DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* BA */ {DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* BB */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
|
||||
/* B2 */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, PBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* ZW */ {DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* CM */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK},
|
||||
/* WJ */ {IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK},
|
||||
/* H2 */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK},
|
||||
/* H3 */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK},
|
||||
/* JL */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, DBK},
|
||||
/* JV */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK},
|
||||
/* JT */ {DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK},
|
||||
/* OP */ { PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, PBK, CPB, PBK, PBK, PBK, PBK, PBK, PBK },
|
||||
/* CL */ { DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* CP */ { DBK, PBK, PBK, IBK, IBK, PBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* QU */ { PBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK },
|
||||
/* GL */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK },
|
||||
/* NS */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* EX */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* SY */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* IS */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* PR */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, IBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK },
|
||||
/* PO */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* NU */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* AL */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* ID */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* IN */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* HY */ { DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* BA */ { DBK, PBK, PBK, IBK, DBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* BB */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK },
|
||||
/* B2 */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, IBK, IBK, DBK, PBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* ZW */ { DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK, PBK, DBK, DBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* CM */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, DBK, IBK, IBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, DBK },
|
||||
/* WJ */ { IBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, IBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, IBK },
|
||||
/* H2 */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK },
|
||||
/* H3 */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK },
|
||||
/* JL */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, IBK, IBK, IBK, IBK, DBK },
|
||||
/* JV */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, IBK, IBK },
|
||||
/* JT */ { DBK, PBK, PBK, IBK, IBK, IBK, PBK, PBK, PBK, DBK, IBK, DBK, DBK, DBK, IBK, IBK, IBK, DBK, DBK, PBK, CIB, PBK, DBK, DBK, DBK, DBK, IBK },
|
||||
};
|
||||
|
||||
uint8_t ch = static_cast<uint8_t>(*text);
|
||||
@@ -415,10 +433,10 @@ std::string::const_iterator nextLineBreak(std::string::const_iterator text, std:
|
||||
return text;
|
||||
}
|
||||
|
||||
std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
std::vector<std::string> wrapLine(const std::string &text, std::size_t width)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::vector<size_t> offsets = {0};
|
||||
std::vector<std::size_t> offsets = { 0 };
|
||||
|
||||
auto b = text.begin();
|
||||
while (b != text.end())
|
||||
@@ -430,18 +448,18 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
b = e;
|
||||
}
|
||||
|
||||
size_t count = offsets.size() - 1;
|
||||
std::size_t count = offsets.size() - 1;
|
||||
|
||||
std::vector<size_t> minima(count + 1, 1000000);
|
||||
std::vector<std::size_t> minima(count + 1, 1000000);
|
||||
minima[0] = 0;
|
||||
std::vector<size_t> breaks(count + 1, 0);
|
||||
std::vector<std::size_t> breaks(count + 1, 0);
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
size_t j = i + 1;
|
||||
std::size_t j = i + 1;
|
||||
while (j <= count)
|
||||
{
|
||||
size_t w = offsets[j] - offsets[i];
|
||||
std::size_t w = offsets[j] - offsets[i];
|
||||
|
||||
if (w > width)
|
||||
break;
|
||||
@@ -449,7 +467,7 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
while (w > 0 and isspace(text[offsets[i] + w - 1]))
|
||||
--w;
|
||||
|
||||
size_t cost = minima[i];
|
||||
std::size_t cost = minima[i];
|
||||
if (j < count) // last line may be shorter
|
||||
cost += (width - w) * (width - w);
|
||||
|
||||
@@ -463,10 +481,10 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
}
|
||||
}
|
||||
|
||||
size_t j = count;
|
||||
std::size_t j = count;
|
||||
while (j > 0)
|
||||
{
|
||||
size_t i = breaks[j];
|
||||
std::size_t i = breaks[j];
|
||||
result.push_back(text.substr(offsets[i], offsets[j] - offsets[i]));
|
||||
j = i;
|
||||
}
|
||||
@@ -476,7 +494,7 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> word_wrap(const std::string &text, size_t width)
|
||||
std::vector<std::string> word_wrap(const std::string &text, std::size_t width)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
for (auto p : cif::split<std::string>(text, "\n"))
|
||||
|
||||
@@ -215,7 +215,7 @@ const char* kSpinner[] = {
|
||||
".", "o", "O", "0", "@", "*", " "
|
||||
};
|
||||
|
||||
const size_t kSpinnerCount = sizeof(kSpinner) / sizeof(char*);
|
||||
const std::size_t kSpinnerCount = sizeof(kSpinner) / sizeof(char*);
|
||||
|
||||
const int kSpinnerTimeInterval = 100;
|
||||
|
||||
@@ -235,7 +235,7 @@ void progress_bar_impl::print_progress()
|
||||
float progress = static_cast<float>(m_consumed) / m_max_value;
|
||||
|
||||
if (width < kMinBarWidth)
|
||||
std::cout << (100 * progress) << '%' << std::endl;
|
||||
std::cout << (100 * progress) << "%\n";
|
||||
else
|
||||
{
|
||||
uint32_t bar_width = 7 * width / 10;
|
||||
@@ -329,7 +329,7 @@ void progress_bar_impl::print_done()
|
||||
if (msg.length() < width)
|
||||
msg += std::string(width - msg.length(), ' ');
|
||||
|
||||
std::cout << '\r' << msg << std::endl;
|
||||
std::cout << '\r' << msg << '\n';
|
||||
}
|
||||
|
||||
progress_bar::progress_bar(int64_t inMax, const std::string &inAction)
|
||||
@@ -877,6 +877,21 @@ class resource_pool
|
||||
|
||||
resource_pool::resource_pool()
|
||||
{
|
||||
// directories are searched in reverse order
|
||||
|
||||
// As a last resort, try the location that might have been
|
||||
// used during installation, works only when running on an
|
||||
// OS with a proc file system.
|
||||
|
||||
std::error_code ec;
|
||||
if (auto exefile = fs::read_symlink("/proc/self/exe", ec); not ec and exefile.parent_path().filename() == "bin")
|
||||
{
|
||||
auto install_prefix = exefile.parent_path().parent_path();
|
||||
auto data_dir = install_prefix / "share" / "libcifpp";
|
||||
if (fs::exists(data_dir, ec))
|
||||
pushDir(data_dir);
|
||||
}
|
||||
|
||||
#if defined(DATA_DIR)
|
||||
pushDir(DATA_DIR);
|
||||
#endif
|
||||
|
||||
@@ -55,14 +55,12 @@ validation_exception::validation_exception(std::error_code ec)
|
||||
}
|
||||
|
||||
validation_exception::validation_exception(std::error_code ec, std::string_view category)
|
||||
: runtime_error(
|
||||
(std::ostringstream{} << ec.message() << "; category: " << std::quoted(category)).str())
|
||||
: runtime_error((ec.message() + "; category: ").append(category))
|
||||
{
|
||||
}
|
||||
|
||||
validation_exception::validation_exception(std::error_code ec, std::string_view category, std::string_view item)
|
||||
: runtime_error(
|
||||
(std::ostringstream{} << ec.message() << "; category: " << std::quoted(category) << "; item: " << std::quoted(item)).str())
|
||||
: runtime_error((ec.message() + "; category: ").append(category).append("; item: ").append(item))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +79,7 @@ struct regex_impl : public regex
|
||||
DDL_PrimitiveType map_to_primitive_type(std::string_view s, std::error_code &ec) noexcept
|
||||
{
|
||||
ec = {};
|
||||
DDL_PrimitiveType result;
|
||||
DDL_PrimitiveType result = DDL_PrimitiveType::Char;
|
||||
if (iequals(s, "char"))
|
||||
result = DDL_PrimitiveType::Char;
|
||||
else if (iequals(s, "uchar"))
|
||||
@@ -140,7 +138,7 @@ int type_validator::compare(std::string_view a, std::string_view b) const
|
||||
ra = selected_charconv<double>::from_chars(a.data(), a.data() + a.length(), da);
|
||||
rb = selected_charconv<double>::from_chars(b.data(), b.data() + b.length(), db);
|
||||
|
||||
if (ra.ec == std::errc() and rb.ec == std::errc())
|
||||
if (not (bool)ra.ec and not (bool)rb.ec)
|
||||
{
|
||||
auto d = da - db;
|
||||
if (std::abs(d) > std::numeric_limits<double>::epsilon())
|
||||
@@ -151,7 +149,7 @@ int type_validator::compare(std::string_view a, std::string_view b) const
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
else if (ra.ec == std::errc())
|
||||
else if ((bool)ra.ec)
|
||||
result = 1;
|
||||
else
|
||||
result = -1;
|
||||
@@ -224,7 +222,7 @@ void item_validator::operator()(std::string_view value) const
|
||||
|
||||
bool item_validator::validate_value(std::string_view value, std::error_code &ec) const noexcept
|
||||
{
|
||||
ec = {};
|
||||
ec.clear();
|
||||
|
||||
if (not value.empty() and value != "?" and value != ".")
|
||||
{
|
||||
@@ -234,7 +232,7 @@ bool item_validator::validate_value(std::string_view value, std::error_code &ec)
|
||||
ec = make_error_code(validation_error::value_is_not_in_enumeration_list);
|
||||
}
|
||||
|
||||
return ec == std::errc();
|
||||
return not (bool)ec;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -355,7 +353,7 @@ void validator::add_link_validator(link_validator &&v)
|
||||
if (ccv == nullptr)
|
||||
throw std::runtime_error("unknown child category " + v.m_child_category);
|
||||
|
||||
for (size_t i = 0; i < v.m_parent_keys.size(); ++i)
|
||||
for (std::size_t i = 0; i < v.m_parent_keys.size(); ++i)
|
||||
{
|
||||
auto piv = pcv->get_validator_for_item(v.m_parent_keys[i]);
|
||||
|
||||
|
||||
75
test/CMakeLists.txt
Normal file
75
test/CMakeLists.txt
Normal file
@@ -0,0 +1,75 @@
|
||||
# We're using the older version 2 of Catch2
|
||||
|
||||
if(NOT(Catch2_FOUND OR TARGET Catch2))
|
||||
find_package(Catch2 QUIET)
|
||||
|
||||
if(NOT Catch2_FOUND)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v2.13.9)
|
||||
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
|
||||
set(Catch2_VERSION "2.13.9")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(
|
||||
APPEND
|
||||
CIFPP_tests
|
||||
unit-v2
|
||||
unit-3d
|
||||
format
|
||||
model
|
||||
rename-compound
|
||||
sugar
|
||||
spinner
|
||||
# reconstruction
|
||||
validate-pdbx)
|
||||
|
||||
add_library(test-main OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/test-main.cpp")
|
||||
|
||||
target_link_libraries(test-main cifpp::cifpp Catch2::Catch2)
|
||||
|
||||
if(${Catch2_VERSION} VERSION_GREATER_EQUAL 3.0.0)
|
||||
target_compile_definitions(test-main PUBLIC CATCH22=0)
|
||||
else()
|
||||
target_compile_definitions(test-main PUBLIC CATCH22=1)
|
||||
endif()
|
||||
|
||||
foreach(CIFPP_TEST IN LISTS CIFPP_tests)
|
||||
set(CIFPP_TEST "${CIFPP_TEST}-test")
|
||||
set(CIFPP_TEST_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/${CIFPP_TEST}.cpp")
|
||||
|
||||
add_executable(
|
||||
${CIFPP_TEST} ${CIFPP_TEST_SOURCE} $<TARGET_OBJECTS:test-main>)
|
||||
|
||||
if(${Catch2_VERSION} VERSION_GREATER_EQUAL 3.0.0)
|
||||
target_compile_definitions(${CIFPP_TEST} PUBLIC CATCH22=0)
|
||||
else()
|
||||
target_compile_definitions(${CIFPP_TEST} PUBLIC CATCH22=1)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${CIFPP_TEST} PRIVATE cifpp::cifpp Catch2::Catch2)
|
||||
target_include_directories(${CIFPP_TEST} PRIVATE "${EIGEN_INCLUDE_DIR}")
|
||||
|
||||
if(MSVC)
|
||||
# Specify unwind semantics so that MSVC knowns how to handle exceptions
|
||||
target_compile_options(${CIFPP_TEST} PRIVATE /EHsc)
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
"run-${CIFPP_TEST}"
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch ${CIFPP_TEST})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Run${CIFPP_TEST}.touch
|
||||
COMMAND $<TARGET_FILE:${CIFPP_TEST}> --data-dir
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_test(NAME ${CIFPP_TEST} COMMAND $<TARGET_FILE:${CIFPP_TEST}> --data-dir
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endforeach()
|
||||
@@ -24,7 +24,8 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
@@ -26,19 +26,17 @@
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -165,10 +163,10 @@ _atom_type.symbol C
|
||||
|
||||
if (not(expected.front() == structure.get_datablock()))
|
||||
{
|
||||
REQUIRE(false);
|
||||
std::cout << expected.front() << '\n'
|
||||
std::cerr << expected.front() << '\n'
|
||||
<< '\n'
|
||||
<< structure.get_datablock() << '\n';
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
@@ -56,7 +54,7 @@ TEST_CASE("reconstruct")
|
||||
|
||||
std::error_code ec;
|
||||
CHECK_FALSE(cif::pdb::is_valid_pdbx_file(f, ec));
|
||||
CHECK(ec != std::errc{});
|
||||
CHECK((bool)ec);
|
||||
|
||||
CHECK(cif::pdb::reconstruct_pdbx(f));
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
#include "cif++/utilities.hpp"
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include "cif++/utilities.hpp"
|
||||
|
||||
#include <random>
|
||||
#include <thread>
|
||||
|
||||
@@ -26,19 +26,17 @@
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char* text, size_t length)
|
||||
cif::file operator""_cf(const char* text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char* text, size_t length)
|
||||
membuf(char* text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -133,7 +131,7 @@ TEST_CASE("sugar_name_1")
|
||||
// auto &db = s.get_datablock();
|
||||
// auto &as = db["atom_site"];
|
||||
|
||||
// for (size_t i = 0; i < 2; ++i)
|
||||
// for (std::size_t i = 0; i < 2; ++i)
|
||||
// {
|
||||
// for (auto r : as.find("label_asym_id"_key == "H" and "auth_seq_id"_key == i + 1))
|
||||
// /*auto &ri = */ai[i].emplace_back(r);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#define CATCH_CONFIG_RUNNER 1
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
std::filesystem::path gTestDir = std::filesystem::current_path();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -12,7 +11,13 @@ int main(int argc, char *argv[])
|
||||
Catch::Session session; // There must be exactly one instance
|
||||
|
||||
// Build a new parser on top of Catch2's
|
||||
#if CATCH22
|
||||
using namespace Catch::clara;
|
||||
#else
|
||||
// Build a new parser on top of Catch2's
|
||||
using namespace Catch::Clara;
|
||||
#endif
|
||||
|
||||
auto cli = session.cli() // Get Catch2's command line parser
|
||||
| Opt(gTestDir, "data-dir") // bind variable to a new option, with a hint string
|
||||
["-D"]["--data-dir"] // the option names it will respond to
|
||||
|
||||
@@ -1,3 +1,37 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 NKI/AVL, Netherlands Cancer Institute
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if CATCH22
|
||||
#include <catch2/catch.hpp>
|
||||
#else
|
||||
#include <catch2/catch_all.hpp>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
extern std::filesystem::path gTestDir;
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cif++.hpp>
|
||||
@@ -36,11 +34,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -159,29 +157,29 @@ TEST_CASE("dh_q_0")
|
||||
};
|
||||
|
||||
auto a = cif::dihedral_angle(t[0], t[1], t[2], p);
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(0.f, 0.01f));
|
||||
|
||||
auto q = cif::construct_from_angle_axis(90, axis);
|
||||
|
||||
p.rotate(q);
|
||||
|
||||
REQUIRE_THAT(p.m_x, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE_THAT(p.m_y, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE_THAT(p.m_z, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE(std::abs(p.m_x - 1.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_y - 0.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_z - 1.f) < 0.01f);
|
||||
|
||||
a = cif::dihedral_angle(t[0], t[1], t[2], p);
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(90, 0.01f));
|
||||
REQUIRE(std::abs(a - 90.f) < 0.01f);
|
||||
|
||||
q = cif::construct_from_angle_axis(-90, axis);
|
||||
|
||||
p.rotate(q);
|
||||
|
||||
REQUIRE_THAT(p.m_x, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE_THAT(p.m_y, Catch::Matchers::WithinRel(1, 0.01f));
|
||||
REQUIRE_THAT(p.m_z, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE(std::abs(p.m_x - 1.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_y - 1.f) < 0.01f);
|
||||
REQUIRE(std::abs(p.m_z - 0.f) < 0.01f);
|
||||
|
||||
a = cif::dihedral_angle(t[0], t[1], t[2], p);
|
||||
REQUIRE_THAT(a, Catch::Matchers::WithinRel(0, 0.01f));
|
||||
REQUIRE(std::abs(a - 0.f) < 0.01f);
|
||||
|
||||
}
|
||||
|
||||
@@ -232,7 +230,7 @@ TEST_CASE("dh_q_1")
|
||||
|
||||
TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
{
|
||||
for (size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
for (std::size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
{
|
||||
auto d = cif::kSymopNrTable[i].symop().data();
|
||||
|
||||
@@ -258,10 +256,10 @@ TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
|
||||
auto ev = es.eigenvalues();
|
||||
|
||||
size_t bestJ = 0;
|
||||
std::size_t bestJ = 0;
|
||||
float bestEV = -1;
|
||||
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
for (std::size_t j = 0; j < 4; ++j)
|
||||
{
|
||||
if (bestEV < ev[j].real())
|
||||
{
|
||||
@@ -295,7 +293,7 @@ TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
|
||||
// "TEST_CASE(m2q_1, *utf::tolerance(0.001f)")
|
||||
// {
|
||||
// for (size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
// for (std::size_t i = 0; i < cif::kSymopNrTableSize; ++i)
|
||||
// {
|
||||
// auto d = cif::kSymopNrTable[i].symop().data();
|
||||
|
||||
@@ -319,10 +317,10 @@ TEST_CASE("m2q_0, *utf::tolerance(0.001f)")
|
||||
|
||||
// auto &&[ev, em] = cif::eigen(m * (1/3.0f), false);
|
||||
|
||||
// size_t bestJ = 0;
|
||||
// std::size_t bestJ = 0;
|
||||
// float bestEV = -1;
|
||||
|
||||
// for (size_t j = 0; j < 4; ++j)
|
||||
// for (std::size_t j = 0; j < 4; ++j)
|
||||
// {
|
||||
// if (bestEV < ev[j])
|
||||
// {
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#include "cif++/dictionary_parser.hpp"
|
||||
@@ -36,11 +34,11 @@
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -52,6 +50,32 @@ cif::file operator""_cf(const char *text, size_t length)
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("from_chars_1")
|
||||
{
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
_test.v
|
||||
616.487
|
||||
616.487000
|
||||
)"_cf;
|
||||
|
||||
auto &db = f.front();
|
||||
auto &c = db.front();
|
||||
|
||||
auto r1 = c.front();
|
||||
REQUIRE(r1.get<double>("v") == 616.487);
|
||||
REQUIRE(r1["v"].compare(616.487) == 0);
|
||||
|
||||
auto r2 = c.back();
|
||||
REQUIRE(r2.get<double>("v") == 616.487);
|
||||
REQUIRE(r2["v"].compare(616.487) == 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("id_1")
|
||||
{
|
||||
REQUIRE(cif::cif_id_for_number(0) == "A");
|
||||
@@ -103,7 +127,7 @@ TEST_CASE("cc_1")
|
||||
float tv;
|
||||
const auto &[ptr, ec] = cif::from_chars(txt.data(), txt.data() + txt.length(), tv);
|
||||
|
||||
REQUIRE(ec == std::errc());
|
||||
CHECK_FALSE((bool)ec);
|
||||
REQUIRE(tv == val);
|
||||
if (ch != 0)
|
||||
REQUIRE(*ptr == ch);
|
||||
@@ -121,7 +145,7 @@ TEST_CASE("cc_2")
|
||||
char buffer[64];
|
||||
const auto &[ptr, ec] = cif::to_chars(buffer, buffer + sizeof(buffer), val, cif::chars_format::fixed, prec);
|
||||
|
||||
REQUIRE(ec == std::errc());
|
||||
CHECK_FALSE((bool)ec);
|
||||
|
||||
REQUIRE(buffer == test);
|
||||
}
|
||||
@@ -242,7 +266,7 @@ TEST_CASE("r_2")
|
||||
{
|
||||
cif::category c("foo");
|
||||
|
||||
for (size_t i = 1; i < 256; ++i)
|
||||
for (std::size_t i = 1; i < 256; ++i)
|
||||
{
|
||||
c.emplace({ { "id", i },
|
||||
{ "txt", std::string(i, 'x') } });
|
||||
@@ -539,7 +563,7 @@ _test.value
|
||||
REQUIRE(not t.empty());
|
||||
REQUIRE(t.front()["name"].as<std::string>() == "aap");
|
||||
|
||||
auto t2 = test.find(cif::key("value") == 1.2f);
|
||||
auto t2 = test.find(cif::key("value") == 1.2);
|
||||
REQUIRE(not t2.empty());
|
||||
REQUIRE(t2.front()["name"].as<std::string>() == "mies");
|
||||
}
|
||||
@@ -574,6 +598,28 @@ _test.value
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("compare-with-float")
|
||||
{
|
||||
auto f = R"(data_TEST
|
||||
#
|
||||
loop_
|
||||
_test.id
|
||||
_test.value
|
||||
1 1.0
|
||||
2 2.0
|
||||
3 3.0
|
||||
4 ?
|
||||
5 .
|
||||
)"_cf;
|
||||
|
||||
auto &db = f.front();
|
||||
auto &cat = db["test"];
|
||||
|
||||
CHECK(cat.find_first<int>(cif::key("value") == 1.0, "id") == 1);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("sw_1")
|
||||
{
|
||||
using namespace cif::literals;
|
||||
@@ -702,7 +748,7 @@ save__cat_2.desc
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -737,7 +783,7 @@ _cat_2.desc
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -746,27 +792,51 @@ _cat_2.desc
|
||||
std::istream is_data(&data_buffer);
|
||||
f.load(is_data);
|
||||
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
SECTION("one")
|
||||
{
|
||||
auto &cat1 = f.front()["cat_1"];
|
||||
auto &cat2 = f.front()["cat_2"];
|
||||
|
||||
REQUIRE(cat1.size() == 3);
|
||||
REQUIRE(cat2.size() == 3);
|
||||
REQUIRE(cat1.size() == 3);
|
||||
REQUIRE(cat2.size() == 3);
|
||||
|
||||
cat1.erase(cif::key("id") == 1);
|
||||
cat1.erase(cif::key("id") == 1);
|
||||
|
||||
REQUIRE(cat1.size() == 2);
|
||||
REQUIRE(cat2.size() == 1);
|
||||
REQUIRE(cat1.size() == 2);
|
||||
REQUIRE(cat2.size() == 1);
|
||||
|
||||
// REQUIRE_THROWS_AS(cat2.emplace({
|
||||
// { "id", 4 },
|
||||
// { "parent_id", 4 },
|
||||
// { "desc", "moet fout gaan" }
|
||||
// }), std::exception);
|
||||
// REQUIRE_THROWS_AS(cat2.emplace({
|
||||
// { "id", 4 },
|
||||
// { "parent_id", 4 },
|
||||
// { "desc", "moet fout gaan" }
|
||||
// }), std::exception);
|
||||
|
||||
REQUIRE_THROWS_AS(cat2.emplace({ { "id", "vijf" }, // <- invalid value
|
||||
{ "parent_id", 2 },
|
||||
{ "desc", "moet fout gaan" } }),
|
||||
std::exception);
|
||||
REQUIRE_THROWS_AS(cat2.emplace({ { "id", "vijf" }, // <- invalid value
|
||||
{ "parent_id", 2 },
|
||||
{ "desc", "moet fout gaan" } }),
|
||||
std::exception);
|
||||
}
|
||||
|
||||
// SECTION("two")
|
||||
// {
|
||||
// auto &cat1 = f.front()["cat_1"];
|
||||
// auto &cat2 = f.front()["cat_2"];
|
||||
|
||||
// cat1.update_value(cif::all(), "id", [](std::string_view v) -> std::string
|
||||
// {
|
||||
// int vi;
|
||||
// auto [ec, ptr] = std::from_chars(v.data(), v.data() + v.length(), vi);
|
||||
// return std::to_string(vi + 1);
|
||||
// });
|
||||
|
||||
// REQUIRE(cat1.find1<std::string>(cif::key("id") == 2, "name") == "Aap");
|
||||
// REQUIRE(cat1.find1<std::string>(cif::key("id") == 3, "name") == "Noot");
|
||||
// REQUIRE(cat1.find1<std::string>(cif::key("id") == 4, "name") == "Mies");
|
||||
|
||||
// REQUIRE(cat2.find1<int>(cif::key("id") == 1, "parent_id") == 2);
|
||||
// REQUIRE(cat2.find1<int>(cif::key("id") == 2, "parent_id") == 2);
|
||||
// REQUIRE(cat2.find1<int>(cif::key("id") == 3, "parent_id") == 3);
|
||||
// }
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -831,7 +901,7 @@ save__cat_1.c
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -858,7 +928,7 @@ mies Mies
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -993,7 +1063,7 @@ save__cat_2.desc
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1031,7 +1101,7 @@ _cat_2.desc
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1196,7 +1266,7 @@ save__cat_2.parent_id3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1244,7 +1314,7 @@ _cat_2.parent_id3
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1417,7 +1487,7 @@ cat_2 3 cat_2:cat_1:3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1458,7 +1528,7 @@ _cat_2.parent_id3
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1657,7 +1727,7 @@ cat_2 1 cat_2:cat_1:1
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -1698,7 +1768,7 @@ _cat_2.parent_id_2
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2053,7 +2123,7 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2099,7 +2169,7 @@ _cat_3.num
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2338,7 +2408,7 @@ cat_2 1 '_cat_2.num' '_cat_3.num' cat_3
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2384,7 +2454,7 @@ _cat_3.num
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2545,11 +2615,11 @@ _cat_3.num
|
||||
// bonded.insert({atom_id_1, atom_id_2});
|
||||
// }
|
||||
|
||||
// for (size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
// for (std::size_t i = 0; i + 1 < atoms.size(); ++i)
|
||||
// {
|
||||
// auto label_i = atoms[i].labelAtomID();
|
||||
|
||||
// for (size_t j = i + 1; j < atoms.size(); ++j)
|
||||
// for (std::size_t j = i + 1; j < atoms.size(); ++j)
|
||||
// {
|
||||
// auto label_j = atoms[j].labelAtomID();
|
||||
|
||||
@@ -2570,7 +2640,7 @@ _cat_3.num
|
||||
|
||||
// auto &poly = structure.polymers().front();
|
||||
|
||||
// for (size_t i = 0; i + 1 < poly.size(); ++i)
|
||||
// for (std::size_t i = 0; i + 1 < poly.size(); ++i)
|
||||
// {
|
||||
// auto C = poly[i].atomByID("C");
|
||||
// auto N = poly[i + 1].atomByID("N");
|
||||
@@ -2672,7 +2742,7 @@ boo.data_.whatever
|
||||
|
||||
REQUIRE(test1.size() == sizeof(kS) / sizeof(T));
|
||||
|
||||
size_t i = 0;
|
||||
std::size_t i = 0;
|
||||
for (auto r : test1)
|
||||
{
|
||||
auto text = r.get<std::string>("text");
|
||||
@@ -2728,7 +2798,7 @@ There it was!)",
|
||||
|
||||
REQUIRE(test1.size() == sizeof(kS) / sizeof(T));
|
||||
|
||||
size_t i = 0;
|
||||
std::size_t i = 0;
|
||||
for (auto r : test1)
|
||||
{
|
||||
auto text = r.get<std::string>("text");
|
||||
@@ -2935,7 +3005,7 @@ save__cat_1.name
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -2962,7 +3032,7 @@ _cat_1.name
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3130,7 +3200,7 @@ save__cat_1.name
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3161,7 +3231,7 @@ _cat_1.name
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3237,7 +3307,7 @@ save__cat_1.id_2
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3266,7 +3336,7 @@ _cat_1.id_2
|
||||
|
||||
struct data_membuf : public std::streambuf
|
||||
{
|
||||
data_membuf(char *text, size_t length)
|
||||
data_membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3450,7 +3520,7 @@ ATOM 7 CD PRO A 1 15.762 13.216 43.724 1.00 30.71 C)"
|
||||
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
@@ -3486,4 +3556,11 @@ TEST_CASE("pdb2cif_formula_weight")
|
||||
|
||||
fw = a.front()["entity"].find1<float>(cif::key("id") == 3, "formula_weight");
|
||||
CHECK(fw == 18.015f);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("update_values_with_provider")
|
||||
{
|
||||
|
||||
}
|
||||
@@ -26,19 +26,17 @@
|
||||
|
||||
#include "test-main.hpp"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include <cif++.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
cif::file operator""_cf(const char *text, size_t length)
|
||||
cif::file operator""_cf(const char *text, std::size_t length)
|
||||
{
|
||||
struct membuf : public std::streambuf
|
||||
{
|
||||
membuf(char *text, size_t length)
|
||||
membuf(char *text, std::size_t length)
|
||||
{
|
||||
this->setg(text, text, text + length);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user