Compare commits

...

82 Commits

Author SHA1 Message Date
Maarten L. Hekkelman
a96b1e07f4 Merge remote-tracking branch 'origin/develop' into trunk 2024-09-10 11:34:00 +02:00
Maarten L. Hekkelman
f48c31bcb5 Proposed fix for comparing floating points (needed on macOS) (#62)
* Proposed fix for comparing floating points (needed on macOS)

* Work around weird behaviour in testing floats using catch2

* Better from_chars implementation
2024-09-10 11:31:59 +02:00
Maarten L. Hekkelman
d85ab93a35 Fix swap for incomplete rows 2024-08-27 15:48:20 +02:00
Maarten L. Hekkelman
a6804b5aca test on macOS 2024-07-22 12:31:17 +02:00
Maarten L. Hekkelman
e4dcb211ee modify tests for macOS? 2024-07-22 11:41:05 +02:00
Maarten L. Hekkelman
a5a5f47f7a Add missing file 2024-07-16 12:44:43 +02:00
Maarten L. Hekkelman
25c900c387 Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2024-07-16 12:08:59 +02:00
Maarten L. Hekkelman
4e95f7b83e restored find atomic 2024-07-16 12:08:43 +02:00
IdaDeVries
66ad3b0cee Use c++20 2024-07-15 09:54:17 +02:00
Maarten L. Hekkelman
e853cd1ca0 set_validator changes 2024-07-01 12:27:31 +02:00
Maarten L. Hekkelman
b9544033c6 Fix reconstruction 2024-07-01 12:16:11 +02:00
Maarten L. Hekkelman
17840cb8cc New dictionary 2024-07-01 12:15:39 +02:00
Maarten L. Hekkelman
f85b6d94b8 Attempt to get code compiling on msvc/macos 2024-06-12 10:25:23 +02:00
Maarten L. Hekkelman
6c32a9f198 Add operator != for optional type 2024-06-12 09:56:04 +02:00
Maarten L. Hekkelman
cefeebbfb8 fix rename in comment 2024-06-12 09:55:46 +02:00
Maarten L. Hekkelman
941a015b43 Do not stop when compound is missing 2024-05-15 09:05:01 +02:00
Maarten L. Hekkelman
ae0e9fbe77 fix cif::item constructor
fix ordering atoms
2024-04-29 12:06:50 +02:00
Maarten L. Hekkelman
3484c3dd2e Merge branch 'develop' of github.com:pdb-redo/libcifpp into develop 2024-04-29 08:34:19 +02:00
Maarten L. Hekkelman
5be8f749bd Fix validation error 2024-04-29 08:34:15 +02:00
Maarten L. Hekkelman
cf484707a0 Fix validation error 2024-04-29 08:30:11 +02:00
Maarten L. Hekkelman
f12e529c0b default alt id for new atoms 2024-04-24 13:21:32 +02:00
Maarten L. Hekkelman
01b90a2ba5 set occupancy of newly added atom 2024-04-23 15:42:55 +02:00
Maarten L. Hekkelman
cd1e952812 residue::create_new_atom 2024-04-23 13:50:25 +02:00
Maarten L. Hekkelman
996f1e4277 check existence of alternate for specific atoms 2024-04-17 16:49:37 +02:00
Maarten L. Hekkelman
2d84694f86 remove debug statement 2024-04-17 14:14:19 +02:00
Maarten L. Hekkelman
65718c64cc fix updating index for change in value in category 2024-04-17 12:54:58 +02:00
Maarten L. Hekkelman
6e30365f55 endl 2024-04-16 11:15:22 +02:00
Maarten L. Hekkelman
c0555b6d86 Export CIFPP_SHARE_DIR variable when included as sub directory 2024-04-10 11:38:23 +02:00
Maarten L. Hekkelman
1ff9b6c071 fix makefile 2024-04-08 10:32:35 +02:00
Maarten L. Hekkelman
c1a51a1dfa fix makefile 2024-04-08 10:31:08 +02:00
Maarten L. Hekkelman
bfbbeb90e7 fix makefile to create shared libraries when requested to do so
example should work when there is no components.cif file yet
2024-04-03 17:21:48 +02:00
Maarten L. Hekkelman
588e075325 Fix query generation when using constant numeric values
replace size_t with std::size_t to silence warnings
2024-04-03 14:01:51 +02:00
Maarten L. Hekkelman
66717fee68 take DESTDIR into account 2024-03-28 20:31:19 +01:00
Maarten L. Hekkelman
844f52c955 Merge branch 'develop' into trunk 2024-03-28 19:04:39 +01:00
Maarten L. Hekkelman
e679cd05c1 update changelog 2024-03-27 16:19:54 +01:00
Maarten L. Hekkelman
1e72ce4830 add missing header 2024-03-19 19:53:00 +01:00
Maarten L. Hekkelman
3bb21c5403 Try one more location to locate resources 2024-03-14 11:34:36 +01:00
Maarten L. Hekkelman
6d1be23ad0 oops 2024-03-14 11:12:39 +01:00
Maarten L. Hekkelman
0472b9a4a4 Merge branch 'trunk' into develop 2024-03-14 10:55:22 +01:00
Maarten L. Hekkelman
c9acff49f9 version bump, clean up makefile 2024-03-14 10:54:54 +01:00
Maarten L. Hekkelman
7cab560595 minimum requires cmake version 2024-03-14 07:37:50 +01:00
Maarten L. Hekkelman
ac98531a2f Fix writing exports file, version bump 2024-03-12 12:55:59 +01:00
Maarten L. Hekkelman
917e0ba79c Merge branch 'develop' of github.com:pdb-redo/libcifpp into develop 2024-03-12 10:12:55 +01:00
Maarten L. Hekkelman
3ebceb7522 do not number non-polymer residues 2024-03-12 10:12:50 +01:00
Maarten L. Hekkelman
92bd52da12 get that code compiling 2024-03-09 14:13:37 +01:00
Maarten L. Hekkelman
fb56a9cd6e version bump 2024-03-09 14:03:45 +01:00
Maarten L. Hekkelman
a4680f7d38 error_code should be checked differently? 2024-03-09 13:54:53 +01:00
Maarten L. Hekkelman
da8a72a8aa Merge branch 'develop' into trunk 2024-03-06 16:50:33 +01:00
Maarten L. Hekkelman
ac497932b5 Fix loading embedded restraint data 2024-03-06 16:50:12 +01:00
Maarten L. Hekkelman
9927b5061a Merge branch 'develop' of github.com:PDB-REDO/libcifpp into develop 2024-03-06 16:21:15 +01:00
Maarten L. Hekkelman
cedaab9642 load compound info from appended restraint info 2024-03-06 16:20:43 +01:00
Maarten L. Hekkelman
50bf2145ec Merge branch 'develop' into trunk 2024-03-06 15:54:56 +01:00
Maarten L. Hekkelman
dc77729f50 update changelog 2024-03-06 15:48:17 +01:00
Maarten L. Hekkelman
e3330d667a formatting 2024-03-06 13:22:00 +01:00
Maarten L. Hekkelman
9822f397a1 update libcifpp makefile 2024-03-06 12:58:50 +01:00
Maarten L. Hekkelman
a3b5ce9959 loading extra compound info changed
cif::file constructors
2024-03-06 12:33:58 +01:00
Maarten L. Hekkelman
9eb06e929a fixes in iterators 2024-03-05 15:52:36 +01:00
Maarten L. Hekkelman
629e06d647 write uncoloured text 2024-03-05 15:22:05 +01:00
Maarten L. Hekkelman
51ccb92184 small changes in constructors 2024-03-05 13:41:05 +01:00
Maarten L. Hekkelman
3cd27f13fd calculate formula_weight when missing 2024-03-05 13:02:31 +01:00
Maarten L. Hekkelman
ae668530c0 do not install files if they are not downloaded 2024-03-05 11:40:33 +01:00
Maarten L. Hekkelman
4a8b1c056c do not install files if they are not downloaded 2024-03-05 11:39:45 +01:00
Maarten L. Hekkelman
d7a5e598bc Merge branch 'develop' of github.com:pdb-redo/libcifpp into develop 2024-03-05 11:33:25 +01:00
Maarten L. Hekkelman
3f1ee32cc6 better trim 2024-03-05 11:33:19 +01:00
Maarten L. Hekkelman
725d6ead98 stupid typo 2024-02-29 14:56:45 +01:00
Maarten L. Hekkelman
baf70579de version bump 2024-02-27 15:23:51 +01:00
Maarten L. Hekkelman
cd28ab58a3 typo in error message 2024-02-27 14:40:56 +01:00
Maarten L. Hekkelman
a78fa0a81d reconstruction fixes 2024-02-27 13:36:45 +01:00
Maarten L. Hekkelman
82130be5f5 oops 2024-02-27 13:29:38 +01:00
Maarten L. Hekkelman
510ce62dfb reconstruction fixes 2024-02-27 13:24:53 +01:00
Maarten L. Hekkelman
93375a5087 Develop (#54)
* - renamed exists to contains
- fix compare for ints where item is empty

* - checking and optionally dropping ndb_poly_seq_scheme
- fix in iterator_proxy

* formatting data in reconstruction

* Version bump

* Attempt to get code compiling on macOS

* attempt 2 to build on macOS

* Added remove column

* Added rename_column
Added item_alias
Rename columns in reconstruct

* macOS...

* Fixed serious bug in emplace of both datablock and file.

* renaming field and column to item

* replace tag with item or item_name

* Fix validate pdbx

* version bump

* atom_site_anisotrop check

* - changed compound::is_known_peptide/is_know_base
- Add audit_conform only if file is really valid
- Added reconstruction code for PDBx

* pdb2cif work

* gcc diagnostics and clipper

* Fixing pdb2cif, and sequence checking

* work around bug in old gcc

* fix reconstruct sequence

* formatting

* some small optimisations

* Fix url in compound message

* Fix operator= for item_handle

* Fix operator= for item_handle

* new update_value in category

* test builds faster now

* Use Catch2 version 3 if installed

* catch22
2024-02-17 16:03:14 +01:00
Maarten L. Hekkelman
be738e7fb1 catch22 2024-02-17 15:37:53 +01:00
Maarten L. Hekkelman
9c78131df3 Use Catch2 version 3 if installed 2024-02-17 15:20:11 +01:00
Maarten L. Hekkelman
d94f6f4d19 test builds faster now 2024-02-05 13:01:28 +01:00
Maarten L. Hekkelman
9a3eced350 new update_value in category 2024-01-31 16:20:49 +01:00
Maarten L. Hekkelman
2fed7a76fb Fix operator= for item_handle 2024-01-30 16:51:12 +01:00
Maarten L. Hekkelman
f02e59df1b Fix operator= for item_handle 2024-01-30 16:40:02 +01:00
Maarten L. Hekkelman
04147a2fe9 Fix url in compound message 2024-01-30 16:39:32 +01:00
Maarten L. Hekkelman
0e83bc31dc some small optimisations 2024-01-30 16:29:22 +01:00
Maarten L. Hekkelman
75a5f7960f formatting 2024-01-30 11:12:29 +01:00
Maarten L. Hekkelman
3f93c27b07 fix reconstruct sequence 2024-01-29 17:40:24 +01:00
Maarten L. Hekkelman
ab781d4516 work around bug in old gcc 2024-01-29 16:33:53 +01:00
56 changed files with 10274 additions and 1506 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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.

View File

@@ -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()

View File

@@ -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())
{

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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));
}
// --------------------------------------------------------------------
/**

View File

@@ -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 */
/**

View File

@@ -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)), ...);

View File

@@ -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:

View File

@@ -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)

View File

@@ -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(); }

View File

@@ -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]) +

View File

@@ -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;

View File

@@ -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]; }

View File

@@ -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;

View File

@@ -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;
};
// --------------------------------------------------------------------

View File

@@ -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);

View File

@@ -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);
}
// --------------------------------------------------------------------

View File

@@ -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:

File diff suppressed because it is too large Load Diff

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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)

View File

@@ -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)

File diff suppressed because it is too large Load Diff

View File

@@ -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";

View File

@@ -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?

View File

@@ -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 }

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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];

View File

@@ -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
)";

View File

@@ -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

View File

@@ -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"))

View File

@@ -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

View File

@@ -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
View 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()

View File

@@ -24,7 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <catch2/catch.hpp>
#include "test-main.hpp"
#include <stdexcept>

View File

@@ -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);
}
}

View File

@@ -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));
}

View File

@@ -28,8 +28,6 @@
#include <cif++.hpp>
#include <catch2/catch.hpp>
#include <iostream>
#include <fstream>

View File

@@ -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>

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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])
// {

View File

@@ -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")
{
}

View File

@@ -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);
}