Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
a855f880
Unverified
Commit
a855f880
authored
Aug 10, 2022
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Getting rid of boost/algorithm/string
parent
cfa2acd6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
612 additions
and
315 deletions
+612
-315
CMakeLists.txt
+40
-52
Config.cmake.in
+2
-4
include/cif++/CifUtils.hpp
+118
-1
include/cif++/Secondary.hpp
+2
-0
include/cif++/Structure.hpp
+0
-2
include/cif++/v2/category.hpp
+31
-0
include/cif++/v2/item.hpp
+3
-2
include/cif++/v2/validate.hpp
+0
-6
src/Cif++.cpp
+52
-51
src/Cif2PDB.cpp
+0
-0
src/CifParser.cpp
+3
-7
src/CifUtils.cpp
+109
-24
src/CifValidator.cpp
+3
-11
src/Compound.cpp
+5
-8
src/PDB2Cif.cpp
+0
-0
src/PDB2CifRemark3.cpp
+14
-20
src/Secondary.cpp
+1
-5
src/Structure.cpp
+18
-77
src/TlsParser.cpp
+2
-6
src/parser.cpp
+3
-3
src/v2/category.cpp
+201
-30
src/v2/validate.cpp
+5
-6
test/unit-v2-test.cpp
+0
-0
No files found.
CMakeLists.txt
View file @
a855f880
...
...
@@ -6,10 +6,10 @@
# 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
# 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 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
...
...
@@ -46,7 +46,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
if
(
"
${
CMAKE_CXX_COMPILER_ID
}
"
STREQUAL
"GNU"
)
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
()
# Building shared libraries?
...
...
@@ -57,6 +57,7 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# Optionally build a version to be installed inside CCP4
option
(
BUILD_FOR_CCP4
"Build a version to be installed in CCP4"
OFF
)
if
(
BUILD_FOR_CCP4
)
if
(
"$ENV{CCP4}"
STREQUAL
""
OR NOT EXISTS $ENV{CCP4}
)
message
(
FATAL_ERROR
"A CCP4 built was requested but CCP4 was not sourced"
)
...
...
@@ -79,6 +80,7 @@ if(EXISTS "$ENV{CCP4}")
set
(
CCP4 $ENV{CCP4}
)
set
(
CLIBD
${
CCP4
}
/lib/data
)
endif
()
if
(
CCP4 AND NOT CLIBD
)
set
(
CLIBD
${
CCP4
}
/lib/data
)
endif
()
...
...
@@ -97,13 +99,12 @@ else()
endif
()
# set(CMAKE_DEBUG_POSTFIX d)
if
(
MSVC
)
# make msvc standards compliant...
add_compile_options
(
/permissive-
)
# make msvc standards compliant...
add_compile_options
(
/permissive-
)
macro
(
get_WIN32_WINNT version
)
if
(
WIN32 AND CMAKE_SYSTEM_VERSION
)
if
(
WIN32 AND CMAKE_SYSTEM_VERSION
)
set
(
ver
${
CMAKE_SYSTEM_VERSION
}
)
string
(
REPLACE
"."
""
ver
${
ver
}
)
string
(
REGEX REPLACE
"([0-9])"
"0
\\
1"
ver
${
ver
}
)
...
...
@@ -129,7 +130,6 @@ if(UNIX AND NOT APPLE AND NOT BUILD_FOR_CCP4 AND CMAKE_INSTALL_PREFIX_INITIALIZE
endif
()
# Optionally use mrc to create resources
if
(
WIN32 AND BUILD_SHARED_LIBS
)
message
(
"Not using resources when building shared libraries for Windows"
)
else
()
...
...
@@ -150,17 +150,12 @@ else()
endif
()
# Libraries
set
(
CMAKE_THREAD_PREFER_PTHREAD
)
set
(
THREADS_PREFER_PTHREAD_FLAG
)
find_package
(
Threads
)
find_package
(
Boost 1.70.0 REQUIRED COMPONENTS system iostreams regex program_options
)
if
(
NOT MSVC AND Boost_USE_STATIC_LIBS
)
find_package
(
ZLIB REQUIRED
)
list
(
APPEND CIFPP_REQUIRED_LIBRARIES ZLIB::ZLIB
)
endif
()
find_package
(
Boost 1.70.0 REQUIRED COMPONENTS system regex program_options
)
find_package
(
gzstream REQUIRED
)
include
(
FindFilesystem
)
list
(
APPEND CIFPP_REQUIRED_LIBRARIES
${
STDCPPFS_LIBRARY
}
)
...
...
@@ -175,21 +170,21 @@ write_version_header("LibCIFPP")
# SymOp data table
if
(
CIFPP_RECREATE_SYMOP_DATA
)
# The tool to create the table
add_executable
(
symop-map-generator
"
${
CMAKE_SOURCE_DIR
}
/tools/symop-map-generator.cpp"
)
target_link_libraries
(
symop-map-generator Threads::Threads
${
Boost_LIBRARIES
}
${
CIFPP_REQUIRED_LIBRARIES
}
)
if
(
Boost_INCLUDE_DIR
)
target_include_directories
(
symop-map-generator PUBLIC
${
Boost_INCLUDE_DIR
}
)
endif
()
set
(
$ENV{CLIBD}
${
CLIBD
}
)
add_custom_command
(
OUTPUT
${
CMAKE_SOURCE_DIR
}
/src/SymOpTable_data.hpp
COMMAND $<TARGET_FILE:symop-map-generator>
${
CLIBD
}
/syminfo.lib
${
CMAKE_SOURCE_DIR
}
/src/SymOpTable_data.hpp
)
)
add_custom_target
(
OUTPUT
${
CMAKE_SOURCE_DIR
}
/src/SymOpTable_data.hpp
DEPENDS symop-map-generator
"$ENV{CLIBD}/syminfo.lib"
...
...
@@ -197,8 +192,7 @@ if(CIFPP_RECREATE_SYMOP_DATA)
endif
()
# Sources
set
(
project_sources
set
(
project_sources
${
PROJECT_SOURCE_DIR
}
/src/AtomType.cpp
${
PROJECT_SOURCE_DIR
}
/src/BondMap.cpp
${
PROJECT_SOURCE_DIR
}
/src/Cif++.cpp
...
...
@@ -224,7 +218,7 @@ set(project_sources
${
PROJECT_SOURCE_DIR
}
/src/v2/validate.cpp
)
set
(
project_headers
set
(
project_headers
${
PROJECT_SOURCE_DIR
}
/include/cif++/AtomType.hpp
${
PROJECT_SOURCE_DIR
}
/include/cif++/BondMap.hpp
${
PROJECT_SOURCE_DIR
}
/include/cif++/Cif++.hpp
...
...
@@ -249,7 +243,7 @@ target_include_directories(cifpp
PUBLIC
"$<BUILD_INTERFACE:
${
PROJECT_SOURCE_DIR
}
/include>"
"$<INSTALL_INTERFACE:
${
CMAKE_INSTALL_INCLUDEDIR
}
>"
${
Boost_INCLUDE_DIR
}
${
Boost_INCLUDE_DIR
}
${
gzstream_INCLUDE_DIR
}
)
target_include_directories
(
cifpp
...
...
@@ -257,21 +251,21 @@ target_include_directories(cifpp
${
CMAKE_BINARY_DIR
}
)
target_link_libraries
(
cifpp PUBLIC Threads::Threads Boost::regex Boost::iostreams
${
CIFPP_REQUIRED_LIBRARIES
}
)
# target_link_libraries(cifpp PRIVATE)
target_link_libraries
(
cifpp PUBLIC Threads::Threads Boost::regex gzstream::gzstream
${
CIFPP_REQUIRED_LIBRARIES
}
)
if
(
CMAKE_CXX_COMPILER_ID STREQUAL
"AppleClang"
)
target_link_options
(
cifpp PRIVATE -undefined dynamic_lookup
)
endif
(
CMAKE_CXX_COMPILER_ID STREQUAL
"AppleClang"
)
# target_link_libraries(cifpp PRIVATE)
if
(
CMAKE_CXX_COMPILER_ID STREQUAL
"AppleClang"
)
target_link_options
(
cifpp PRIVATE -undefined dynamic_lookup
)
endif
(
CMAKE_CXX_COMPILER_ID STREQUAL
"AppleClang"
)
option
(
CIFPP_DOWNLOAD_CCD
"Download the CCD file components.cif during installation"
OFF
)
if
(
CIFPP_DOWNLOAD_CCD
)
# download the components.cif file from CCD
set
(
COMPONENTS_CIF
${
PROJECT_SOURCE_DIR
}
/data/components.cif
)
if
(
NOT EXISTS
${
COMPONENTS_CIF
}
)
if
(
NOT EXISTS
${
PROJECT_SOURCE_DIR
}
/data
)
if
(
NOT EXISTS
${
COMPONENTS_CIF
}
)
if
(
NOT EXISTS
${
PROJECT_SOURCE_DIR
}
/data
)
file
(
MAKE_DIRECTORY
${
PROJECT_SOURCE_DIR
}
/data/
)
endif
()
...
...
@@ -301,8 +295,8 @@ endif()
generate_export_header
(
cifpp
EXPORT_FILE_NAME cif++/Cif++Export.hpp
)
set
(
INCLUDE_INSTALL_DIR
${
CMAKE_INSTALL_INCLUDEDIR
}
)
set
(
LIBRARY_INSTALL_DIR
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
INCLUDE_INSTALL_DIR
${
CMAKE_INSTALL_INCLUDEDIR
}
)
set
(
LIBRARY_INSTALL_DIR
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
SHARE_INSTALL_DIR
${
CMAKE_INSTALL_DATADIR
}
/libcifpp
)
set
(
CIFPP_DATA_DIR
"
${
CMAKE_INSTALL_PREFIX
}
/
${
SHARE_INSTALL_DIR
}
"
CACHE STRING
"The directory containing the provided data files"
)
...
...
@@ -310,7 +304,6 @@ set(CIFPP_DATA_DIR "${CMAKE_INSTALL_PREFIX}/${SHARE_INSTALL_DIR}" CACHE STRING "
target_compile_definitions
(
cifpp PUBLIC DATA_DIR=
"
${
CIFPP_DATA_DIR
}
"
)
# Install rules
install
(
TARGETS cifpp
EXPORT cifppTargets
ARCHIVE DESTINATION
${
CMAKE_INSTALL_LIBDIR
}
...
...
@@ -357,8 +350,8 @@ configure_package_config_file(Config.cmake.in
)
install
(
FILES
"
${
CMAKE_CURRENT_BINARY_DIR
}
/cifpp/cifppConfig.cmake"
"
${
CMAKE_CURRENT_BINARY_DIR
}
/cifpp/cifppConfigVersion.cmake"
"
${
CMAKE_CURRENT_BINARY_DIR
}
/cifpp/cifppConfig.cmake"
"
${
CMAKE_CURRENT_BINARY_DIR
}
/cifpp/cifppConfigVersion.cmake"
DESTINATION
${
CMAKE_INSTALL_LIBDIR
}
/cmake/cifpp
COMPONENT Devel
)
...
...
@@ -370,21 +363,20 @@ set_target_properties(cifpp PROPERTIES
INTERFACE_cifpp_MAJOR_VERSION
${
cifpp_MAJOR_VERSION
}
)
set_property
(
TARGET cifpp APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION
COMPATIBLE_INTERFACE_STRING cifpp_MAJOR_VERSION
)
write_basic_package_version_file
(
"
${
CMAKE_CURRENT_BINARY_DIR
}
/cifpp/cifppConfigVersion.cmake"
VERSION
${
PROJECT_VERSION
}
COMPATIBILITY AnyNewerVersion
"
${
CMAKE_CURRENT_BINARY_DIR
}
/cifpp/cifppConfigVersion.cmake"
VERSION
${
PROJECT_VERSION
}
COMPATIBILITY AnyNewerVersion
)
# pkgconfig support
set
(
prefix
${
CMAKE_INSTALL_PREFIX
}
)
set
(
prefix
${
CMAKE_INSTALL_PREFIX
}
)
set
(
exec_prefix
${
CMAKE_INSTALL_PREFIX
}
)
set
(
libdir
${
CMAKE_INSTALL_PREFIX
}
/
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
includedir
${
CMAKE_INSTALL_PREFIX
}
/
${
CMAKE_INSTALL_INCLUDEDIR
}
)
set
(
libdir
${
CMAKE_INSTALL_PREFIX
}
/
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
includedir
${
CMAKE_INSTALL_PREFIX
}
/
${
CMAKE_INSTALL_INCLUDEDIR
}
)
configure_file
(
${
CMAKE_CURRENT_SOURCE_DIR
}
/libcifpp.pc.in
${
CMAKE_CURRENT_BINARY_DIR
}
/libcifpp.pc.in @ONLY
)
...
...
@@ -393,12 +385,11 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc
install
(
FILES
${
CMAKE_CURRENT_BINARY_DIR
}
/libcifpp.pc DESTINATION
${
CMAKE_INSTALL_LIBDIR
}
/pkgconfig
)
# Unit tests
option
(
CIFPP_BUILD_TESTS
"Build test exectuables"
OFF
)
if
(
CIFPP_BUILD_TESTS
)
list
(
APPEND CIFPP_tests
# pdb2cif
rename-compound
structure
...
...
@@ -414,10 +405,10 @@ if(CIFPP_BUILD_TESTS)
target_include_directories
(
${
CIFPP_TEST
}
PRIVATE
${
CMAKE_CURRENT_SOURCE_DIR
}
/include
${
CMAKE_CURRENT_BINARY_DIR
}
# for config.h
${
CMAKE_CURRENT_BINARY_DIR
}
# for config.h
)
target_link_libraries
(
${
CIFPP_TEST
}
PRIVATE Threads::Threads cifpp
)
target_link_libraries
(
${
CIFPP_TEST
}
PRIVATE Threads::Threads cifpp
)
if
(
CIFPP_USE_RSRC
)
mrc_target_resources
(
${
CIFPP_TEST
}
${
CMAKE_SOURCE_DIR
}
/rsrc/mmcif_pdbx_v50.dic
)
...
...
@@ -436,14 +427,12 @@ if(CIFPP_BUILD_TESTS)
add_test
(
NAME
${
CIFPP_TEST
}
COMMAND $<TARGET_FILE:
${
CIFPP_TEST
}
> --
${
CMAKE_SOURCE_DIR
}
/test
)
endforeach
()
endif
()
message
(
"Will install in
${
CMAKE_INSTALL_PREFIX
}
"
)
# Optionally install the update scripts for CCD and dictionary files
if
(
CIFPP_INSTALL_UPDATE_SCRIPT
)
set
(
CIFPP_CRON_DIR
"$ENV{DESTDIR}/etc/cron.weekly"
)
...
...
@@ -468,4 +457,3 @@ if(CIFPP_INSTALL_UPDATE_SCRIPT)
target_compile_definitions
(
cifpp PUBLIC CACHE_DIR=
"
${
CIFPP_CACHE_DIR
}
"
)
endif
()
Config.cmake.in
View file @
a855f880
...
...
@@ -2,10 +2,8 @@
include(CMakeFindDependencyMacro)
find_dependency(Threads)
find_dependency(Boost 1.70.0 REQUIRED COMPONENTS system iostreams regex)
if(NOT WIN32)
find_dependency(ZLIB)
endif()
find_dependency(Boost 1.70.0 REQUIRED COMPONENTS system regex)
find_dependency(gzstream)
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
...
...
include/cif++/CifUtils.hpp
View file @
a855f880
...
...
@@ -72,7 +72,124 @@ bool iequals(const char *a, const char *b);
int
icompare
(
const
char
*
a
,
const
char
*
b
);
void
toLower
(
std
::
string
&
s
);
std
::
string
toLowerCopy
(
const
std
::
string
&
s
);
std
::
string
toLowerCopy
(
std
::
string_view
s
);
void
toUpper
(
std
::
string
&
s
);
// std::string toUpperCopy(const std::string &s);
template
<
typename
IterType
>
std
::
string
join
(
IterType
b
,
IterType
e
,
std
::
string_view
sep
)
{
std
::
ostringstream
s
;
if
(
b
!=
e
)
{
auto
ai
=
b
;
auto
ni
=
std
::
next
(
ai
);
for
(;;)
{
s
<<
*
ai
;
ai
=
ni
;
ni
=
std
::
next
(
ai
);
if
(
ni
==
e
)
break
;
s
<<
sep
;
}
}
return
s
.
str
();
}
template
<
typename
V
>
std
::
string
join
(
const
V
&
arr
,
std
::
string_view
sep
)
{
return
join
(
arr
.
begin
(),
arr
.
end
(),
sep
);
}
template
<
typename
StringType
=
std
::
string_view
>
std
::
vector
<
StringType
>
split
(
std
::
string_view
s
,
std
::
string_view
separators
,
bool
suppress_empty
=
false
)
{
std
::
vector
<
StringType
>
result
;
auto
b
=
s
.
begin
();
auto
e
=
b
;
while
(
e
!=
s
.
end
())
{
if
(
separators
.
find
(
*
e
)
!=
std
::
string_view
::
npos
)
{
if
(
e
>
b
or
not
suppress_empty
)
result
.
emplace_back
(
b
,
e
-
b
);
b
=
e
=
e
+
1
;
continue
;
}
++
e
;
}
if
(
e
>
b
or
not
suppress_empty
)
result
.
emplace_back
(
b
,
e
-
b
);
return
result
;
}
void
replace_all
(
std
::
string
&
s
,
std
::
string_view
what
,
std
::
string_view
with
=
{});
#if defined(__cpp_lib_starts_ends_with)
inline
bool
starts_with
(
std
::
string
s
,
std
::
string_view
with
)
{
return
s
.
starts_with
(
with
);
}
inline
bool
ends_with
(
std
::
string_view
s
,
std
::
string_view
with
)
{
return
s
.
ends_with
(
with
);
}
#else
inline
bool
starts_with
(
std
::
string
s
,
std
::
string_view
with
)
{
return
s
.
compare
(
0
,
with
.
length
(),
with
)
==
0
;
}
inline
bool
ends_with
(
std
::
string_view
s
,
std
::
string_view
with
)
{
return
s
.
length
()
>=
with
.
length
()
and
s
.
compare
(
s
.
length
()
-
with
.
length
(),
with
.
length
(),
with
)
==
0
;
}
#endif
#if defined(__cpp_lib_string_contains)
inline
bool
contains
(
std
::
string_view
s
,
std
::
string_view
q
)
{
return
s
.
contains
(
q
);
}
#else
inline
bool
contains
(
std
::
string_view
s
,
std
::
string_view
q
)
{
return
s
.
find
(
q
)
!=
std
::
string_view
::
npos
;
}
#endif
bool
icontains
(
std
::
string_view
s
,
std
::
string_view
q
);
void
trim_left
(
std
::
string
&
s
);
void
trim_right
(
std
::
string
&
s
);
void
trim
(
std
::
string
&
s
);
std
::
string
trim_left_copy
(
std
::
string_view
s
);
std
::
string
trim_right_copy
(
std
::
string_view
s
);
std
::
string
trim_copy
(
std
::
string_view
s
);
// To make life easier, we also define iless and iset using iequals
...
...
include/cif++/Secondary.hpp
View file @
a855f880
...
...
@@ -28,6 +28,8 @@
#pragma once
#include <vector>
namespace
mmcif
{
...
...
include/cif++/Structure.hpp
View file @
a855f880
...
...
@@ -599,8 +599,6 @@ class File : public cif::File
void
load
(
const
std
::
filesystem
::
path
&
p
)
override
;
void
save
(
const
std
::
filesystem
::
path
&
p
)
override
;
void
load
(
std
::
istream
&
is
)
override
;
using
cif
::
File
::
load
;
using
cif
::
File
::
save
;
...
...
include/cif++/v2/category.hpp
View file @
a855f880
...
...
@@ -394,6 +394,34 @@ class category
}
// --------------------------------------------------------------------
/// \brief generate a new, unique ID. Pass it an ID generating function
/// based on a sequence number. This function will be called until the
/// result is unique in the context of this category
std
::
string
get_unique_id
(
std
::
function
<
std
::
string
(
int
)
>
generator
=
cif
::
cifIdForNumber
);
std
::
string
get_unique_id
(
const
std
::
string
&
prefix
)
{
return
get_unique_id
([
prefix
](
int
nr
)
{
return
prefix
+
std
::
to_string
(
nr
+
1
);
});
}
// --------------------------------------------------------------------
/// \brief Rename a single column 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
/// and unique. If they are not, the child category rows are split.
void
update_value
(
condition
&&
cond
,
std
::
string_view
tag
,
std
::
string_view
value
)
{
auto
rs
=
find
(
std
::
move
(
cond
));
std
::
vector
<
row_handle
>
rows
;
std
::
copy
(
rs
.
begin
(),
rs
.
end
(),
std
::
back_inserter
(
rows
));
update_value
(
rows
,
tag
,
value
);
}
void
update_value
(
const
std
::
vector
<
row_handle
>
&
rows
,
std
::
string_view
tag
,
std
::
string_view
value
);
// --------------------------------------------------------------------
/// \brief Return the index number for \a column_name
uint16_t
get_column_ix
(
std
::
string_view
column_name
)
const
...
...
@@ -573,6 +601,8 @@ class category
}
}
row_handle
create_copy
(
row_handle
r
);
struct
item_column
{
std
::
string
m_name
;
...
...
@@ -607,6 +637,7 @@ class category
const
category_validator
*
m_cat_validator
=
nullptr
;
std
::
vector
<
link
>
m_parent_links
,
m_child_links
;
bool
m_cascade
=
true
;
uint32_t
m_last_unique_num
=
0
;
class
category_index
*
m_index
=
nullptr
;
row
*
m_head
=
nullptr
,
*
m_tail
=
nullptr
;
};
...
...
include/cif++/v2/item.hpp
View file @
a855f880
...
...
@@ -452,8 +452,9 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_same_v<T, std::str
{
static
std
::
string
convert
(
const
item_handle
&
ref
)
{
std
::
string_view
txt
=
ref
.
text
();
return
{
txt
.
data
(),
txt
.
size
()};
if
(
ref
.
empty
())
return
{};
return
{
ref
.
text
().
data
(),
ref
.
text
().
size
()};
}
static
int
compare
(
const
item_handle
&
ref
,
const
std
::
string
&
value
,
bool
icase
)
...
...
include/cif++/v2/validate.hpp
View file @
a855f880
...
...
@@ -31,16 +31,10 @@
// duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
// #include <regex>
// TODO: get rid of boost::iostreams
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/regex.hpp>
#include <cif++/CifUtils.hpp>
namespace
io
=
boost
::
iostreams
;
namespace
cif
::
v2
{
...
...
src/Cif++.cpp
View file @
a855f880
...
...
@@ -38,9 +38,8 @@
#include <filesystem>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <gzstream/gzstream.hpp>
#include <boost/logic/tribool.hpp>
#include <cif++/Cif++.hpp>
...
...
@@ -48,8 +47,6 @@
#include <cif++/CifUtils.hpp>
#include <cif++/CifValidator.hpp>
namespace
ba
=
boost
::
algorithm
;
namespace
io
=
boost
::
iostreams
;
namespace
fs
=
std
::
filesystem
;
namespace
cif
...
...
@@ -622,10 +619,10 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB)
while
(
catA_i
!=
catA
.
end
()
and
catB_i
!=
catB
.
end
())
{
std
::
string
nA
=
*
catA_i
;
ba
::
to_l
ower
(
nA
);
toL
ower
(
nA
);
std
::
string
nB
=
*
catB_i
;
ba
::
to_l
ower
(
nB
);
toL
ower
(
nB
);
int
d
=
nA
.
compare
(
nB
);
if
(
d
>
0
)
...
...
@@ -654,11 +651,11 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB)
{
std
::
cerr
<<
"compare of datablocks failed"
<<
std
::
endl
;
if
(
not
missingA
.
empty
())
std
::
cerr
<<
"Categories missing in A: "
<<
ba
::
join
(
missingA
,
", "
)
<<
std
::
endl
std
::
cerr
<<
"Categories missing in A: "
<<
cif
::
join
(
missingA
,
", "
)
<<
std
::
endl
<<
std
::
endl
;
if
(
not
missingB
.
empty
())
std
::
cerr
<<
"Categories missing in B: "
<<
ba
::
join
(
missingB
,
", "
)
<<
std
::
endl
std
::
cerr
<<
"Categories missing in B: "
<<
cif
::
join
(
missingB
,
", "
)
<<
std
::
endl
<<
std
::
endl
;
result
=
false
;
...
...
@@ -673,10 +670,10 @@ bool operator==(const cif::Datablock &dbA, const cif::Datablock &dbB)
while
(
catA_i
!=
catA
.
end
()
and
catB_i
!=
catB
.
end
())
{
std
::
string
nA
=
*
catA_i
;
ba
::
to_l
ower
(
nA
);
toL
ower
(
nA
);
std
::
string
nB
=
*
catB_i
;
ba
::
to_l
ower
(
nB
);
toL
ower
(
nB
);
int
d
=
nA
.
compare
(
nB
);
if
(
d
>
0
)
...
...
@@ -2156,7 +2153,7 @@ bool Category::isValid()
if
(
not
mandatory
.
empty
())
{
mValidator
->
reportError
(
"In Category "
+
mName
+
" the following mandatory fields are missing: "
+
ba
::
join
(
mandatory
,
", "
),
false
);
mValidator
->
reportError
(
"In Category "
+
mName
+
" the following mandatory fields are missing: "
+
cif
::
join
(
mandatory
,
", "
),
false
);
result
=
false
;
}
...
...
@@ -2447,12 +2444,12 @@ namespace detail
{
if
(
value
.
find
(
'\n'
)
!=
std
::
string
::
npos
or
width
==
0
or
value
.
length
()
>
132
)
// write as text field
{
ba
::
replace_all
(
value
,
"
\n
;"
,
"
\n\\
;"
);
cif
::
replace_all
(
value
,
"
\n
;"
,
"
\n\\
;"
);
if
(
offset
>
0
)
os
<<
std
::
endl
;
os
<<
';'
<<
value
;
if
(
not
ba
::
ends_with
(
value
,
"
\n
"
))
if
(
not
cif
::
ends_with
(
value
,
"
\n
"
))
os
<<
std
::
endl
;
os
<<
';'
<<
std
::
endl
;
offset
=
0
;
...
...
@@ -3451,48 +3448,50 @@ void File::load(const std::filesystem::path &p)
{
fs
::
path
path
(
p
);
std
::
ifstream
inFile
(
p
,
std
::
ios_base
::
in
|
std
::
ios_base
::
binary
);
if
(
not
inFile
.
is_open
())
throw
std
::
runtime_error
(
"Could not open file: "
+
path
.
string
());
io
::
filtering_stream
<
io
::
input
>
in
;
std
::
string
ext
;
if
(
path
.
extension
()
==
".gz"
)
{
in
.
push
(
io
::
gzip_decompressor
());
ext
=
path
.
stem
().
extension
().
string
();
}
in
.
push
(
inFile
);
gzstream
::
ifstream
in
(
p
);
try
{
load
(
in
);
try
{
load
(
in
);
}
catch
(
const
std
::
exception
&
ex
)
{
if
(
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Error loading file "
<<
path
<<
std
::
endl
;
throw
;
}
}
catch
(
const
std
::
exception
&
ex
)
else
{
if
(
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Error loading file "
<<
path
<<
std
::
endl
;
throw
;
std
::
ifstream
inFile
(
p
,
std
::
ios_base
::
in
|
std
::
ios_base
::
binary
);
try
{
load
(
inFile
);
}
catch
(
const
std
::
exception
&
ex
)
{
if
(
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Error loading file "
<<
path
<<
std
::
endl
;
throw
;
}
}
}
void
File
::
save
(
const
std
::
filesystem
::
path
&
p
)
{
fs
::
path
path
(
p
);
std
::
ofstream
outFile
(
p
,
std
::
ios_base
::
out
|
std
::
ios_base
::
binary
);
io
::
filtering_stream
<
io
::
output
>
out
;
if
(
path
.
extension
()
==
".gz"
)
if
(
p
.
extension
()
==
".gz"
)
{
out
.
push
(
io
::
gzip_compressor
());
path
=
path
.
stem
();
gzstream
::
ofstream
outFile
(
p
);
save
(
outFile
);
}
else
{
std
::
ofstream
outFile
(
p
,
std
::
ios_base
::
out
|
std
::
ios_base
::
binary
);
save
(
outFile
);
}
out
.
push
(
outFile
);
save
(
out
);
}
void
File
::
load
(
std
::
istream
&
is
)
...
...
@@ -3534,14 +3533,16 @@ void File::load(const char *data, std::size_t length)
membuf
(
char
*
data
,
size_t
length
)
{
this
->
setg
(
data
,
data
,
data
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
data
),
length
);
std
::
istream
is
(
&
buffer
);
io
::
filtering_stream
<
io
::
input
>
in
;
if
(
gzipped
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
is
);
load
(
is
);
{
gzstream
::
istream
is
(
&
buffer
);
load
(
is
);
}
else
{
std
::
istream
is
(
&
buffer
);
load
(
is
);
}
}
void
File
::
save
(
std
::
ostream
&
os
)
...
...
src/Cif2PDB.cpp
View file @
a855f880
This diff is collapsed.
Click to expand it.
src/CifParser.cpp
View file @
a855f880
...
...
@@ -26,14 +26,10 @@
#include <set>
#include <boost/algorithm/string.hpp>
#include <cif++/Cif++.hpp>
#include <cif++/CifParser.hpp>
#include <cif++/CifValidator.hpp>
namespace
ba
=
boost
::
algorithm
;
extern
int
VERBOSE
;
namespace
cif
...
...
@@ -1300,9 +1296,9 @@ bool DictParser::collectItemTypes()
std
::
string
code
,
primitiveCode
,
construct
;
cif
::
tie
(
code
,
primitiveCode
,
construct
)
=
t
.
get
(
"code"
,
"primitive_code"
,
"construct"
);
ba
::
replace_all
(
construct
,
"
\\
n"
,
"
\n
"
);
ba
::
replace_all
(
construct
,
"
\\
t"
,
"
\t
"
);
ba
::
replace_all
(
construct
,
"
\\\n
"
,
""
);
cif
::
replace_all
(
construct
,
"
\\
n"
,
"
\n
"
);
cif
::
replace_all
(
construct
,
"
\\
t"
,
"
\t
"
);
cif
::
replace_all
(
construct
,
"
\\\n
"
,
""
);
try
{
...
...
src/CifUtils.cpp
View file @
a855f880
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 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
...
...
@@ -25,6 +25,7 @@
*/
#include <atomic>
#include <cassert>
#include <cmath>
#include <fstream>
#include <iomanip>
...
...
@@ -42,13 +43,10 @@
#include <termios.h>
#endif
#include <boost/algorithm/string.hpp>
#include <cif++/CifUtils.hpp>
#include "revision.hpp"
namespace
ba
=
boost
::
algorithm
;
namespace
fs
=
std
::
filesystem
;
// --------------------------------------------------------------------
...
...
@@ -96,7 +94,7 @@ bool iequals(std::string_view a, std::string_view b)
bool
result
=
a
.
length
()
==
b
.
length
();
for
(
auto
ai
=
a
.
begin
(),
bi
=
b
.
begin
();
result
and
ai
!=
a
.
end
();
++
ai
,
++
bi
)
result
=
kCharToLowerMap
[
uint8_t
(
*
ai
)]
==
kCharToLowerMap
[
uint8_t
(
*
bi
)];
// result = tolower(*ai) == tolower(*bi);
// result = tolower(*ai) == tolower(*bi);
return
result
;
}
...
...
@@ -152,7 +150,7 @@ void toLower(std::string &s)
c
=
tolower
(
c
);
}
std
::
string
toLowerCopy
(
const
std
::
string
&
s
)
std
::
string
toLowerCopy
(
std
::
string_view
s
)
{
std
::
string
result
(
s
);
for
(
auto
&
c
:
result
)
...
...
@@ -160,6 +158,91 @@ std::string toLowerCopy(const std::string &s)
return
result
;
}
void
toUpper
(
std
::
string
&
s
)
{
for
(
auto
&
c
:
s
)
c
=
toupper
(
c
);
}
void
replace_all
(
std
::
string
&
s
,
std
::
string_view
what
,
std
::
string_view
with
)
{
for
(
std
::
string
::
size_type
p
=
s
.
find
(
what
);
p
!=
std
::
string
::
npos
;
p
=
s
.
find
(
what
,
p
))
s
.
replace
(
p
,
what
.
length
(),
with
);
}
bool
icontains
(
std
::
string_view
s
,
std
::
string_view
q
)
{
return
contains
(
toLowerCopy
(
s
),
toLowerCopy
(
q
));
}
void
trim_right
(
std
::
string
&
s
)
{
auto
e
=
s
.
end
();
while
(
e
!=
s
.
begin
())
{
auto
pe
=
std
::
prev
(
e
);
if
(
not
std
::
isspace
(
*
pe
))
break
;
e
=
pe
;
}
if
(
e
!=
s
.
end
())
s
.
erase
(
e
,
s
.
end
());
}
std
::
string
trim_right_copy
(
std
::
string_view
s
)
{
auto
e
=
s
.
end
();
while
(
e
!=
s
.
begin
())
{
auto
pe
=
std
::
prev
(
e
);
if
(
not
std
::
isspace
(
*
pe
))
break
;
e
=
pe
;
}
return
{
s
.
begin
(),
e
};
}
std
::
string
trim_left_copy
(
std
::
string_view
s
)
{
auto
b
=
s
.
begin
();
while
(
b
!=
s
.
end
())
{
if
(
not
std
::
isspace
(
*
b
))
break
;
b
=
std
::
next
(
b
);
}
return
{
b
,
s
.
end
()};
}
void
trim_left
(
std
::
string
&
s
)
{
auto
b
=
s
.
begin
();
while
(
b
!=
s
.
end
())
{
if
(
not
std
::
isspace
(
*
b
))
break
;
b
=
std
::
next
(
b
);
}
s
.
erase
(
s
.
begin
(),
b
);
}
void
trim
(
std
::
string
&
s
)
{
trim_right
(
s
);
trim_left
(
s
);
}
std
::
string
trim_copy
(
std
::
string_view
s
)
{
return
trim_left_copy
(
trim_right_copy
(
s
));
}
// --------------------------------------------------------------------
std
::
tuple
<
std
::
string
,
std
::
string
>
splitTagName
(
std
::
string_view
tag
)
...
...
@@ -181,7 +264,7 @@ std::tuple<std::string, std::string> splitTagName(std::string_view tag)
std
::
string
cifIdForNumber
(
int
number
)
{
std
::
string
result
;
if
(
number
>=
26
*
26
*
26
)
result
=
'L'
+
std
::
to_string
(
number
);
else
...
...
@@ -192,17 +275,17 @@ std::string cifIdForNumber(int number)
result
+=
char
(
'A'
-
1
+
v
);
number
%=
(
26
*
26
);
}
if
(
number
>=
26
)
{
int
v
=
number
/
26
;
result
+=
char
(
'A'
-
1
+
v
);
number
%=
26
;
}
result
+=
char
(
'A'
+
number
);
}
assert
(
not
result
.
empty
());
return
result
;
}
...
...
@@ -433,11 +516,8 @@ std::vector<std::string> wrapLine(const std::string &text, size_t width)
std
::
vector
<
std
::
string
>
wordWrap
(
const
std
::
string
&
text
,
size_t
width
)
{
std
::
vector
<
std
::
string
>
paragraphs
;
ba
::
split
(
paragraphs
,
text
,
ba
::
is_any_of
(
"
\n
"
));
std
::
vector
<
std
::
string
>
result
;
for
(
auto
&
p
:
paragraphs
)
for
(
auto
p
:
cif
::
split
<
std
::
string
>
(
text
,
"
\n
"
)
)
{
if
(
p
.
empty
())
{
...
...
@@ -482,12 +562,15 @@ std::string GetExecutablePath()
// convert from utf16 to utf8
std
::
wstring_convert
<
std
::
codecvt_utf8
<
wchar_t
>>
conv1
;
std
::
string
u8str
=
conv1
.
to_bytes
(
ws
);
std
::
string
u8str
=
conv1
.
to_bytes
(
ws
);
return
u8str
;
}
#else
#include <limits.h>
uint32_t
get_terminal_width
()
{
uint32_t
result
=
80
;
...
...
@@ -786,9 +869,9 @@ struct rsrc_imp
#if _MSC_VER
extern
"C"
const
mrsrc
::
rsrc_imp
*
gResourceIndexDefault
[
1
]
=
{};
extern
"C"
const
char
*
gResourceDataDefault
[
1
]
=
{};
extern
"C"
const
char
*
gResourceNameDefault
[
1
]
=
{};
extern
"C"
const
mrsrc
::
rsrc_imp
*
gResourceIndexDefault
[
1
]
=
{};
extern
"C"
const
char
*
gResourceDataDefault
[
1
]
=
{};
extern
"C"
const
char
*
gResourceNameDefault
[
1
]
=
{};
extern
"C"
const
mrsrc
::
rsrc_imp
gResourceIndex
[];
extern
"C"
const
char
gResourceData
[];
...
...
@@ -1250,12 +1333,14 @@ class ResourcePool
result
.
reset
(
file
.
release
());
}
}
catch
(...)
{}
catch
(...)
{
}
return
result
;
}
std
::
map
<
std
::
string
,
std
::
filesystem
::
path
>
mLocalResources
;
std
::
map
<
std
::
string
,
std
::
filesystem
::
path
>
mLocalResources
;
std
::
deque
<
fs
::
path
>
mDirs
;
};
...
...
@@ -1301,7 +1386,7 @@ std::unique_ptr<std::istream> ResourcePool::load(fs::path name)
result
.
reset
(
new
mrsrc
::
istream
(
rsrc
));
}
return
result
;
return
result
;
}
// --------------------------------------------------------------------
...
...
src/CifValidator.cpp
View file @
a855f880
...
...
@@ -27,17 +27,13 @@
#include <fstream>
#include <filesystem>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <gzstream/gzstream.hpp>
#include <cif++/Cif++.hpp>
#include <cif++/CifParser.hpp>
#include <cif++/CifValidator.hpp>
namespace
ba
=
boost
::
algorithm
;
namespace
fs
=
std
::
filesystem
;
namespace
io
=
boost
::
iostreams
;
extern
int
VERBOSE
;
...
...
@@ -416,15 +412,11 @@ const Validator &ValidatorFactory::operator[](std::string_view dictionary)
if
(
fs
::
exists
(
p
,
ec
)
and
not
ec
)
{
std
::
ifstream
file
(
p
,
std
::
ios
::
binary
);
gzstream
::
ifstream
file
(
p
);
if
(
not
file
.
is_open
())
throw
std
::
runtime_error
(
"Could not open dictionary ("
+
p
.
string
()
+
")"
);
io
::
filtering_stream
<
io
::
input
>
in
;
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
file
);
mValidators
.
emplace_back
(
dictionary
,
in
);
mValidators
.
emplace_back
(
dictionary
,
file
);
}
else
throw
std
::
runtime_error
(
"Dictionary not found or defined ("
+
dict_name
.
string
()
+
")"
);
...
...
src/Compound.cpp
View file @
a855f880
...
...
@@ -29,8 +29,6 @@
#include <numeric>
#include <shared_mutex>
#include <boost/algorithm/string.hpp>
#include <filesystem>
#include <fstream>
...
...
@@ -40,7 +38,6 @@
#include <cif++/Compound.hpp>
#include <cif++/Point.hpp>
namespace
ba
=
boost
::
algorithm
;
namespace
fs
=
std
::
filesystem
;
namespace
mmcif
...
...
@@ -126,7 +123,7 @@ Compound::Compound(cif::Datablock &db)
chemComp
.
front
().
get
(
"id"
,
"name"
,
"type"
,
"formula"
,
"formula_weight"
,
"pdbx_formal_charge"
);
// The name should not contain newline characters since that triggers validation errors later on
ba
::
replace_all
(
mName
,
"
\n
"
,
""
);
cif
::
replace_all
(
mName
,
"
\n
"
,
""
);
mGroup
=
"non-polymer"
;
...
...
@@ -286,7 +283,7 @@ class CompoundFactoryImpl : public std::enable_shared_from_this<CompoundFactoryI
{
std
::
shared_lock
lock
(
mMutex
);
ba
::
to_u
pper
(
id
);
cif
::
toU
pper
(
id
);
Compound
*
result
=
nullptr
;
...
...
@@ -554,7 +551,7 @@ CCP4CompoundFactoryImpl::CCP4CompoundFactoryImpl(const fs::path &clibd_mon, std:
{
if
(
std
::
regex_match
(
group
,
peptideRx
))
mKnownPeptides
.
insert
(
threeLetterCode
);
else
if
(
ba
::
iequals
(
group
,
"DNA"
)
or
ba
::
iequals
(
group
,
"RNA"
))
else
if
(
cif
::
iequals
(
group
,
"DNA"
)
or
cif
::
iequals
(
group
,
"RNA"
))
mKnownBases
.
insert
(
threeLetterCode
);
}
}
...
...
@@ -576,10 +573,10 @@ Compound *CCP4CompoundFactoryImpl::create(const std::string &id)
cif
::
tie
(
name
,
group
,
numberAtomsAll
,
numberAtomsNh
)
=
row
.
get
(
"name"
,
"group"
,
"number_atoms_all"
,
"number_atoms_nh"
);
fs
::
path
resFile
=
mCLIBD_MON
/
ba
::
to_lower_c
opy
(
id
.
substr
(
0
,
1
))
/
(
id
+
".cif"
);
fs
::
path
resFile
=
mCLIBD_MON
/
cif
::
toLowerC
opy
(
id
.
substr
(
0
,
1
))
/
(
id
+
".cif"
);
if
(
not
fs
::
exists
(
resFile
)
and
(
id
==
"COM"
or
id
==
"CON"
or
"PRN"
))
// seriously...
resFile
=
mCLIBD_MON
/
ba
::
to_lower_c
opy
(
id
.
substr
(
0
,
1
))
/
(
id
+
'_'
+
id
+
".cif"
);
resFile
=
mCLIBD_MON
/
cif
::
toLowerC
opy
(
id
.
substr
(
0
,
1
))
/
(
id
+
'_'
+
id
+
".cif"
);
if
(
fs
::
exists
(
resFile
))
{
...
...
src/PDB2Cif.cpp
View file @
a855f880
This diff is collapsed.
Click to expand it.
src/PDB2CifRemark3.cpp
View file @
a855f880
...
...
@@ -29,7 +29,6 @@
#include <map>
#include <set>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <cif++/AtomType.hpp>
...
...
@@ -37,8 +36,6 @@
#include <cif++/PDB2CifRemark3.hpp>
#include <cif++/CifUtils.hpp>
namespace
ba
=
boost
::
algorithm
;
using
cif
::
Datablock
;
using
cif
::
Category
;
using
cif
::
Row
;
...
...
@@ -992,7 +989,7 @@ std::string Remark3Parser::nextLine()
while
(
mRec
->
is
(
"REMARK 3"
)
and
mRec
->
mVlen
>
valueIndent
)
{
std
::
string
v
(
mRec
->
mValue
+
4
,
mRec
->
mValue
+
mRec
->
mVlen
);
if
(
not
ba
::
starts_with
(
v
,
indent
))
if
(
not
cif
::
starts_with
(
v
,
indent
))
break
;
mLine
+=
' '
;
...
...
@@ -1146,7 +1143,7 @@ void Remark3Parser::storeCapture(const char* category, std::initializer_list<con
++
capture
;
std
::
string
value
=
mM
[
capture
].
str
();
ba
::
trim
(
value
);
cif
::
trim
(
value
);
if
(
iequals
(
value
,
"NULL"
)
or
iequals
(
value
,
"NONE"
)
or
iequals
(
value
,
"Inf"
)
or
iequals
(
value
,
"+Inf"
)
or
iequals
(
value
,
std
::
string
(
value
.
length
(),
'*'
)))
continue
;
...
...
@@ -1253,7 +1250,7 @@ void Remark3Parser::storeRefineLsRestr(const char* type, std::initializer_list<c
++
capture
;
std
::
string
value
=
mM
[
capture
].
str
();
ba
::
trim
(
value
);
cif
::
trim
(
value
);
if
(
value
.
empty
()
or
iequals
(
value
,
"NULL"
)
or
iequals
(
value
,
"Inf"
)
or
iequals
(
value
,
"+Inf"
)
or
iequals
(
value
,
std
::
string
(
value
.
length
(),
'*'
)))
continue
;
...
...
@@ -1284,7 +1281,7 @@ void Remark3Parser::updateRefineLsRestr(const char* type, std::initializer_list<
++
capture
;
std
::
string
value
=
mM
[
capture
].
str
();
ba
::
trim
(
value
);
cif
::
trim
(
value
);
if
(
iequals
(
value
,
"NULL"
)
or
iequals
(
value
,
std
::
string
(
value
.
length
(),
'*'
)))
value
.
clear
();
...
...
@@ -1385,32 +1382,29 @@ bool Remark3Parser::parse(const std::string& expMethod, PDBRecord* r, cif::Datab
}
};
for
(
auto
p
=
make_split_iterator
(
line
,
ba
::
first_finder
(
", "
));
not
p
.
eof
();
++
p
)
for
(
auto
program
:
cif
::
split
<
std
::
string
>
(
line
,
", "
,
true
))
{
std
::
string
program
(
p
->
begin
(),
p
->
end
());
if
(
ba
::
starts_with
(
program
,
"BUSTER"
))
if
(
cif
::
starts_with
(
program
,
"BUSTER"
))
tryParser
(
new
BUSTER_TNT_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"CNS"
)
or
ba
::
starts_with
(
program
,
"CNX"
))
else
if
(
cif
::
starts_with
(
program
,
"CNS"
)
or
cif
::
starts_with
(
program
,
"CNX"
))
tryParser
(
new
CNS_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"PHENIX"
))
else
if
(
cif
::
starts_with
(
program
,
"PHENIX"
))
tryParser
(
new
PHENIX_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"NUCLSQ"
))
else
if
(
cif
::
starts_with
(
program
,
"NUCLSQ"
))
tryParser
(
new
NUCLSQ_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"PROLSQ"
))
else
if
(
cif
::
starts_with
(
program
,
"PROLSQ"
))
tryParser
(
new
PROLSQ_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"REFMAC"
))
else
if
(
cif
::
starts_with
(
program
,
"REFMAC"
))
{
// simply try both and take the best
tryParser
(
new
REFMAC_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
tryParser
(
new
REFMAC5_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
}
else
if
(
ba
::
starts_with
(
program
,
"SHELXL"
))
else
if
(
cif
::
starts_with
(
program
,
"SHELXL"
))
tryParser
(
new
SHELXL_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"TNT"
))
else
if
(
cif
::
starts_with
(
program
,
"TNT"
))
tryParser
(
new
TNT_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
ba
::
starts_with
(
program
,
"X-PLOR"
))
else
if
(
cif
::
starts_with
(
program
,
"X-PLOR"
))
tryParser
(
new
XPLOR_Remark3Parser
(
program
,
expMethod
,
r
,
db
));
else
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"Skipping unknown program ("
<<
program
<<
") in REMARK 3"
<<
std
::
endl
;
...
...
src/Secondary.cpp
View file @
a855f880
...
...
@@ -30,13 +30,9 @@
#include <numeric>
#include <thread>
#include <boost/algorithm/string.hpp>
#include <cif++/Secondary.hpp>
#include <cif++/Structure.hpp>
namespace
ba
=
boost
::
algorithm
;
// --------------------------------------------------------------------
namespace
mmcif
...
...
@@ -106,7 +102,7 @@ const ResidueInfo kResidueInfo[] = {
ResidueType
MapResidue
(
std
::
string
inName
)
{
ba
::
trim
(
inName
);
cif
::
trim
(
inName
);
ResidueType
result
=
kUnknownResidue
;
...
...
src/Structure.cpp
View file @
a855f880
...
...
@@ -31,9 +31,7 @@
#include <iomanip>
#include <numeric>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <gzstream/gzstream.hpp>
#if __cpp_lib_format
#include <format>
...
...
@@ -47,8 +45,6 @@
// #include <cif++/AtomShape.hpp>
namespace
fs
=
std
::
filesystem
;
namespace
ba
=
boost
::
algorithm
;
namespace
io
=
boost
::
iostreams
;
extern
int
cif
::
VERBOSE
;
...
...
@@ -1289,81 +1285,27 @@ float Branch::weight() const
void
File
::
load
(
const
std
::
filesystem
::
path
&
path
)
{
std
::
ifstream
inFile
(
path
,
std
::
ios_base
::
in
|
std
::
ios_base
::
binary
);
if
(
not
inFile
.
is_open
())
throw
std
::
runtime_error
(
"No such file: "
+
path
.
string
());
io
::
filtering_stream
<
io
::
input
>
in
;
std
::
string
ext
=
path
.
extension
().
string
();
if
(
path
.
extension
()
==
".gz"
)
if
(
ext
==
".gz"
)
{
in
.
push
(
io
::
gzip_decompressor
());
ext
=
path
.
stem
().
extension
().
string
();
}
gzstream
::
ifstream
in
(
path
);
in
.
push
(
inFile
);
ext
=
path
.
stem
().
extension
().
string
(
);
try
{
// OK, we've got the file, now create a protein
if
(
ext
==
".cif"
)
load
(
in
);
else
if
(
ext
==
".pdb"
or
ext
==
".ent"
)
if
(
ext
==
".pdb"
or
ext
==
".ent"
)
ReadPDBFile
(
in
,
*
this
);
else
{
try
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"unrecognized file extension, trying cif"
<<
std
::
endl
;
cif
::
File
::
load
(
in
);
}
catch
(
const
cif
::
CifParserError
&
e
)
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"Not cif, trying plain old PDB"
<<
std
::
endl
;
// pffft...
in
.
reset
();
if
(
inFile
.
is_open
())
inFile
.
seekg
(
0
);
else
inFile
.
open
(
path
,
std
::
ios_base
::
in
|
std
::
ios
::
binary
);
if
(
path
.
extension
()
==
".gz"
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
inFile
);
ReadPDBFile
(
in
,
*
this
);
}
}
cif
::
File
::
load
(
in
);
}
catch
(
const
std
::
exception
&
ex
)
else
{
if
(
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Error trying to load file "
<<
path
<<
std
::
endl
;
throw
;
}
// validate, otherwise lots of functionality won't work
loadDictionary
(
"mmcif_pdbx_v50"
);
if
(
not
isValid
()
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Invalid mmCIF file"
<<
(
cif
::
VERBOSE
>
0
?
"."
:
" use --verbose option to see errors"
)
<<
std
::
endl
;
}
std
::
ifstream
in
(
path
,
std
::
ios_base
::
binary
);
void
File
::
load
(
std
::
istream
&
is
)
{
try
{
cif
::
File
::
load
(
is
);
}
catch
(
const
cif
::
CifParserError
&
e
)
{
ReadPDBFile
(
is
,
*
this
);
if
(
ext
==
".pdb"
or
ext
==
".ent"
)
ReadPDBFile
(
in
,
*
this
);
else
cif
::
File
::
load
(
in
);
}
// validate, otherwise lots of functionality won't work
...
...
@@ -1376,21 +1318,20 @@ void File::save(const std::filesystem::path &path)
{
fs
::
path
file
=
path
.
filename
();
std
::
ofstream
outFile
(
path
,
std
::
ios_base
::
out
|
std
::
ios_base
::
binary
);
io
::
filtering_stream
<
io
::
output
>
out
;
std
::
unique_ptr
<
std
::
ostream
>
outFile
;
if
(
file
.
extension
()
==
".gz"
)
{
out
.
push
(
io
::
gzip_compressor
(
));
out
File
.
reset
(
new
gzstream
::
ofstream
(
path
));
file
.
replace_extension
(
""
);
}
out
.
push
(
outFile
);
else
outFile
.
reset
(
new
std
::
ofstream
(
path
,
std
::
ios_base
::
out
|
std
::
ios_base
::
binary
)
);
if
(
file
.
extension
()
==
".pdb"
)
WritePDBFile
(
out
,
data
());
WritePDBFile
(
*
outFile
,
data
());
else
cif
::
File
::
save
(
out
);
cif
::
File
::
save
(
*
outFile
);
}
// --------------------------------------------------------------------
...
...
src/TlsParser.cpp
View file @
a855f880
...
...
@@ -24,12 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <boost/algorithm/string.hpp>
#include <cif++/TlsParser.hpp>
namespace
ba
=
boost
::
algorithm
;
namespace
cif
{
...
...
@@ -1830,7 +1826,7 @@ TLSSelectionPtr ParseSelectionDetails(const std::string& program, const std::str
TLSSelectionPtr
result
;
if
(
ba
::
icontains
(
program
,
"buster"
))
if
(
cif
::
icontains
(
program
,
"buster"
))
{
result
=
buster
.
Parse
(
selection
);
...
...
@@ -1848,7 +1844,7 @@ TLSSelectionPtr ParseSelectionDetails(const std::string& program, const std::str
result
=
phenix
.
Parse
(
selection
);
}
}
else
if
(
ba
::
icontains
(
program
,
"phenix"
))
else
if
(
cif
::
icontains
(
program
,
"phenix"
))
{
result
=
phenix
.
Parse
(
selection
);
...
...
src/parser.cpp
View file @
a855f880
...
...
@@ -1294,9 +1294,9 @@ bool DictParser::collectItemTypes()
std
::
string
code
,
primitiveCode
,
construct
;
cif
::
tie
(
code
,
primitiveCode
,
construct
)
=
t
.
get
(
"code"
,
"primitive_code"
,
"construct"
);
ba
::
replace_all
(
construct
,
"
\\
n"
,
"
\n
"
);
ba
::
replace_all
(
construct
,
"
\\
t"
,
"
\t
"
);
ba
::
replace_all
(
construct
,
"
\\\n
"
,
""
);
cif
::
replace_all
(
construct
,
"
\\
n"
,
"
\n
"
);
cif
::
replace_all
(
construct
,
"
\\
t"
,
"
\t
"
);
cif
::
replace_all
(
construct
,
"
\\\n
"
,
""
);
try
{
...
...
src/v2/category.cpp
View file @
a855f880
...
...
@@ -34,32 +34,6 @@
namespace
cif
::
v2
{
template
<
typename
V
>
std
::
string
join
(
const
V
&
arr
,
std
::
string_view
sep
)
{
std
::
ostringstream
s
;
if
(
not
arr
.
empty
())
{
auto
ai
=
arr
.
begin
();
auto
ni
=
std
::
next
(
ai
);
for
(;;)
{
s
<<
*
ai
;
ai
=
ni
;
ni
=
std
::
next
(
ai
);
if
(
ni
==
arr
.
end
())
break
;
s
<<
sep
;
}
}
return
s
.
str
();
}
// --------------------------------------------------------------------
class
row_comparator
...
...
@@ -1013,8 +987,13 @@ category::iterator category::erase(iterator pos)
for
(
size_t
ix
=
0
;
ix
<
link
->
m_parent_keys
.
size
();
++
ix
)
{
std
::
string_view
value
=
rh
[
link
->
m_parent_keys
[
ix
]].
text
();
// cond = std::move(cond) and (key(link->m_child_keys[ix]) == value or key(link->m_child_keys[ix]) == null);
cond
=
std
::
move
(
cond
)
and
(
key
(
link
->
m_child_keys
[
ix
])
==
value
);
auto
childKey
=
link
->
m_child_keys
[
ix
];
if
(
childCat
->
m_cat_validator
and
childCat
->
m_cat_validator
->
m_mandatory_fields
.
contains
(
childKey
))
cond
=
std
::
move
(
cond
)
and
key
(
childKey
)
==
value
;
else
cond
=
std
::
move
(
cond
)
and
(
key
(
childKey
)
==
value
or
key
(
childKey
)
==
null
);
}
childCat
->
erase_orphans
(
std
::
move
(
cond
));
...
...
@@ -1133,6 +1112,164 @@ void category::erase_orphans(condition &&cond)
erase
(
iterator
(
*
this
,
r
));
}
std
::
string
category
::
get_unique_id
(
std
::
function
<
std
::
string
(
int
)
>
generator
)
{
using
namespace
cif
::
v2
::
literals
;
std
::
string
id_tag
=
"id"
;
if
(
m_cat_validator
!=
nullptr
and
m_cat_validator
->
m_keys
.
size
()
==
1
)
id_tag
=
m_cat_validator
->
m_keys
.
front
();
// calling size() often is a waste of resources
if
(
m_last_unique_num
==
0
)
m_last_unique_num
=
size
();
for
(;;)
{
std
::
string
result
=
generator
(
static_cast
<
int
>
(
m_last_unique_num
++
));
if
(
exists
(
key
(
id_tag
)
==
result
))
continue
;
return
result
;
}
}
void
category
::
update_value
(
const
std
::
vector
<
row_handle
>
&
rows
,
std
::
string_view
tag
,
std
::
string_view
value
)
{
using
namespace
std
::
literals
;
if
(
rows
.
empty
())
return
;
auto
colIx
=
get_column_ix
(
tag
);
if
(
colIx
>=
m_columns
.
size
())
throw
std
::
runtime_error
(
"Invalid column "
+
std
::
string
{
value
}
+
" for "
+
m_name
);
auto
&
col
=
m_columns
[
colIx
];
// check the value
if
(
col
.
m_validator
)
(
*
col
.
m_validator
)(
value
);
// first some sanity checks, what was the old value and is it the same for all rows?
std
::
string_view
oldValue
=
rows
.
front
()[
tag
].
text
();
for
(
auto
row
:
rows
)
{
if
(
oldValue
!=
row
[
tag
].
text
())
throw
std
::
runtime_error
(
"Inconsistent old values in update_value"
);
}
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
for
(
auto
parent
:
rows
)
{
for
(
auto
&&
[
childCat
,
linked
]
:
m_child_links
)
{
if
(
std
::
find
(
linked
->
m_parent_keys
.
begin
(),
linked
->
m_parent_keys
.
end
(),
tag
)
==
linked
->
m_parent_keys
.
end
())
continue
;
condition
cond
;
std
::
string
childTag
;
for
(
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
];
// TODO: add code to *NOT* test mandatory fields for Empty
if
(
pk
==
tag
)
{
childTag
=
ck
;
cond
=
std
::
move
(
cond
)
&&
key
(
ck
)
==
oldValue
;
}
else
cond
=
std
::
move
(
cond
)
&&
key
(
ck
)
==
parent
[
pk
].
text
();
}
auto
children
=
childCat
->
find
(
std
::
move
(
cond
));
if
(
children
.
empty
())
continue
;
std
::
vector
<
row_handle
>
child_rows
;
std
::
copy
(
children
.
begin
(),
children
.
end
(),
std
::
back_inserter
(
child_rows
));
// now be careful. If we search back from child to parent and still find a valid parent row
// we cannot simply rename the child but will have to create a new child. Unless that new
// child already exists of course.
std
::
vector
<
row_handle
>
process
;
for
(
auto
child
:
child_rows
)
{
condition
cond_c
;
for
(
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
];
// TODO: add code to *NOT* test mandatory fields for Empty
cond_c
=
std
::
move
(
cond_c
)
&&
key
(
pk
)
==
child
[
ck
].
text
();
}
auto
parents
=
find
(
std
::
move
(
cond_c
));
if
(
parents
.
empty
())
{
process
.
push_back
(
child
);
continue
;
}
// 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
)
{
std
::
string
pk
=
linked
->
m_parent_keys
[
ix
];
std
::
string
ck
=
linked
->
m_child_keys
[
ix
];
// TODO: add code to *NOT* test mandatory fields for Empty
if
(
pk
==
tag
)
check
=
std
::
move
(
check
)
&&
key
(
ck
)
==
value
;
else
check
=
std
::
move
(
check
)
&&
key
(
ck
)
==
parent
[
pk
].
text
();
}
if
(
childCat
->
exists
(
std
::
move
(
check
)))
// phew..., narrow escape
continue
;
// create the actual copy, if we can...
if
(
childCat
->
m_cat_validator
!=
nullptr
and
childCat
->
m_cat_validator
->
m_keys
.
size
()
==
1
)
{
auto
copy
=
childCat
->
create_copy
(
child
);
if
(
copy
!=
child
)
{
process
.
push_back
(
child
);
continue
;
}
}
// cannot update this...
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"Cannot update child "
<<
childCat
->
m_name
<<
"."
<<
childTag
<<
" with value "
<<
value
<<
std
::
endl
;
}
// finally, update the children
if
(
not
process
.
empty
())
childCat
->
update_value
(
std
::
move
(
process
),
childTag
,
value
);
}
}
}
void
category
::
update_value
(
row
*
row
,
size_t
column
,
std
::
string_view
value
,
bool
updateLinked
,
bool
validate
)
{
auto
&
col
=
m_columns
[
column
];
...
...
@@ -1235,7 +1372,7 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
std
::
string
pk
=
linked
->
m_parent_keys
[
ix
];
std
::
string
ck
=
linked
->
m_child_keys
[
ix
];
// TODO add code to *NOT* test mandatory fields for Empty
// TODO
:
add code to *NOT* test mandatory fields for Empty
if
(
pk
==
iv
->
m_tag
)
{
...
...
@@ -1272,7 +1409,7 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
std
::
string
pk
=
linked
->
m_parent_keys
[
ix
];
std
::
string
ck
=
linked
->
m_child_keys
[
ix
];
// TODO add code to *NOT* test mandatory fields for Empty
// TODO
:
add code to *NOT* test mandatory fields for Empty
if
(
pk
==
iv
->
m_tag
)
cond_n
=
std
::
move
(
cond_n
)
and
key
(
ck
)
==
value
;
...
...
@@ -1301,6 +1438,40 @@ void category::update_value(row *row, size_t column, std::string_view value, boo
}
}
row_handle
category
::
create_copy
(
row_handle
r
)
{
// copy the values
std
::
vector
<
item
>
items
;
for
(
item_value
*
iv
=
r
.
m_row
->
m_head
;
iv
!=
nullptr
;
iv
=
iv
->
m_next
)
items
.
emplace_back
(
m_columns
[
iv
->
m_column_ix
].
m_name
,
iv
->
text
());
if
(
m_cat_validator
and
m_cat_validator
->
m_keys
.
size
()
==
1
)
{
auto
key
=
m_cat_validator
->
m_keys
.
front
();
auto
kv
=
m_cat_validator
->
get_validator_for_item
(
key
);
for
(
auto
&
item
:
items
)
{
if
(
item
.
name
()
!=
key
)
continue
;
if
(
kv
->
m_type
->
m_primitive_type
==
DDL_PrimitiveType
::
Numb
)
item
.
value
(
get_unique_id
(
""
));
else
item
.
value
(
get_unique_id
(
m_name
+
"_id_"
));
break
;
}
}
return
emplace
(
items
.
begin
(),
items
.
end
());
// auto &&[result, inserted] = emplace(items.begin(), items.end());
// // assert(inserted);
// return result;
}
// proxy methods for every insertion
category
::
iterator
category
::
insert_impl
(
const_iterator
pos
,
row
*
n
)
{
...
...
src/v2/validate.cpp
View file @
a855f880
...
...
@@ -28,6 +28,8 @@
#include <fstream>
#include <iostream>
#include <gzstream/gzstream.hpp>
#include <cif++/v2/dictionary_parser.hpp>
#include <cif++/v2/validate.hpp>
...
...
@@ -407,13 +409,10 @@ const validator &validator_factory::operator[](std::string_view dictionary_name)
if
(
std
::
filesystem
::
exists
(
p
,
ec
)
and
not
ec
)
{
std
::
ifstream
file
(
p
,
std
::
ios
::
binary
);
if
(
not
file
.
is_open
())
throw
std
::
runtime_error
(
"Could not open dictionary ("
+
p
.
string
()
+
")"
);
gzstream
::
ifstream
in
(
p
);
io
::
filtering_stream
<
io
::
input
>
in
;
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
file
);
if
(
not
in
.
is_open
())
throw
std
::
runtime_error
(
"Could not open dictionary ("
+
p
.
string
()
+
")"
);
construct_validator
(
dictionary_name
,
in
);
}
...
...
test/unit-v2-test.cpp
View file @
a855f880
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment