From 656c82838a9e745d141990402298b80726f78d6a Mon Sep 17 00:00:00 2001 From: "Maarten L. Hekkelman" Date: Mon, 5 Jan 2026 12:59:59 +0100 Subject: [PATCH] macOS and Windows fixes, start using clang-tidy --- .clang-tidy | 5 + CMakeLists.txt | 661 ++++++++++++++++++------------------ include/cif++/atom_type.hpp | 21 +- include/cif++/category.hpp | 92 ++--- include/cif++/compound.hpp | 34 +- include/cif++/utilities.hpp | 6 +- src/category.cpp | 78 ++--- src/cql.cpp | 71 ++-- src/text.cpp | 6 +- 9 files changed, 496 insertions(+), 478 deletions(-) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..13f38d6 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,5 @@ +Checks: '-*, + modernize*, + -modernize-use-trailing-return-type, + -modernize-avoid-c-arrays + ' diff --git a/CMakeLists.txt b/CMakeLists.txt index 48e06bf..4e3951c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,15 +27,15 @@ cmake_minimum_required(VERSION 3.23) cmake_policy(SET CMP0135 NEW) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() # set the project name project( - libcifpp - VERSION 10.0.0 - LANGUAGES CXX C) + libcifpp + VERSION 10.0.0 + LANGUAGES CXX C) list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -49,16 +49,16 @@ include(VersionString) # When building with ninja-multiconfig, build both debug and release by default if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") - set(CMAKE_CROSS_CONFIGS "Debug;Release") - set(CMAKE_DEFAULT_CONFIGS "Debug;Release") + set(CMAKE_CROSS_CONFIGS "Debug;Release") + set(CMAKE_DEFAULT_CONFIGS "Debug;Release") endif() if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers" - ) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers" + ) elseif(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") endif() # Build documentation? @@ -72,144 +72,144 @@ set(BUILD_SQLITE_INTERFACE ON CACHE BOOL "Build the sqlite interface") # Building shared libraries? if(NOT (BUILD_FOR_CCP4 AND WIN32)) - set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build a shared library instead of a static one") + set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build a shared library instead of a static one") endif() if(PROJECT_IS_TOP_LEVEL AND NOT BUILD_FOR_CCP4) - # Lots of code depend on the availability of the components.cif file - set(CIFPP_DOWNLOAD_CCD ON CACHE BOOL "Download the CCD file components.cif during installation") + # Lots of code depend on the availability of the components.cif file + set(CIFPP_DOWNLOAD_CCD ON CACHE BOOL "Download the CCD file components.cif during installation") - # An optional cron script can be installed to keep the data files up-to-date - if(UNIX AND NOT APPLE) - set(CIFPP_INSTALL_UPDATE_SCRIPT ON CACHE BOOL "Install the script to update CCD and dictionary files") - endif() + # An optional cron script can be installed to keep the data files up-to-date + if(UNIX AND NOT APPLE) + set(CIFPP_INSTALL_UPDATE_SCRIPT ON CACHE BOOL "Install the script to update CCD and dictionary files") + endif() else() - unset(CIFPP_DOWNLOAD_CCD) - unset(CIFPP_INSTALL_UPDATE_SCRIPT) + unset(CIFPP_DOWNLOAD_CCD) + unset(CIFPP_INSTALL_UPDATE_SCRIPT) endif() # When CCP4 is sourced in the environment, we can recreate the symmetry # operations table if(EXISTS "$ENV{CCP4}/lib/data/syminfo.lib") - set(CIFPP_RECREATE_SYMOP_DATA ON CACHE BOOL "Recreate SymOp data table in case it is out of date") + set(CIFPP_RECREATE_SYMOP_DATA ON CACHE BOOL "Recreate SymOp data table in case it is out of date") endif() # CCP4 build if(BUILD_FOR_CCP4) - if("$ENV{CCP4}" STREQUAL "" OR NOT EXISTS $ENV{CCP4}) - message(FATAL_ERROR "cifpp: A CCP4 built was requested but CCP4 was not sourced") - else() - list(PREPEND CMAKE_MODULE_PATH "$ENV{CCP4}") - list(PREPEND CMAKE_PREFIX_PATH "$ENV{CCP4}") - set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}") + if("$ENV{CCP4}" STREQUAL "" OR NOT EXISTS $ENV{CCP4}) + message(FATAL_ERROR "cifpp: A CCP4 built was requested but CCP4 was not sourced") + else() + list(PREPEND CMAKE_MODULE_PATH "$ENV{CCP4}") + list(PREPEND CMAKE_PREFIX_PATH "$ENV{CCP4}") + set(CMAKE_INSTALL_PREFIX "$ENV{CCP4}") - if(WIN32) - set(BUILD_SHARED_LIBS ON) - endif() - endif() + if(WIN32) + set(BUILD_SHARED_LIBS ON) + endif() + endif() endif() # Now include the GNUInstallDirs module include(GNUInstallDirs) if(WIN32) - if(${CMAKE_SYSTEM_VERSION} GREATER_EQUAL 10) # Windows 10 - add_definitions(-D _WIN32_WINNT=0x0A00) - elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.3) # Windows 8.1 - add_definitions(-D _WIN32_WINNT=0x0603) - elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.2) # Windows 8 - add_definitions(-D _WIN32_WINNT=0x0602) - elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.1) # Windows 7 - add_definitions(-D _WIN32_WINNT=0x0601) - elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.0) # Windows Vista - add_definitions(-D _WIN32_WINNT=0x0600) - else() # Windows XP (5.1) - add_definitions(-D _WIN32_WINNT=0x0501) - endif() + if(${CMAKE_SYSTEM_VERSION} GREATER_EQUAL 10) # Windows 10 + add_definitions(-D _WIN32_WINNT=0x0A00) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.3) # Windows 8.1 + add_definitions(-D _WIN32_WINNT=0x0603) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.2) # Windows 8 + add_definitions(-D _WIN32_WINNT=0x0602) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.1) # Windows 7 + add_definitions(-D _WIN32_WINNT=0x0601) + elseif(${CMAKE_SYSTEM_VERSION} EQUAL 6.0) # Windows Vista + add_definitions(-D _WIN32_WINNT=0x0600) + else() # Windows XP (5.1) + add_definitions(-D _WIN32_WINNT=0x0501) + endif() - # We do not want to write an export file for all our symbols... - set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + # We do not want to write an export file for all our symbols... + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) endif() if(MSVC) - # make msvc standards compliant... - add_compile_options(/permissive- /bigobj) - add_link_options(/NODEFAULTLIB:library) + # make msvc standards compliant... + add_compile_options(/permissive- /bigobj) + add_link_options(/NODEFAULTLIB:library) - # This is dubious... - if(BUILD_SHARED_LIBS) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") - else() - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - endif() + # This is dubious... + if(BUILD_SHARED_LIBS) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() endif() # Libraries if(MSVC) - # Avoid linking the shared library of zlib. Search ZLIB_ROOT first if it is - # set. - if(ZLIB_ROOT) - set(_ZLIB_SEARCH_ROOT PATHS ${ZLIB_ROOT} NO_DEFAULT_PATH) - list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT) - endif() + # Avoid linking the shared library of zlib. Search ZLIB_ROOT first if it is + # set. + if(ZLIB_ROOT) + set(_ZLIB_SEARCH_ROOT PATHS ${ZLIB_ROOT} NO_DEFAULT_PATH) + list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT) + endif() - # Normal search. - set(_ZLIB_x86 "(x86)") - set(_ZLIB_SEARCH_NORMAL - PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]" - "$ENV{ProgramFiles}/zlib" "$ENV{ProgramFiles${_ZLIB_x86}}/zlib") - unset(_ZLIB_x86) - list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL) + # Normal search. + set(_ZLIB_x86 "(x86)") + set(_ZLIB_SEARCH_NORMAL + PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]" + "$ENV{ProgramFiles}/zlib" "$ENV{ProgramFiles${_ZLIB_x86}}/zlib") + unset(_ZLIB_x86) + list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL) - if(BUILD_FOR_CCP4) - list(PREPEND _ZLIB_SEARCHES "$ENV{CCP4}/lib") - endif() + if(BUILD_FOR_CCP4) + list(PREPEND _ZLIB_SEARCHES "$ENV{CCP4}/lib") + endif() - foreach(search ${_ZLIB_SEARCHES}) - find_library( - ZLIB_LIBRARY - NAMES zlibstatic NAMES_PER_DIR ${${search}} - PATH_SUFFIXES lib) - endforeach() + foreach(search ${_ZLIB_SEARCHES}) + find_library( + ZLIB_LIBRARY + NAMES zlibstatic NAMES_PER_DIR ${${search}} + PATH_SUFFIXES lib) + endforeach() endif() set(CMAKE_CXX_STANDARD 20) # Using fast_float for float parsing, but only if needed try_compile(STD_CHARCONV_COMPILING - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-charconv.cpp - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON) + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-charconv.cpp + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED ON) if(NOT STD_CHARCONV_COMPILING) - message(NOTICE "libcifpp: Using fast_float for std::from_chars") - find_package(FastFloat 8.0 QUIET CONFIG) - if(NOT FastFloat_FOUND) - message(STATUS "FastFloat not found in system, fetching from GitHub") - FetchContent_Declare(fastfloat - GIT_REPOSITORY "https://github.com/fastfloat/fast_float" - GIT_TAG v8.0.2 - EXCLUDE_FROM_ALL) - FetchContent_MakeAvailable(fastfloat) - endif() + message(NOTICE "libcifpp: Using fast_float for std::from_chars") + find_package(FastFloat 8.0 QUIET CONFIG) + if(NOT FastFloat_FOUND) + message(STATUS "FastFloat not found in system, fetching from GitHub") + FetchContent_Declare(fastfloat + GIT_REPOSITORY "https://github.com/fastfloat/fast_float" + GIT_TAG v8.0.2 + EXCLUDE_FROM_ALL) + FetchContent_MakeAvailable(fastfloat) + endif() endif() find_package(Threads) find_package(ZLIB QUIET) if(NOT ZLIB_FOUND) - message(FATAL_ERROR "cifpp: 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)") + message(FATAL_ERROR "cifpp: 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() include(FindPkgConfig) if(PKG_CONFIG_FOUND) - pkg_check_modules(PCRE2 IMPORTED_TARGET libpcre2-8) + pkg_check_modules(PCRE2 IMPORTED_TARGET libpcre2-8) endif() if(NOT PCRE2_FOUND) - add_subdirectory(pcre2-simple) + add_subdirectory(pcre2-simple) endif() # Using Eigen3 is a bit of a thing. We don't want to build it completely since @@ -218,40 +218,40 @@ endif() find_package(Eigen3 3.4 QUIET) if(Eigen3_FOUND AND TARGET Eigen3::Eigen) - get_target_property(EIGEN_INCLUDE_DIR Eigen3::Eigen - INTERFACE_INCLUDE_DIRECTORIES) + get_target_property(EIGEN_INCLUDE_DIR Eigen3::Eigen + INTERFACE_INCLUDE_DIRECTORIES) else() - # Use ExternalProject since FetchContent always tries to install the result... - ExternalProject_Add(my-eigen3 - URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.zip - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "") + # Use ExternalProject since FetchContent always tries to install the result... + ExternalProject_Add(my-eigen3 + URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "") - ExternalProject_Get_Property(my-eigen3 SOURCE_DIR) - set(EIGEN_INCLUDE_DIR ${SOURCE_DIR}) + ExternalProject_Get_Property(my-eigen3 SOURCE_DIR) + set(EIGEN_INCLUDE_DIR ${SOURCE_DIR}) endif() # SymOp data table if(CIFPP_RECREATE_SYMOP_DATA) - # The tool to create the table - add_executable(symop-map-generator - "${CMAKE_CURRENT_SOURCE_DIR}/src/symop-map-generator.cpp") + # The tool to create the table + add_executable(symop-map-generator + "${CMAKE_CURRENT_SOURCE_DIR}/src/symop-map-generator.cpp") - target_compile_features(symop-map-generator PUBLIC cxx_std_20) + target_compile_features(symop-map-generator PUBLIC cxx_std_20) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp - COMMAND - $ $ENV{CLIBD}/syminfo.lib - $ENV{CLIBD}/symop.lib ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp + COMMAND + $ $ENV{CLIBD}/syminfo.lib + $ENV{CLIBD}/symop.lib ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp) - add_custom_target( - OUTPUT - ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp - DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib" - "$ENV{CLIBD}/symop.lib") + add_custom_target( + OUTPUT + ${CMAKE_CURRENT_SOURCE_DIR}/src/symop_table_data.hpp + DEPENDS symop-map-generator "$ENV{CLIBD}/syminfo.lib" + "$ENV{CLIBD}/symop.lib") endif() # Create a revision file, containing the current git version info @@ -262,324 +262,333 @@ add_library(cifpp::cifpp ALIAS cifpp) # Sources list(APPEND project_sources - ${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/cql.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 + ${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/cql.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 ) if(BUILD_SQLITE_INTERFACE) - find_package(sqlite3 QUIET) - if(sqlite3_FOUND) - target_link_libraries(cifpp PRIVATE sqlite3) - else() - FetchContent_Populate(sqlite3 - URL https://sqlite.org/2025/sqlite-amalgamation-3510100.zip - URL_HASH SHA3_256=856b52ffe7383d779bb86a0ed1ddc19c41b0e5751fa14ce6312f27534e629b64 - EXCLUDE_FROM_ALL) + find_package(sqlite3 QUIET) + if(sqlite3_FOUND) + target_link_libraries(cifpp PRIVATE sqlite3) + else() + FetchContent_Populate(sqlite3 + URL https://sqlite.org/2025/sqlite-amalgamation-3510100.zip + URL_HASH SHA3_256=856b52ffe7383d779bb86a0ed1ddc19c41b0e5751fa14ce6312f27534e629b64 + EXCLUDE_FROM_ALL) - list(APPEND project_sources $/sqlite3.c) - target_include_directories(cifpp PRIVATE $) - endif() + list(APPEND project_sources $/sqlite3.c) + target_include_directories(cifpp PRIVATE $) + endif() endif() list(APPEND project_headers - 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.hpp - include/cif++/point.hpp - include/cif++/row.hpp - include/cif++/symmetry.hpp - include/cif++/text.hpp - include/cif++/cql.hpp - include/cif++/utilities.hpp - include/cif++/validate.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.hpp + include/cif++/point.hpp + include/cif++/row.hpp + include/cif++/symmetry.hpp + include/cif++/text.hpp + include/cif++/cql.hpp + include/cif++/utilities.hpp + include/cif++/validate.hpp ) if(TARGET my-eigen3) - add_dependencies(cifpp my-eigen3) + add_dependencies(cifpp my-eigen3) endif() 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} + 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) +find_program(CLANG_TIDY_EXE "clang-tidy") + +if(CLANG_TIDY_EXE) + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_EXE} --warnings-as-errors=-*) +else() + message(WARNING "clang-tidy not found!") +endif() + generate_export_header(cifpp EXPORT_FILE_NAME - ${CMAKE_CURRENT_SOURCE_DIR}/include/cif++/exports.hpp) + ${CMAKE_CURRENT_SOURCE_DIR}/include/cif++/exports.hpp) if(MSVC) - target_compile_definitions(cifpp PUBLIC NOMINMAX=1) + target_compile_definitions(cifpp PUBLIC NOMINMAX=1) endif() set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON) target_include_directories( - cifpp - PUBLIC "$" - "$" - PRIVATE "${EIGEN_INCLUDE_DIR}") + cifpp + PUBLIC "$" + "$" + PRIVATE "${EIGEN_INCLUDE_DIR}") target_link_libraries(cifpp - PUBLIC Threads::Threads ZLIB::ZLIB $<$:std::atomic>) + PUBLIC Threads::Threads ZLIB::ZLIB $<$:std::atomic>) if(PCRE2_FOUND) - target_include_directories(cifpp PRIVATE ${PCRE2_INCLUDE_DIRS}) - target_link_libraries(cifpp PRIVATE ${PCRE2_LINK_LIBRARIES}) + target_include_directories(cifpp PRIVATE ${PCRE2_INCLUDE_DIRS}) + target_link_libraries(cifpp PRIVATE ${PCRE2_LINK_LIBRARIES}) else() - target_link_libraries(cifpp PRIVATE $) + target_link_libraries(cifpp PRIVATE $) endif() if(NOT STD_CHARCONV_COMPILING) - target_link_libraries(cifpp PRIVATE FastFloat::fast_float) + target_link_libraries(cifpp PRIVATE FastFloat::fast_float) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - target_link_options(cifpp PRIVATE -undefined dynamic_lookup) + target_link_options(cifpp PRIVATE -undefined dynamic_lookup) endif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") if(CIFPP_DOWNLOAD_CCD) - # download the components.cif file from CCD - set(COMPONENTS_CIF ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/components.cif) + # download the components.cif file from CCD + set(COMPONENTS_CIF ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/components.cif) - if(EXISTS ${COMPONENTS_CIF}) - file(SIZE ${COMPONENTS_CIF} CCD_FILE_SIZE) + if(EXISTS ${COMPONENTS_CIF}) + file(SIZE ${COMPONENTS_CIF} CCD_FILE_SIZE) - if(CCD_FILE_SIZE EQUAL 0) - message(STATUS "cifpp: Removing empty ${COMPONENTS_CIF} file") - file(REMOVE "${COMPONENTS_CIF}") - endif() - endif() + if(CCD_FILE_SIZE EQUAL 0) + message(STATUS "cifpp: Removing empty ${COMPONENTS_CIF} file") + file(REMOVE "${COMPONENTS_CIF}") + endif() + endif() - if(NOT EXISTS ${COMPONENTS_CIF}) - # Since the file(DOWNLOAD) command in cmake does not use compression, we try - # to download the gzipped version and decompress it ourselves. - find_program(GUNZIP gunzip) + if(NOT EXISTS ${COMPONENTS_CIF}) + # Since the file(DOWNLOAD) command in cmake does not use compression, we try + # to download the gzipped version and decompress it ourselves. + find_program(GUNZIP gunzip) - if(WIN32 OR GUNZIP STREQUAL "GUNZIP-NOTFOUND") - file( - DOWNLOAD https://files.wwpdb.org/pub/pdb/data/monomers/components.cif - ${COMPONENTS_CIF} - SHOW_PROGRESS - STATUS CCD_FETCH_STATUS) - else() - if(NOT EXISTS "${COMPONENTS_CIF}.gz") - file( - DOWNLOAD - https://files.wwpdb.org/pub/pdb/data/monomers/components.cif.gz - ${COMPONENTS_CIF}.gz - SHOW_PROGRESS - STATUS CCD_FETCH_STATUS) - endif() + if(WIN32 OR GUNZIP STREQUAL "GUNZIP-NOTFOUND") + file( + DOWNLOAD https://files.wwpdb.org/pub/pdb/data/monomers/components.cif + ${COMPONENTS_CIF} + SHOW_PROGRESS + STATUS CCD_FETCH_STATUS) + else() + if(NOT EXISTS "${COMPONENTS_CIF}.gz") + file( + DOWNLOAD + https://files.wwpdb.org/pub/pdb/data/monomers/components.cif.gz + ${COMPONENTS_CIF}.gz + SHOW_PROGRESS + STATUS CCD_FETCH_STATUS) + endif() - add_custom_command( - OUTPUT ${COMPONENTS_CIF} - COMMAND "${GUNZIP}" ${COMPONENTS_CIF}.gz - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/) + add_custom_command( + OUTPUT ${COMPONENTS_CIF} + COMMAND "${GUNZIP}" ${COMPONENTS_CIF}.gz + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rsrc/) - add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF}) - endif() + add_custom_target(COMPONENTS ALL DEPENDS ${COMPONENTS_CIF}) + endif() - # Do not continue if downloading went wrong - list(POP_FRONT CCD_FETCH_STATUS CCD_FETCH_STATUS_CODE) + # Do not continue if downloading went wrong + list(POP_FRONT CCD_FETCH_STATUS CCD_FETCH_STATUS_CODE) - if(CCD_FETCH_STATUS_CODE) - message( - FATAL_ERROR "cifpp: Error trying to download CCD file: ${CCD_FETCH_STATUS}") - endif() - endif() + if(CCD_FETCH_STATUS_CODE) + message( + FATAL_ERROR "cifpp: Error trying to download CCD file: ${CCD_FETCH_STATUS}") + endif() + endif() endif() # Installation directories if(BUILD_FOR_CCP4) - set(CIFPP_DATA_DIR - "$ENV{CCP4}/share/libcifpp" - CACHE PATH "Directory where dictionary and other static data is stored") + set(CIFPP_DATA_DIR + "$ENV{CCP4}/share/libcifpp" + CACHE PATH "Directory where dictionary and other static data is stored") else() - set(CIFPP_DATA_DIR - "${CMAKE_INSTALL_FULL_DATADIR}/libcifpp" - CACHE PATH "Directory where dictionary and other static data is stored") + set(CIFPP_DATA_DIR + "${CMAKE_INSTALL_FULL_DATADIR}/libcifpp" + CACHE PATH "Directory where dictionary and other static data is stored") endif() if(CIFPP_DATA_DIR) - target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}") - set_target_properties(cifpp PROPERTIES CIFPP_DATA_DIR ${CIFPP_DATA_DIR}) + target_compile_definitions(cifpp PUBLIC DATA_DIR="${CIFPP_DATA_DIR}") + set_target_properties(cifpp PROPERTIES CIFPP_DATA_DIR ${CIFPP_DATA_DIR}) endif() if(NOT PROJECT_IS_TOP_LEVEL) - set(CIFPP_SHARE_DIR ${CIFPP_DATA_DIR} PARENT_SCOPE) + 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 - "/var/cache/libcifpp" - CACHE PATH "The directory where downloaded data files are stored") - else() - set(CIFPP_CACHE_DIR - "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/cache/libcifpp" - CACHE PATH "The directory where downloaded data files are stored") - endif() + if("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local") + set(CIFPP_CACHE_DIR + "/var/cache/libcifpp" + CACHE PATH "The directory where downloaded data files are stored") + else() + set(CIFPP_CACHE_DIR + "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/cache/libcifpp" + CACHE PATH "The directory where downloaded data files are stored") + endif() - target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}") + target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}") - set(CIFPP_ETC_DIR - "${CMAKE_INSTALL_FULL_SYSCONFDIR}" - CACHE PATH "The directory where the update configuration file is stored") + set(CIFPP_ETC_DIR + "${CMAKE_INSTALL_FULL_SYSCONFDIR}" + CACHE PATH "The directory where the update configuration file is stored") else() - unset(CIFPP_CACHE_DIR) + unset(CIFPP_CACHE_DIR) endif() # Install rules install(TARGETS cifpp - EXPORT cifpp - FILE_SET cifpp_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + EXPORT cifpp + FILE_SET cifpp_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) if(MSVC AND BUILD_SHARED_LIBS) - install( - FILES $ - DESTINATION ${CMAKE_INSTALL_LIBDIR} - OPTIONAL) + install( + FILES $ + DESTINATION ${CMAKE_INSTALL_LIBDIR} + OPTIONAL) endif() # Clean up old config files (with old names) file(GLOB OLD_CONFIG_FILES - ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cifpp/cifppConfig*.cmake - ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cifpp/cifppTargets*.cmake) + ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cifpp/cifppConfig*.cmake + ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cifpp/cifppTargets*.cmake) if(OLD_CONFIG_FILES) - message( - STATUS "cifpp: Installation will remove old config files: ${OLD_CONFIG_FILES}") - install(CODE "file(REMOVE ${OLD_CONFIG_FILES})") + message( + STATUS "cifpp: Installation will remove old config files: ${OLD_CONFIG_FILES}") + install(CODE "file(REMOVE ${OLD_CONFIG_FILES})") endif() install(EXPORT cifpp - NAMESPACE cifpp:: - FILE "cifpp-targets.cmake" - DESTINATION lib/cmake/cifpp) + NAMESPACE cifpp:: + FILE "cifpp-targets.cmake" + DESTINATION lib/cmake/cifpp) install( - 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) + 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) if(CIFPP_DATA_DIR AND CIFPP_DOWNLOAD_CCD) - install(FILES ${COMPONENTS_CIF} - DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp) + install(FILES ${COMPONENTS_CIF} + DESTINATION ${CMAKE_INSTALL_DATADIR}/libcifpp) endif() 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 lib/cmake/cifpp - PATH_VARS CIFPP_DATA_DIR) + ${CONFIG_TEMPLATE_FILE} ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake + 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 lib/cmake/cifpp) + FILES "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake" + DESTINATION lib/cmake/cifpp) set_target_properties( - cifpp - PROPERTIES VERSION ${PROJECT_VERSION} - SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" - INTERFACE_cifpp_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}) + cifpp + PROPERTIES VERSION ${PROJECT_VERSION} + SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" + INTERFACE_cifpp_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}) set_property( - TARGET cifpp - APPEND - PROPERTY COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION) + TARGET cifpp + APPEND + PROPERTY COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION) write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY AnyNewerVersion) + "${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifpp-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion) if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL) - add_subdirectory(test) + add_subdirectory(test) endif() # Optionally install the update scripts for CCD and dictionary files if(CIFPP_INSTALL_UPDATE_SCRIPT) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tools/update-libcifpp-data.in - update-libcifpp-data @ONLY) + 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 "cifpp: Don't know where to install the update script") - endif() + 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 "cifpp: Don't know where to install the update script") + endif() - # a config file, to make it complete - # 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 + # a config file, to make it complete + # 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 ${CMAKE_INSTALL_SYSCONFDIR}) - install( - CODE "message(\"cifpp: A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")" - ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.conf + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}) + install( + CODE "message(\"cifpp: A configuration file has been written to ${CIFPP_ETC_DIR}/libcifpp.conf, please edit this file to enable automatic updates\")" + ) - install(DIRECTORY DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/libcifpp/cache-update.d) - endif() + install(DIRECTORY DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/libcifpp/cache-update.d) + endif() - target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}") + target_compile_definitions(cifpp PUBLIC CACHE_DIR="${CIFPP_CACHE_DIR}") endif() if(BUILD_DOCUMENTATION) - add_subdirectory(docs) + add_subdirectory(docs) endif() diff --git a/include/cif++/atom_type.hpp b/include/cif++/atom_type.hpp index 178e7a5..49fb6ca 100644 --- a/include/cif++/atom_type.hpp +++ b/include/cif++/atom_type.hpp @@ -33,6 +33,7 @@ #include "cif++/exports.hpp" +#include #include #include #include @@ -235,7 +236,7 @@ struct atom_type_info /// Array containing all known radii for this element. A value of kNA is /// stored for unknown values - float radii[kRadiusTypeCount]; + std::array radii; }; /// Array of atom_type_info struct for each of the defined elements in atom_type @@ -256,12 +257,12 @@ class atom_type_traits /// Constructor based on the element as a string in \a symbol atom_type_traits(const std::string &symbol); - atom_type type() const { return m_info->type; } ///< Returns the atom_type - std::string name() const { return m_info->name; } ///< Returns the name of the element - std::string symbol() const { return m_info->symbol; } ///< Returns the symbol of the element - float weight() const { return m_info->weight; } ///< Returns the average weight of the element + [[nodiscard]] atom_type type() const { return m_info->type; } ///< Returns the atom_type + [[nodiscard]] std::string name() const { return m_info->name; } ///< Returns the name of the element + [[nodiscard]] std::string symbol() const { return m_info->symbol; } ///< Returns the symbol of the element + [[nodiscard]] float weight() const { return m_info->weight; } ///< Returns the average weight of the element - bool is_metal() const { return m_info->metal; } ///< Returns true if the element is a metal + [[nodiscard]] bool is_metal() const { return m_info->metal; } ///< Returns true if the element is a metal /// Return true if the symbol in \a symbol actually exists in the list of known elements in atom_type static bool is_element(const std::string &symbol); @@ -272,7 +273,7 @@ class atom_type_traits /// @brief Return the radius for the element, use \a type to select which radius to return /// @param type The selector for which radius to return /// @return The requested radius or kNA if not known (or applicable) - float radius(radius_type type = radius_type::single_bond) const + [[nodiscard]] float radius(radius_type type = radius_type::single_bond) const { if (type >= radius_type::type_count) throw std::invalid_argument("invalid radius requested"); @@ -283,20 +284,20 @@ class atom_type_traits /// /// \param charge The charge of the ion /// \return The radius of the ion - float crystal_ionic_radius(int charge) const; + [[nodiscard]] float crystal_ionic_radius(int charge) const; /// \brief Return the radius for a charged version of this atom in a non-solid environment /// /// \param charge The charge of the ion /// \return The radius of the ion - float effective_ionic_radius(int charge) const; + [[nodiscard]] float effective_ionic_radius(int charge) const; /// \brief Return the radius for a charged version of this atom, returns the effective radius by default /// /// \param charge The charge of the ion /// \param type The requested ion radius type /// \return The radius of the ion - float ionic_radius(int charge, ionic_radius_type type = ionic_radius_type::effective) const + [[nodiscard]] float ionic_radius(int charge, ionic_radius_type type = ionic_radius_type::effective) const { return type == ionic_radius_type::effective ? effective_ionic_radius(charge) : crystal_ionic_radius(charge); } diff --git a/include/cif++/category.hpp b/include/cif++/category.hpp index fad7de5..ae3d939 100644 --- a/include/cif++/category.hpp +++ b/include/cif++/category.hpp @@ -26,6 +26,8 @@ #pragma once +#include + #include "cif++/condition.hpp" #include "cif++/forward_decl.hpp" #include "cif++/iterator.hpp" @@ -79,13 +81,13 @@ class missing_key_error : public std::runtime_error /** * @brief Construct a new duplicate key error object */ - missing_key_error(const std::string &msg, const std::string &key) + missing_key_error(const std::string &msg, std::string key) : std::runtime_error(msg) - , m_key(key) + , m_key(std::move(key)) { } - const std::string &get_key() const noexcept { return m_key; } + [[nodiscard]] const std::string &get_key() const noexcept { return m_key; } private: std::string m_key; @@ -99,7 +101,7 @@ class multiple_results_error : public std::runtime_error /** * @brief Construct a new multiple results error object */ - multiple_results_error() + multiple_results_error() // NOLINT : std::runtime_error("query should have returned exactly one row") { } @@ -176,7 +178,7 @@ class category // -------------------------------------------------------------------- - const std::string &name() const { return m_name; } ///< Returns the name of the category + [[nodiscard]] const std::string &name() const { return m_name; } ///< Returns the name of the category /// \brief Rename category to @a new_name void name(std::string_view new_name) @@ -186,7 +188,7 @@ class category } /// \brief Return true if the category has been modified since last open/save - constexpr bool is_dirty() const + [[nodiscard]] constexpr bool is_dirty() const { return m_dirty; } @@ -198,14 +200,14 @@ class 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 + [[deprecated("use key_items instead")]] [[nodiscard]] iset key_fields() 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 key_field_indices() const; ///< Returns a set of indices for the key items. + [[nodiscard]] iset key_items() const; ///< Returns the cif::iset of key item names. Retrieved from the @ref category_validator for this category - std::set key_item_indices() const; ///< Returns a set of indices for the key items. + [[deprecated("use key_item_indices instead")]] [[nodiscard]] std::set key_field_indices() const; ///< Returns a set of indices for the key items. + + [[nodiscard]] std::set 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. @@ -218,15 +220,15 @@ class category /// @brief Return the global @ref validator for the data /// @return The @ref validator or nullptr if not assigned - const validator *get_validator() const { return m_validator; } + [[nodiscard]] const validator *get_validator() const { return m_validator; } /// @brief Return the category validator for this category /// @return The @ref category_validator or nullptr if not assigned - const category_validator *get_cat_validator() const { return m_cat_validator; } + [[nodiscard]] const category_validator *get_cat_validator() const { return m_cat_validator; } /// @brief Validate the data stored using the assigned @ref category_validator /// @return Returns true is all validations pass - bool is_valid() const; + [[nodiscard]] bool is_valid() const; /// @brief Validate links, that means, values in this category should have an /// accompanying value in parent categories. @@ -239,7 +241,7 @@ class category /// parent in those categories. /// /// @return Returns true is all validations pass - bool validate_links() const; + [[nodiscard]] bool validate_links() const; /** * @brief Strip removes items from this category that are invalid according to the assigned validator @@ -272,7 +274,7 @@ class category /// @brief Return a const reference to the first row in this category. /// @return const reference to the first row in this category. The result is undefined if /// the category is empty. - const_reference front() const + [[nodiscard]] const_reference front() const { return { const_cast(*this), const_cast(*m_head) }; } @@ -288,7 +290,7 @@ class category /// @brief Return a const reference to the last row in this category. /// @return const reference to the last row in this category. The result is undefined if /// the category is empty. - const_reference back() const + [[nodiscard]] const_reference back() const { return { const_cast(*this), const_cast(*m_tail) }; } @@ -306,43 +308,43 @@ class category } /// Return a const iterator to the first row - const_iterator begin() const + [[nodiscard]] const_iterator begin() const { return { *this, m_head }; } /// Return a const iterator pointing past the last row - const_iterator end() const + [[nodiscard]] const_iterator end() const { return { *this, nullptr }; } /// Return a const iterator to the first row - const_iterator cbegin() const + [[nodiscard]] const_iterator cbegin() const { return { *this, m_head }; } /// Return an iterator pointing past the last row - const_iterator cend() const + [[nodiscard]] const_iterator cend() const { return { *this, nullptr }; } /// Return a count of the rows in this container - std::size_t size() const + [[nodiscard]] std::size_t size() const { return std::distance(cbegin(), cend()); } /// Return the theoretical maximum number or rows that can be stored - std::size_t max_size() const + [[nodiscard]] std::size_t max_size() const { return std::numeric_limits::max(); // this is a bit optimistic, I guess } /// Return true if the category is empty - bool empty() const + [[nodiscard]] bool empty() const { return m_head == nullptr; } @@ -610,8 +612,9 @@ class category /// @param cond The condition to search for /// @param item The name of the item to return the value for /// @return The value found - template , int> = 0> + template T find1(const_iterator pos, condition &&cond, std::string_view item) const + requires(not is_optional_v) { auto h = find(pos, std::move(cond), item); @@ -629,8 +632,9 @@ class category /// @param cond The condition to search for /// @param item The name of the item to return the value for /// @return The value found, can be empty if no row matches the condition - template , int> = 0> + template T find1(const_iterator pos, condition &&cond, std::string_view item) const + requires(is_optional_v) { auto h = find(pos, std::move(cond), item); @@ -905,23 +909,23 @@ class category /// Using the relations defined in the validator, return whether the row /// in @a r has any children in other categories - bool has_children(row_handle r) const; + [[nodiscard]] bool has_children(row_handle r) const; /// Using the relations defined in the validator, return whether the row /// in @a r has any parents in other categories - bool has_parents(row_handle r) const; + [[nodiscard]] bool has_parents(row_handle r) const; /// Using the relations defined in the validator, return the row handles /// for all rows in @a childCat that are linked to row @a r - std::vector get_children(row_handle r, const category &childCat) const; + [[nodiscard]] std::vector get_children(row_handle r, const category &childCat) const; /// Using the relations defined in the validator, return the row handles /// for all rows in @a parentCat that are linked to row @a r - std::vector get_parents(row_handle r, const category &parentCat) const; + [[nodiscard]] std::vector get_parents(row_handle r, const category &parentCat) const; /// Using the relations defined in the validator, return the row handles /// for all rows in @a cat that are in any way linked to row @a r - std::vector get_linked(row_handle r, const category &cat) const; + [[nodiscard]] std::vector get_linked(row_handle r, const category &cat) const; // -------------------------------------------------------------------- @@ -1066,12 +1070,12 @@ class category // -------------------------------------------------------------------- /// \brief Return the index number for \a item_name - uint16_t get_item_ix(std::string_view item_name) const; + [[nodiscard]] uint16_t get_item_ix(std::string_view item_name) const; /// @brief Return the name for item with index @a ix /// @param ix The index number /// @return The name of the item - std::string_view get_item_name(uint16_t ix) const + [[nodiscard]] std::string_view get_item_name(uint16_t ix) const { if (ix >= m_items.size()) throw std::out_of_range("item index is out of range"); @@ -1098,16 +1102,16 @@ class category /// @brief Return whether a item with name @a name exists in this category /// @param name The name of the item /// @return True if the item exists - bool has_item(std::string_view name) const + [[nodiscard]] bool has_item(std::string_view name) const { return get_item_ix(name) < m_items.size(); } /// @brief Return the items in this category - std::vector get_items() const; + [[nodiscard]] std::vector get_items() const; /// @brief Return the number of items (colums) in this category - size_t get_item_count() const noexcept + [[nodiscard]] size_t get_item_count() const noexcept { return m_items.size(); } @@ -1128,14 +1132,14 @@ 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 get_tag_order() const + [[deprecated("use get_item_order instead")]] [[nodiscard]] std::vector get_tag_order() const { return get_item_order(); } /// This function returns effectively the list of fully qualified item /// names, that is category_name + '.' + item_name for each item - std::vector get_item_order() const; + [[nodiscard]] std::vector get_item_order() const; /// Write the contents of the category to the std::ostream @a os void write(std::ostream &os) const; @@ -1143,13 +1147,13 @@ class category /// \brief Various supported output formats enum class output_format { - cif, // Output in mmCIF format + cif, // Output in mmCIF format csv, // comma separated values tsv, // tab separated values list, // values delimited by a '|' character column, // output in columns markdown, // - table, // ascii art table + table, // ascii art table box, // table with unicode line characters }; @@ -1201,7 +1205,7 @@ class category using allocator_type = std::allocator; - constexpr allocator_type get_allocator() const + [[nodiscard]] constexpr allocator_type get_allocator() const { return {}; } @@ -1265,8 +1269,8 @@ class category // -------------------------------------------------------------------- - condition get_parents_condition(row_handle rh, const category &parentCat) const; - condition get_children_condition(row_handle rh, const category &childCat) const; + [[nodiscard]] condition get_parents_condition(row_handle rh, const category &parentCat) const; + [[nodiscard]] condition get_children_condition(row_handle rh, const category &childCat) const; // -------------------------------------------------------------------- @@ -1283,7 +1287,7 @@ class category class category_index *m_index = nullptr; row *m_head = nullptr, *m_tail = nullptr; - bool m_dirty = false; // Keep track of modifications + bool m_dirty = false; // Keep track of modifications }; } // namespace cif diff --git a/include/cif++/compound.hpp b/include/cif++/compound.hpp index bd39710..1edcd1a 100644 --- a/include/cif++/compound.hpp +++ b/include/cif++/compound.hpp @@ -116,7 +116,7 @@ struct compound_atom z; ///< The z component of the coordinates for each atom specified as orthogonal angstroms. /// Return the location of the atom as a point - point get_location() const + [[nodiscard]] point get_location() const { return { x, y, z }; } @@ -146,34 +146,34 @@ class compound public: // accessors - std::string id() const { return m_id; } ///< Return the alphanumeric code for the chemical component. - std::string name() const { return m_name; } ///< Return the name of the chemical component. - std::string type() const { return m_type; } ///< Return the type of monomer. - std::string formula() const { return m_formula; } ///< Return the chemical formula of the chemical component. - float formula_weight() const { return m_formula_weight; } ///< Return the formula mass of the chemical component in Daltons. - int formal_charge() const { return m_formal_charge; } ///< Return the formal charge on the chemical component. + [[nodiscard]] std::string id() const { return m_id; } ///< Return the alphanumeric code for the chemical component. + [[nodiscard]] std::string name() const { return m_name; } ///< Return the name of the chemical component. + [[nodiscard]] std::string type() const { return m_type; } ///< Return the type of monomer. + [[nodiscard]] std::string formula() const { return m_formula; } ///< Return the chemical formula of the chemical component. + [[nodiscard]] float formula_weight() const { return m_formula_weight; } ///< Return the formula mass of the chemical component in Daltons. + [[nodiscard]] int formal_charge() const { return m_formal_charge; } ///< Return the formal charge on the chemical component. - const std::vector &atoms() const { return m_atoms; } ///< Return the list of atoms for this compound - const std::vector &bonds() const { return m_bonds; } ///< Return the list of bonds for this compound + [[nodiscard]] const std::vector &atoms() const { return m_atoms; } ///< Return the list of atoms for this compound + [[nodiscard]] const std::vector &bonds() const { return m_bonds; } ///< Return the list of bonds for this compound - compound_atom get_atom_by_atom_id(const std::string &atom_id) const; ///< Return the atom with id @a atom_id + [[nodiscard]] compound_atom get_atom_by_atom_id(const std::string &atom_id) const; ///< Return the atom with id @a atom_id - bool atoms_bonded(const std::string &atomId_1, const std::string &atomId_2) const; ///< Return true if @a atomId_1 is bonded to @a atomId_2 - float bond_length(const std::string &atomId_1, const std::string &atomId_2) const; ///< Return the bond length between @a atomId_1 and @a atomId_2 + [[nodiscard]] bool atoms_bonded(const std::string &atomId_1, const std::string &atomId_2) const; ///< Return true if @a atomId_1 is bonded to @a atomId_2 + [[nodiscard]] float bond_length(const std::string &atomId_1, const std::string &atomId_2) const; ///< Return the bond length between @a atomId_1 and @a atomId_2 - bool is_water() const ///< Return if the compound is actually a water + [[nodiscard]] bool is_water() const ///< Return if the compound is actually a water { return m_id == "HOH" or m_id == "H2O" or m_id == "WAT"; } /** \brief Return whether this compound has a type of either 'peptide linking' or 'L-peptide linking' */ - bool is_peptide() const; + [[nodiscard]] bool is_peptide() const; /** \brief Return whether this compound has a type of either 'DNA linking' or 'RNA linking' */ - bool is_base() const; + [[nodiscard]] bool is_base() const; - char one_letter_code() const { return m_one_letter_code; }; ///< Return the one letter code to use in a canonical sequence. If unknown the value '\0' is returned - std::string parent_id() const { return m_parent_id; }; ///< Return the parent id code in case a parent is specified (e.g. MET for MSE) + [[nodiscard]] char one_letter_code() const { return m_one_letter_code; }; ///< Return the one letter code to use in a canonical sequence. If unknown the value '\0' is returned + [[nodiscard]] std::string parent_id() const { return m_parent_id; }; ///< Return the parent id code in case a parent is specified (e.g. MET for MSE) private: friend class compound_factory_impl; diff --git a/include/cif++/utilities.hpp b/include/cif++/utilities.hpp index 60755b9..72336ae 100644 --- a/include/cif++/utilities.hpp +++ b/include/cif++/utilities.hpp @@ -88,7 +88,7 @@ namespace colour /// @brief The defined colours enum colour_type { - black = 0, + black, red, green, yellow, @@ -96,7 +96,8 @@ namespace colour magenta, cyan, white, - none = 9 + _unused, + none }; /// @brief The defined styles @@ -127,6 +128,7 @@ namespace colour { } + coloured_string_t(coloured_string_t &) = delete; coloured_string_t &operator=(coloured_string_t &) = delete; /** diff --git a/src/category.cpp b/src/category.cpp index 57afce3..b1ba0ea 100644 --- a/src/category.cpp +++ b/src/category.cpp @@ -31,6 +31,7 @@ #include "cif++/utilities.hpp" #include "cif++/validate.hpp" +#include #include #include #include @@ -68,7 +69,8 @@ class row_comparator using namespace std::placeholders; - m_comparator.emplace_back(ix, std::bind(&type_validator::compare, tv, _1, _2)); + m_comparator.emplace_back(ix, [tv](auto &&a1, auto &&a2) + { return tv->compare(std::forward(a1), std::forward(a2)); }); } } @@ -145,8 +147,8 @@ class category_index delete m_root; } - row *find(const category &cat, row *k) const; - row *find_by_value(const category &cat, const category::key_type &k) const; + [[nodiscard]] row *find(const category &cat, row *k) const; + [[nodiscard]] row *find_by_value(const category &cat, const category::key_type &k) const; void insert(category &cat, row *r); void erase(category &cat, row *r); @@ -169,7 +171,7 @@ class category_index return result; } - std::size_t size() const; + [[nodiscard]] std::size_t size() const; // bool isValid() const; private: @@ -177,9 +179,6 @@ class category_index { entry(row *r) : m_row(r) - , m_left(nullptr) - , m_right(nullptr) - , m_red(true) { } @@ -190,9 +189,9 @@ class category_index } row *m_row; - entry *m_left; - entry *m_right; - bool m_red; + entry *m_left = nullptr; + entry *m_right = nullptr; + bool m_red = true; }; entry *insert(category &cat, entry *h, row *v); @@ -328,12 +327,11 @@ class category_index } row_comparator m_row_comparator; - entry *m_root; + entry *m_root = nullptr; }; category_index::category_index(category &cat) : m_row_comparator(cat) - , m_root(nullptr) { for (auto r : cat) insert(cat, r.get_row()); @@ -611,7 +609,7 @@ void category::remove_item(std::string_view item_name) void category::drop_empty_items() { std::vector is_empty(m_items.size(), true); - + for (auto &row : *this) { for (size_t ix = 0; ix < m_items.size(); ++ix) @@ -634,13 +632,13 @@ void category::drop_empty_items() void category::rename_item(std::string_view from_name, std::string_view to_name) { - for (std::size_t ix = 0; ix < m_items.size(); ++ix) + for (auto &item : m_items) { - if (not iequals(from_name, m_items[ix].m_name)) + if (not iequals(from_name, item.m_name)) continue; - m_items[ix].m_name = to_name; - m_items[ix].m_validator = m_cat_validator ? m_cat_validator->get_validator_for_item(to_name) : nullptr; + item.m_name = to_name; + item.m_validator = m_cat_validator ? m_cat_validator->get_validator_for_item(to_name) : nullptr; break; } @@ -988,9 +986,9 @@ condition category::get_parents_condition(row_handle rh, const category &parentC condition result; auto links = m_validator->get_links_for_child(m_name); - links.erase(remove_if(links.begin(), links.end(), [n = parentCat.m_name](auto &l) - { return l->m_parent_category != n; }), - links.end()); + auto e = std::ranges::remove_if(links, [n = parentCat.m_name](auto &l) + { return l->m_parent_category != n; }); + links.erase(e.begin(), e.end()); if (not links.empty()) { @@ -1030,9 +1028,9 @@ condition category::get_children_condition(row_handle rh, const category &childC mandatoryChildItems = childCatValidator->m_mandatory_items; auto links = m_validator->get_links_for_parent(m_name); - links.erase(remove_if(links.begin(), links.end(), [n = childCat.m_name](auto &l) - { return l->m_child_category != n; }), - links.end()); + auto e = std::ranges::remove_if(links, [n = childCat.m_name](auto &l) + { return l->m_child_category != n; }); + links.erase(e.begin(), e.end()); if (not links.empty()) { @@ -1105,7 +1103,7 @@ std::vector category::get_children(row_handle r, const category &chi for (auto child : childCat.find(get_children_condition(r, childCat))) { - if (std::find(result.begin(), result.end(), child) == result.end()) + if (std::ranges::find(result, child) == result.end()) result.push_back(child); } @@ -1121,7 +1119,7 @@ std::vector category::get_parents(row_handle r, const category &pare for (auto parent : parentCat.find(get_parents_condition(r, parentCat))) { - if (std::find(result.begin(), result.end(), parent) == result.end()) + if (std::ranges::find(result, parent) == result.end()) result.push_back(parent); } @@ -1327,7 +1325,7 @@ std::string category::get_unique_id(std::function generator) for (;;) { - if (m_index->find_by_value(*this, { { id_name, result } }) == nullptr) + if (m_index->find_by_value(*this, { { .name = id_name, .value = result } }) == nullptr) break; result = generator(static_cast(m_last_unique_num++)); } @@ -1356,7 +1354,7 @@ std::string category::get_unique_value(std::string_view item_name) if (iv and iv->m_type and iv->m_type->m_primitive_type == DDL_PrimitiveType::Numb) { - uint64_t v = find_max(item_name); + auto v = find_max(item_name); result = std::to_string(v + 1); } } @@ -1414,7 +1412,7 @@ void category::update_value(const std::vector &rows, std::string_vie 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()) + if (std::ranges::find(linked->m_parent_keys, item_name) == linked->m_parent_keys.end()) continue; condition cond; @@ -1560,7 +1558,7 @@ void category::update_value(row *row, uint16_t item, std::string_view value, boo for (auto &&[childCat, linked] : m_child_links) { - if (std::find(linked->m_parent_keys.begin(), linked->m_parent_keys.end(), iv->m_item_name) == linked->m_parent_keys.end()) + if (std::ranges::find(linked->m_parent_keys, iv->m_item_name) == linked->m_parent_keys.end()) continue; condition cond; @@ -1770,7 +1768,7 @@ category::iterator category::insert_impl(const_iterator pos, row *n) m_dirty = true; - return iterator(*this, n); + return { *this, n }; } catch (const std::exception &e) { @@ -1814,11 +1812,8 @@ void category::sort(std::function f) for (auto itemRow = m_head; itemRow != nullptr; itemRow = itemRow->m_next) rows.emplace_back(*this, *itemRow); - std::stable_sort(rows.begin(), rows.end(), - [&f](row_handle ia, row_handle ib) - { - return f(ia, ib) < 0; - }); + std::ranges::stable_sort(rows, [&f](row_handle ia, row_handle ib) + { return f(ia, ib) < 0; }); m_head = rows.front().get_row(); m_tail = rows.back().get_row(); @@ -1968,7 +1963,7 @@ void category::write(std::ostream &os, output_format fmt, const std::vectorget_validator_for_category(a.name()); - typedef std::function compType; + using compType = std::function; std::vector> item_names; std::vector keys; std::vector keyIx; @@ -2630,8 +2625,8 @@ bool category::operator==(const category &rhs) const { for (auto &item_name : a.get_items()) { - item_names.push_back(std::make_tuple(item_name, [](std::string_view va, std::string_view vb) - { return va.compare(vb); })); + item_names.emplace_back(item_name, [](std::string_view va, std::string_view vb) + { return va.compare(vb); }); keyIx.push_back(keys.size()); keys.push_back(item_name); } @@ -2648,13 +2643,14 @@ bool category::operator==(const category &rhs) const auto tv = iv->m_type; if (tv == nullptr) throw std::runtime_error("missing type validator"); - item_names.push_back(std::make_tuple(item_name, std::bind(&cif::type_validator::compare, tv, std::placeholders::_1, std::placeholders::_2))); + item_names.emplace_back(item_name, [tv](auto &&a1, auto &&a2) + { return tv->compare(std::forward(a1), std::forward(a2)); }); auto pred = [item_name](const std::string &s) -> bool { return cif::iequals(item_name, s) == 0; }; - if (find_if(keys.begin(), keys.end(), pred) == keys.end()) + if (std::ranges::find_if(keys, pred) == keys.end()) keyIx.push_back(item_names.size() - 1); } } diff --git a/src/cql.cpp b/src/cql.cpp index 20b9388..e29bfa3 100644 --- a/src/cql.cpp +++ b/src/cql.cpp @@ -35,14 +35,15 @@ #include "cif++/text.hpp" #include "cif++/validate.hpp" -#include - +#include #include #include #include #include #include +#include #include +#include #include #include #include @@ -77,7 +78,7 @@ field_ref row_ref::operator[](std::string_view name) const // -------------------------------------------------------------------- result::result(category &&cat, const std::string &query) - : m_impl(new result_impl{ std::forward(cat), query }) + : m_impl(new result_impl{ .m_cat = std::forward(cat), .m_query = query }) { } @@ -208,16 +209,16 @@ sqlite3_module connection_impl::s_module{ /* xRowid */ Rowid, /* xUpdate */ Update, /* xBegin */ Begin, - /* xSync */ 0, + /* xSync */ nullptr, /* xCommit */ Commit, /* xRollback */ Rollback, - /* xFindFunction */ 0, + /* xFindFunction */ nullptr, /* xRename */ Rename, - /* xSavepoint */ 0, - /* xRelease */ 0, - /* xRollbackTo */ 0, - /* xShadowName */ 0, - /* xIntegrity */ 0 + /* xSavepoint */ nullptr, + /* xRelease */ nullptr, + /* xRollbackTo */ nullptr, + /* xShadowName */ nullptr, + /* xIntegrity */ nullptr }; /* @@ -236,7 +237,7 @@ sqlite3_module connection_impl::s_module{ int connection_impl::Connect(sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **ppVtab, char **pzErr) { - connection_impl *impl = reinterpret_cast(pAux); + auto *impl = reinterpret_cast(pAux); try { return impl->Connect(db, argc, argv, ppVtab, pzErr); @@ -280,7 +281,7 @@ int connection_impl::Connect(sqlite3 *db, int argc, const char *const *argv, sql for (auto iv : cv->m_item_validators) { - if (std::find(items.begin(), items.end(), iv.m_item_name) == items.end()) + if (std::ranges::find(items, iv.m_item_name) == items.end()) items.emplace_back(iv.m_item_name); } @@ -334,10 +335,11 @@ int connection_impl::Connect(sqlite3 *db, int argc, const char *const *argv, sql */ int connection_impl::Destroy(sqlite3_vtab *pVtab) { - virtual_table *p = reinterpret_cast(pVtab); + auto *p = reinterpret_cast(pVtab); auto &conn = p->m_connection_impl; - conn.m_vtabs.erase(std::remove(conn.m_vtabs.begin(), conn.m_vtabs.end(), p), conn.m_vtabs.end()); + auto e = std::ranges::remove(conn.m_vtabs, p); + conn.m_vtabs.erase(e.begin(), e.end()); auto &db = p->m_db; db.remove(p->m_cat); @@ -351,10 +353,11 @@ int connection_impl::Destroy(sqlite3_vtab *pVtab) */ int connection_impl::Disconnect(sqlite3_vtab *pVtab) { - virtual_table *p = reinterpret_cast(pVtab); + auto *p = reinterpret_cast(pVtab); auto &conn = p->m_connection_impl; - conn.m_vtabs.erase(std::remove(conn.m_vtabs.begin(), conn.m_vtabs.end(), p), conn.m_vtabs.end()); + auto e = std::ranges::remove(conn.m_vtabs, p); + conn.m_vtabs.erase(e.begin(), e.end()); delete p; @@ -524,7 +527,7 @@ int connection_impl::Filter(sqlite3_vtab_cursor *pVtabCursor, int idxNum, const else { double value; - const auto &[ptr, ec] = std::from_chars(m[3].str().data(), m[3].str().data() + m[3].str().length(), value); + const auto &[ptr, ec] = cif::from_chars(m[3].str().data(), m[3].str().data() + m[3].str().length(), value); if (ec != std::errc{}) throw std::system_error(std::make_error_code(ec)); @@ -569,7 +572,7 @@ int connection_impl::Filter(sqlite3_vtab_cursor *pVtabCursor, int idxNum, const */ int connection_impl::BestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo) { - virtual_table *p = reinterpret_cast(pVtab); + auto *p = reinterpret_cast(pVtab); try { @@ -615,7 +618,7 @@ int connection_impl::BestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo break; default: { - std::string s = (const char *)sqlite3_value_text(val); + std::string s = reinterpret_cast(sqlite3_value_text(val)); if (s.find("\n") == std::string::npos) os << std::quoted(s) << "\n"; else @@ -713,7 +716,7 @@ int connection_impl::BestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite_int64 *pRowid) { - virtual_table *p = reinterpret_cast(pVTab); + auto *p = reinterpret_cast(pVTab); int rc = SQLITE_ERROR; @@ -789,7 +792,7 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, data.emplace_back(p->m_items[i - 2], "?"); break; default: - data.emplace_back(p->m_items[i - 2], (const char *)sqlite3_value_text(argv[i])); + data.emplace_back(p->m_items[i - 2], reinterpret_cast(sqlite3_value_text(argv[i]))); break; } } @@ -818,7 +821,7 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, data.emplace_back(p->m_items[i - 2], "?"); break; default: - data.emplace_back(p->m_items[i - 2], (const char *)sqlite3_value_text(argv[i])); + data.emplace_back(p->m_items[i - 2], reinterpret_cast(sqlite3_value_text(argv[i]))); break; } } @@ -833,12 +836,12 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, if (childCat == nullptr) continue; - std::vector> ixs; + std::vector> ixs; for (auto &ri : data) { - auto i = std::find(link->m_parent_keys.begin(), link->m_parent_keys.end(), ri.name()); + auto i = std::ranges::find(link->m_parent_keys, ri.name()); if (i == link->m_parent_keys.end()) - continue; // no update needed + continue; // no update needed ixs.emplace_back(i - link->m_parent_keys.begin(), ri.value()); } @@ -847,14 +850,14 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, std::ostringstream sql; sql << "UPDATE " << link->m_child_category; - + for (bool first = true; auto [i, txt] : ixs) { if (not std::exchange(first, false)) sql << ","; sql << " SET " << link->m_child_keys[i] << " = ?" << (i + 1); } - + sql << " WHERE "; for (bool first = true; auto [i, txt] : ixs) { @@ -870,7 +873,7 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, for (auto [i, txt] : ixs) { // set - if (rc == SQLITE_OK) + if (rc == SQLITE_OK) rc = sqlite3_bind_text(sub_stmt, i + 1, txt.data(), txt.length(), nullptr); // where @@ -889,8 +892,6 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, } } - - rh.assign(data); *pRowid = addr; rc = SQLITE_OK; @@ -907,21 +908,21 @@ int connection_impl::Update(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, int connection_impl::Rename(sqlite3_vtab *pVtab, const char *zNew) { - virtual_table *p = reinterpret_cast(pVtab); + auto *p = reinterpret_cast(pVtab); p->m_cat.name(zNew); return SQLITE_OK; } int connection_impl::Begin(sqlite3_vtab *pVTab) { - virtual_table *p = reinterpret_cast(pVTab); + auto *p = reinterpret_cast(pVTab); p->m_rollback_buffer.push(p->m_cat); return SQLITE_OK; } int connection_impl::Commit(sqlite3_vtab *pVTab) { - virtual_table *p = reinterpret_cast(pVTab); + auto *p = reinterpret_cast(pVTab); if (not p->m_rollback_buffer.empty()) p->m_rollback_buffer.pop(); return SQLITE_OK; @@ -929,7 +930,7 @@ int connection_impl::Commit(sqlite3_vtab *pVTab) int connection_impl::Rollback(sqlite3_vtab *pVTab) { - virtual_table *p = reinterpret_cast(pVTab); + auto *p = reinterpret_cast(pVTab); if (not p->m_rollback_buffer.empty()) { std::swap(p->m_cat, p->m_rollback_buffer.top()); @@ -1078,7 +1079,7 @@ result connection::exec(std::string query, std::string &tail) sqlite3_finalize(stmt); - return result(std::move(cat), sql); + return { std::move(cat), sql }; } catch (const std::exception &ex) { diff --git a/src/text.cpp b/src/text.cpp index 191b90c..945fbbe 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -268,7 +268,7 @@ std::string cif_id_for_number(int number) number = (number - r) / 26 - 1; } while (number >= 0); - std::reverse(result.begin(), result.end()); + std::ranges::reverse(result); assert(not result.empty()); @@ -494,7 +494,7 @@ std::vector wrapLine(const std::string &text, std::size_t width) j = i; } - reverse(result.begin(), result.end()); + std::ranges::reverse(result); return result; } @@ -506,7 +506,7 @@ std::vector word_wrap(const std::string &text, std::size_t width) { if (p.empty()) { - result.push_back(""); + result.emplace_back(""); continue; }